...30import org.openqa.selenium.grid.graphql.GraphqlHandler;31import org.openqa.selenium.grid.log.LoggingOptions;32import org.openqa.selenium.grid.router.ProxyCdpIntoGrid;33import org.openqa.selenium.grid.router.Router;34import org.openqa.selenium.grid.security.BasicAuthenticationFilter;35import org.openqa.selenium.grid.security.Secret;36import org.openqa.selenium.grid.security.SecretOptions;37import org.openqa.selenium.grid.server.BaseServerOptions;38import org.openqa.selenium.grid.server.EventBusOptions;39import org.openqa.selenium.grid.server.NetworkOptions;40import org.openqa.selenium.grid.server.Server;41import org.openqa.selenium.grid.sessionmap.SessionMap;42import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap;43import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;44import org.openqa.selenium.grid.sessionqueue.config.SessionRequestOptions;45import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;46import org.openqa.selenium.grid.web.CombinedHandler;47import org.openqa.selenium.grid.web.GridUiRoute;48import org.openqa.selenium.grid.web.RoutableHttpClientFactory;49import org.openqa.selenium.internal.Require;50import org.openqa.selenium.remote.http.Contents;51import org.openqa.selenium.remote.http.HttpClient;52import org.openqa.selenium.remote.http.HttpHandler;53import org.openqa.selenium.remote.http.HttpResponse;54import org.openqa.selenium.remote.http.Routable;55import org.openqa.selenium.remote.http.Route;56import org.openqa.selenium.remote.tracing.Tracer;57import java.net.MalformedURLException;58import java.net.URL;59import java.util.Collections;60import java.util.Set;61import java.util.logging.Logger;62import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;63import static java.net.HttpURLConnection.HTTP_OK;64import static org.openqa.selenium.grid.config.StandardGridRoles.DISTRIBUTOR_ROLE;65import static org.openqa.selenium.grid.config.StandardGridRoles.EVENT_BUS_ROLE;66import static org.openqa.selenium.grid.config.StandardGridRoles.HTTPD_ROLE;67import static org.openqa.selenium.grid.config.StandardGridRoles.ROUTER_ROLE;68import static org.openqa.selenium.grid.config.StandardGridRoles.SESSION_QUEUE_ROLE;69import static org.openqa.selenium.remote.http.Route.combine;70@AutoService(CliCommand.class)71public class Hub extends TemplateGridServerCommand {72 private static final Logger LOG = Logger.getLogger(Hub.class.getName());73 @Override74 public String getName() {75 return "hub";76 }77 @Override78 public String getDescription() {79 return "A grid hub, composed of sessions, distributor, and router.";80 }81 @Override82 public Set<Role> getConfigurableRoles() {83 return ImmutableSet.of(84 DISTRIBUTOR_ROLE,85 EVENT_BUS_ROLE,86 HTTPD_ROLE,87 SESSION_QUEUE_ROLE,88 ROUTER_ROLE);89 }90 @Override91 public Set<Object> getFlagObjects() {92 return Collections.emptySet();93 }94 @Override95 protected String getSystemPropertiesConfigPrefix() {96 return "selenium";97 }98 @Override99 protected Config getDefaultConfig() {100 return new DefaultHubConfig();101 }102 @Override103 protected Handlers createHandlers(Config config) {104 LoggingOptions loggingOptions = new LoggingOptions(config);105 Tracer tracer = loggingOptions.getTracer();106 EventBusOptions events = new EventBusOptions(config);107 EventBus bus = events.getEventBus();108 CombinedHandler handler = new CombinedHandler();109 SessionMap sessions = new LocalSessionMap(tracer, bus);110 handler.addHandler(sessions);111 BaseServerOptions serverOptions = new BaseServerOptions(config);112 SecretOptions secretOptions = new SecretOptions(config);113 Secret secret = secretOptions.getRegistrationSecret();114 URL externalUrl;115 try {116 externalUrl = serverOptions.getExternalUri().toURL();117 } catch (MalformedURLException e) {118 throw new IllegalArgumentException(e);119 }120 NetworkOptions networkOptions = new NetworkOptions(config);121 HttpClient.Factory clientFactory = new RoutableHttpClientFactory(122 externalUrl,123 handler,124 networkOptions.getHttpClientFactory(tracer));125 DistributorOptions distributorOptions = new DistributorOptions(config);126 SessionRequestOptions sessionRequestOptions = new SessionRequestOptions(config);127 NewSessionQueue queue = new LocalNewSessionQueue(128 tracer,129 bus,130 distributorOptions.getSlotMatcher(),131 sessionRequestOptions.getSessionRequestRetryInterval(),132 sessionRequestOptions.getSessionRequestTimeout(),133 secret);134 handler.addHandler(queue);135 Distributor distributor = new LocalDistributor(136 tracer,137 bus,138 clientFactory,139 sessions,140 queue,141 distributorOptions.getSlotSelector(),142 secret,143 distributorOptions.getHealthCheckInterval(),144 distributorOptions.shouldRejectUnsupportedCaps());145 handler.addHandler(distributor);146 Router router = new Router(tracer, clientFactory, sessions, queue, distributor);147 GraphqlHandler graphqlHandler = new GraphqlHandler(148 tracer,149 distributor,150 queue,151 serverOptions.getExternalUri(),152 getServerVersion());153 HttpHandler readinessCheck = req -> {154 boolean ready = router.isReady() && bus.isReady();155 return new HttpResponse()156 .setStatus(ready ? HTTP_OK : HTTP_INTERNAL_ERROR)157 .setContent(Contents.utf8String("Router is " + ready));158 };159 Routable ui = new GridUiRoute();160 Routable routerWithSpecChecks = router.with(networkOptions.getSpecComplianceChecks());161 Routable httpHandler = combine(162 ui,163 routerWithSpecChecks,164 Route.prefix("/wd/hub").to(combine(routerWithSpecChecks)),165 Route.options("/graphql").to(() -> graphqlHandler),166 Route.post("/graphql").to(() -> graphqlHandler));167 UsernameAndPassword uap = secretOptions.getServerAuthentication();168 if (uap != null) {169 LOG.info("Requiring authentication to connect");170 httpHandler = httpHandler.with(new BasicAuthenticationFilter(uap.username(), uap.password()));171 }172 // Allow the liveness endpoint to be reached, since k8s doesn't make it easy to authenticate these checks173 httpHandler = combine(httpHandler, Route.get("/readyz").to(() -> readinessCheck));174 return new Handlers(httpHandler, new ProxyCdpIntoGrid(clientFactory, sessions));175 }176 @Override177 protected void execute(Config config) {178 Require.nonNull("Config", config);179 Server<?> server = asServer(config).start();180 LOG.info(String.format("Started Selenium Hub %s: %s", getServerVersion(), server.getUrl()));181 }182 private String getServerVersion() {183 BuildInfo info = new BuildInfo();184 return String.format("%s (revision %s)", info.getReleaseLabel(), info.getBuildRevision());...