diff options
Diffstat (limited to 'configserver')
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/serviceview/ConfigServerLocation.java | 38 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java | 259 | ||||
-rw-r--r-- | configserver/src/main/java/com/yahoo/vespa/serviceview/StateResource.java | 253 | ||||
-rw-r--r-- | configserver/src/main/resources/configserver-app/services.xml | 10 | ||||
-rw-r--r-- | configserver/src/test/java/com/yahoo/vespa/serviceview/StateRequestHandlerTest.java (renamed from configserver/src/test/java/com/yahoo/vespa/serviceview/StateResourceTest.java) | 43 |
5 files changed, 283 insertions, 320 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/serviceview/ConfigServerLocation.java b/configserver/src/main/java/com/yahoo/vespa/serviceview/ConfigServerLocation.java deleted file mode 100644 index 05d1119aa4f..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/serviceview/ConfigServerLocation.java +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.serviceview; - -import ai.vespa.util.http.VespaClientBuilderFactory; -import com.google.inject.Inject; -import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.component.AbstractComponent; - -/** - * Wrapper for settings from the cloud.config.configserver config. - * - * @author Steinar Knutsen - */ -public class ConfigServerLocation extends AbstractComponent { - - final int restApiPort; - // The client factory must be owned by a component as StateResource is instantiated per request - @SuppressWarnings("removal") - final VespaClientBuilderFactory clientBuilderFactory = new VespaClientBuilderFactory(); - - @Inject - public ConfigServerLocation(ConfigserverConfig configServer) { - restApiPort = configServer.httpport(); - } - - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("ConfigServerLocation [restApiPort=").append(restApiPort).append("]"); - return builder.toString(); - } - - @Override - public void deconstruct() { - clientBuilderFactory.close(); - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java b/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java new file mode 100644 index 00000000000..38c74b16c1f --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java @@ -0,0 +1,259 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.serviceview; + +import com.google.inject.Inject; +import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.container.jdisc.LoggingRequestHandler; +import com.yahoo.restapi.JacksonJsonResponse; +import com.yahoo.restapi.RestApi; +import com.yahoo.restapi.RestApiRequestHandler; +import com.yahoo.vespa.serviceview.bindings.ApplicationView; +import com.yahoo.vespa.serviceview.bindings.ConfigClient; +import com.yahoo.vespa.serviceview.bindings.HealthClient; +import com.yahoo.vespa.serviceview.bindings.ModelResponse; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.proxy.WebResourceFactory; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.HttpHeaders; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +/** + * A web service to discover and proxy Vespa service state info. + * + * @author Steinar Knutsen + * @author bjorncs + */ +public class StateRequestHandler extends RestApiRequestHandler<StateRequestHandler> { + + private static final String USER_AGENT = "service-view-config-server-client"; + private static final String SINGLE_API_LINK = "url"; + + @SuppressWarnings("removal") + private final Client client = new ai.vespa.util.http.VespaClientBuilderFactory() + .newBuilder() + .property(ClientProperties.CONNECT_TIMEOUT, 10000) + .property(ClientProperties.READ_TIMEOUT, 10000) + .register((ClientRequestFilter) ctx -> ctx.getHeaders().put(HttpHeaders.USER_AGENT, List.of(USER_AGENT))) + .build(); + + private final int restApiPort; + + private static class GiveUpLinkRetargetingException extends Exception { + public GiveUpLinkRetargetingException(Throwable reason) { + super(reason); + } + + public GiveUpLinkRetargetingException(String message) { + super(message); + } + } + + @Inject + public StateRequestHandler(LoggingRequestHandler.Context context, + ConfigserverConfig configserverConfig) { + super(context, StateRequestHandler::createRestApiDefinition); + this.restApiPort = configserverConfig.httpport(); + } + + @Override + protected void destroy() { + client.close(); + super.destroy(); + } + + private static RestApi createRestApiDefinition(StateRequestHandler self) { + return RestApi.builder() + .addRoute(RestApi.route("/serviceview/v1/") + .get(self::getDefaultUserInfo)) + .addRoute(RestApi.route("/serviceview/v1/tenant/{tenantName}/application/{applicationName}/environment/{environmentName}/region/{regionName}/instance/{instanceName}") + .get(self::getUserInfo)) + .addRoute(RestApi.route("/serviceview/v1/tenant/{tenantName}/application/{applicationName}/environment/{environmentName}/region/{regionName}/instance/{instanceName}/service/{serviceIdentifier}/{*}") + .get(self::singleService)) + .addResponseMapper(HashMap.class, (hashMap, context) -> new JacksonJsonResponse<>(200, hashMap, true)) + .addResponseMapper(ApplicationView.class, (applicationView, context) -> new JacksonJsonResponse<>(200, applicationView, true)) + .build(); + } + + private ApplicationView getDefaultUserInfo(RestApi.RequestContext context) { + return getUserInfo(context.request().getUri(), "default", "default", "default", "default", "default"); + } + + private ApplicationView getUserInfo(RestApi.RequestContext context) { + String tenantName = context.pathParameters().getStringOrThrow("tenantName"); + String applicationName = context.pathParameters().getStringOrThrow("applicationName"); + String environmentName = context.pathParameters().getStringOrThrow("environmentName"); + String regionName = context.pathParameters().getStringOrThrow("regionName"); + String instanceName = context.pathParameters().getStringOrThrow("instanceName"); + return getUserInfo(context.request().getUri(), tenantName, applicationName, environmentName, regionName, instanceName); + } + + public HashMap<?, ?> singleService(RestApi.RequestContext context) { + String tenantName = context.pathParameters().getStringOrThrow("tenantName"); + String applicationName = context.pathParameters().getStringOrThrow("applicationName"); + String environmentName = context.pathParameters().getStringOrThrow("environmentName"); + String regionName = context.pathParameters().getStringOrThrow("regionName"); + String instanceName = context.pathParameters().getStringOrThrow("instanceName"); + String identifier = context.pathParameters().getStringOrThrow("serviceIdentifier"); + String apiParams = context.pathParameters().getString("*").orElse(""); + return singleService(context.request().getUri(), tenantName, applicationName, environmentName, regionName, instanceName, identifier, apiParams); + } + + protected ApplicationView getUserInfo(URI requestUri, String tenantName, String applicationName, String environmentName, String regionName, String instanceName) { + ServiceModel model = new ServiceModel( + getModelConfig(tenantName, applicationName, environmentName, regionName, instanceName)); + return model.showAllClusters( + baseUri(requestUri).toString(), + applicationIdentifier(tenantName, applicationName, environmentName, regionName, instanceName)); + } + + protected ModelResponse getModelConfig(String tenant, String application, String environment, String region, String instance) { + try { + WebTarget target = client.target("http://localhost:" + restApiPort + "/"); + ConfigClient resource = WebResourceFactory.newResource(ConfigClient.class, target); + return resource.getServiceModel(tenant, application, environment, region, instance); + } finally { + client.close(); + } + } + + protected HashMap<?, ?> singleService( + URI requestUri, String tenantName, String applicationName, String environmentName, String regionName, String instanceName, String identifier, String apiParams) { + ServiceModel model = new ServiceModel(getModelConfig(tenantName, applicationName, environmentName, regionName, instanceName)); + Service s = model.getService(identifier); + int requestedPort = s.matchIdentifierWithPort(identifier); + try { + HealthClient resource = getHealthClient(apiParams, s, requestedPort, requestUri.getRawQuery(), client); + HashMap<?, ?> apiResult = resource.getHealthInfo(); + rewriteResourceLinks(requestUri, apiResult, model, s, applicationIdentifier(tenantName, applicationName, environmentName, regionName, instanceName), identifier); + return apiResult; + } finally { + client.close(); + } + } + + protected HealthClient getHealthClient(String apiParams, Service s, int requestedPort, String uriQuery, Client client) { + final StringBuilder uriBuffer = new StringBuilder("http://").append(s.host).append(':').append(requestedPort).append('/') + .append(apiParams); + addQuery(uriQuery, uriBuffer); + WebTarget target = client.target(uriBuffer.toString()); + return WebResourceFactory.newResource(HealthClient.class, target); + } + + private String applicationIdentifier(String tenant, String application, String environment, String region, String instance) { + return "tenant/" + tenant + + "/application/" + application + + "/environment/" + environment + + "/region/" + region + + "/instance/" + instance; + } + + private void rewriteResourceLinks(URI requestUri, + Object apiResult, + ServiceModel model, + Service self, + String applicationIdentifier, + String incomingIdentifier) { + if (apiResult instanceof List) { + for (@SuppressWarnings("unchecked") ListIterator<Object> i = ((List<Object>) apiResult).listIterator(); i.hasNext();) { + Object resource = i.next(); + if (resource instanceof String) { + try { + StringBuilder buffer = linkBuffer(requestUri, applicationIdentifier); + // if it points to a port and host not part of the application, rewriting will not occur, so this is kind of safe + retarget(model, self, buffer, (String) resource); + i.set(buffer.toString()); + } catch (GiveUpLinkRetargetingException e) { + break; // assume relatively homogenous lists when doing rewrites to avoid freezing up on scanning long lists + } + } else { + rewriteResourceLinks(requestUri, resource, model, self, applicationIdentifier, incomingIdentifier); + } + } + } else if (apiResult instanceof Map) { + @SuppressWarnings("unchecked") + Map<Object, Object> api = (Map<Object, Object>) apiResult; + for (Map.Entry<Object, Object> entry : api.entrySet()) { + if (SINGLE_API_LINK.equals(entry.getKey()) && entry.getValue() instanceof String) { + try { + rewriteSingleLink(entry, model, self, linkBuffer(requestUri, applicationIdentifier)); + } catch (GiveUpLinkRetargetingException e) { + // NOP + } + } else if ("link".equals(entry.getKey()) && entry.getValue() instanceof String) { + buildSingleLink(entry, linkBuffer(requestUri, applicationIdentifier), incomingIdentifier); + } else { + rewriteResourceLinks(requestUri, entry.getValue(), model, self, applicationIdentifier, incomingIdentifier); + } + } + } + } + + private void buildSingleLink(Map.Entry<Object, Object> entry, + StringBuilder newUri, + String incomingIdentifier) { + newUri.append("/service/") + .append(incomingIdentifier); + newUri.append(entry.getValue()); + entry.setValue(newUri.toString()); + } + + private void addQuery(String query, StringBuilder newUri) { + if (query != null && query.length() > 0) { + newUri.append('?').append(query); + } + } + + private StringBuilder linkBuffer(URI requestUri, String applicationIdentifier) { + return baseUri(requestUri).append(applicationIdentifier); + } + + private void rewriteSingleLink(Map.Entry<Object, Object> entry, + ServiceModel model, + Service self, + StringBuilder newUri) throws GiveUpLinkRetargetingException { + String url = (String) entry.getValue(); + retarget(model, self, newUri, url); + entry.setValue(newUri.toString()); + } + + private void retarget(ServiceModel model, Service self, StringBuilder newUri, String url) throws GiveUpLinkRetargetingException { + URI link; + try { + link = new URI(url); + } catch (URISyntaxException e) { + throw new GiveUpLinkRetargetingException(e); + } + if (!link.isAbsolute()) { + throw new GiveUpLinkRetargetingException("This rewriting only supports absolute URIs."); + } + int linkPort = link.getPort(); + if (linkPort == -1) { + linkPort = 80; + } + Service s; + try { + s = model.resolve(link.getHost(), linkPort, self); + } catch (IllegalArgumentException e) { + throw new GiveUpLinkRetargetingException(e); + } + newUri.append("/service/").append(s.getIdentifier(linkPort)); + newUri.append(link.getRawPath()); + } + + private static StringBuilder baseUri(URI requestUri) { + return new StringBuilder(requestUri.getScheme()) + .append("://") + .append(requestUri.getHost()) + .append(':') + .append(requestUri.getPort()) + .append("/serviceview/v1/"); + } +} diff --git a/configserver/src/main/java/com/yahoo/vespa/serviceview/StateResource.java b/configserver/src/main/java/com/yahoo/vespa/serviceview/StateResource.java deleted file mode 100644 index 138e6c8798c..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/serviceview/StateResource.java +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.serviceview; - -import ai.vespa.util.http.VespaClientBuilderFactory; -import com.yahoo.container.jaxrs.annotation.Component; -import com.yahoo.vespa.serviceview.bindings.ApplicationView; -import com.yahoo.vespa.serviceview.bindings.ConfigClient; -import com.yahoo.vespa.serviceview.bindings.HealthClient; -import com.yahoo.vespa.serviceview.bindings.ModelResponse; -import com.yahoo.vespa.serviceview.bindings.StateClient; -import org.glassfish.jersey.client.proxy.WebResourceFactory; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriInfo; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - - -/** - * A web service to discover and proxy Vespa service state info. - * - * @author Steinar Knutsen - */ -@Path("/") -public class StateResource implements StateClient { - - private static final String USER_AGENT = "service-view-config-server-client"; - private static final String SINGLE_API_LINK = "url"; - - @SuppressWarnings("removal") - private final VespaClientBuilderFactory clientBuilderFactory; - private final int restApiPort; - private final String host; - private final UriInfo uriInfo; - - @SuppressWarnings("serial") - private static class GiveUpLinkRetargetingException extends Exception { - public GiveUpLinkRetargetingException(Throwable reason) { - super(reason); - } - - public GiveUpLinkRetargetingException(String message) { - super(message); - } - } - - public StateResource(@Component ConfigServerLocation configServer, @Context UriInfo ui) { - this.clientBuilderFactory = configServer.clientBuilderFactory; - this.restApiPort = configServer.restApiPort; - this.host = "localhost"; - this.uriInfo = ui; - } - - @Override - @GET - @Path("v1/") - @Produces(MediaType.APPLICATION_JSON) - public ApplicationView getDefaultUserInfo() { - return getUserInfo("default", "default", "default", "default", "default"); - } - - @Override - @GET - @Path("v1/tenant/{tenantName}/application/{applicationName}/environment/{environmentName}/region/{regionName}/instance/{instanceName}") - @Produces(MediaType.APPLICATION_JSON) - public ApplicationView getUserInfo(@PathParam("tenantName") String tenantName, - @PathParam("applicationName") String applicationName, - @PathParam("environmentName") String environmentName, - @PathParam("regionName") String regionName, - @PathParam("instanceName") String instanceName) { - ServiceModel model = new ServiceModel( - getModelConfig(tenantName, applicationName, environmentName, regionName, instanceName)); - return model.showAllClusters( - getBaseUri() + "v1/", - applicationIdentifier(tenantName, applicationName, environmentName, regionName, instanceName)); - } - - private String getBaseUri() { - String baseUri = uriInfo.getBaseUri().toString(); - if (baseUri.endsWith("/")) { - return baseUri; - } else { - return baseUri + "/"; - } - } - - protected ModelResponse getModelConfig(String tenant, String application, String environment, String region, String instance) { - Client client = client(); - try { - WebTarget target = client.target("http://" + host + ":" + restApiPort + "/"); - ConfigClient resource = WebResourceFactory.newResource(ConfigClient.class, target); - return resource.getServiceModel(tenant, application, environment, region, instance); - } finally { - client.close(); - } - } - - @SuppressWarnings("rawtypes") - @Override - @GET - @Path("v1/tenant/{tenantName}/application/{applicationName}/environment/{environmentName}/region/{regionName}/instance/{instanceName}/service/{serviceIdentifier}/{apiParams: .*}") - @Produces(MediaType.APPLICATION_JSON) - public HashMap singleService(@PathParam("tenantName") String tenantName, - @PathParam("applicationName") String applicationName, - @PathParam("environmentName") String environmentName, - @PathParam("regionName") String regionName, - @PathParam("instanceName") String instanceName, - @PathParam("serviceIdentifier") String identifier, - @PathParam("apiParams") String apiParams) { - ServiceModel model = new ServiceModel(getModelConfig(tenantName, applicationName, environmentName, regionName, instanceName)); - Service s = model.getService(identifier); - int requestedPort = s.matchIdentifierWithPort(identifier); - Client client = client(); - try { - HealthClient resource = getHealthClient(apiParams, s, requestedPort, client); - HashMap<?, ?> apiResult = resource.getHealthInfo(); - rewriteResourceLinks(apiResult, model, s, applicationIdentifier(tenantName, applicationName, environmentName, regionName, instanceName), identifier); - return apiResult; - } finally { - client.close(); - } - } - - protected HealthClient getHealthClient(String apiParams, Service s, int requestedPort, Client client) { - final StringBuilder uriBuffer = new StringBuilder("http://").append(s.host).append(':').append(requestedPort).append('/') - .append(apiParams); - addQuery(uriBuffer); - WebTarget target = client.target(uriBuffer.toString()); - return WebResourceFactory.newResource(HealthClient.class, target); - } - - private String applicationIdentifier(String tenant, String application, String environment, String region, String instance) { - return "tenant/" + tenant - + "/application/" + application - + "/environment/" + environment - + "/region/" + region - + "/instance/" + instance; - } - - private void rewriteResourceLinks(Object apiResult, - ServiceModel model, - Service self, - String applicationIdentifier, - String incomingIdentifier) { - if (apiResult instanceof List) { - for (@SuppressWarnings("unchecked") ListIterator<Object> i = ((List<Object>) apiResult).listIterator(); i.hasNext();) { - Object resource = i.next(); - if (resource instanceof String) { - try { - StringBuilder buffer = linkBuffer(applicationIdentifier); - // if it points to a port and host not part of the application, rewriting will not occur, so this is kind of safe - retarget(model, self, buffer, (String) resource); - i.set(buffer.toString()); - } catch (GiveUpLinkRetargetingException e) { - break; // assume relatively homogenous lists when doing rewrites to avoid freezing up on scanning long lists - } - } else { - rewriteResourceLinks(resource, model, self, applicationIdentifier, incomingIdentifier); - } - } - } else if (apiResult instanceof Map) { - @SuppressWarnings("unchecked") - Map<Object, Object> api = (Map<Object, Object>) apiResult; - for (Map.Entry<Object, Object> entry : api.entrySet()) { - if (SINGLE_API_LINK.equals(entry.getKey()) && entry.getValue() instanceof String) { - try { - rewriteSingleLink(entry, model, self, linkBuffer(applicationIdentifier)); - } catch (GiveUpLinkRetargetingException e) { - // NOP - } - } else if ("link".equals(entry.getKey()) && entry.getValue() instanceof String) { - buildSingleLink(entry, linkBuffer(applicationIdentifier), incomingIdentifier); - } else { - rewriteResourceLinks(entry.getValue(), model, self, applicationIdentifier, incomingIdentifier); - } - } - } - } - - private void buildSingleLink(Map.Entry<Object, Object> entry, - StringBuilder newUri, - String incomingIdentifier) { - newUri.append("/service/") - .append(incomingIdentifier); - newUri.append(entry.getValue()); - entry.setValue(newUri.toString()); - } - - private void addQuery(StringBuilder newUri) { - String query = uriInfo.getRequestUri().getRawQuery(); - if (query != null && query.length() > 0) { - newUri.append('?').append(query); - } - } - - private StringBuilder linkBuffer(String applicationIdentifier) { - StringBuilder newUri = new StringBuilder(getBaseUri()); - newUri.append("v1/").append(applicationIdentifier); - return newUri; - } - - private void rewriteSingleLink(Map.Entry<Object, Object> entry, - ServiceModel model, - Service self, - StringBuilder newUri) throws GiveUpLinkRetargetingException { - String url = (String) entry.getValue(); - retarget(model, self, newUri, url); - entry.setValue(newUri.toString()); - } - - private void retarget(ServiceModel model, Service self, StringBuilder newUri, String url) throws GiveUpLinkRetargetingException { - URI link; - try { - link = new URI(url); - } catch (URISyntaxException e) { - throw new GiveUpLinkRetargetingException(e); - } - if (!link.isAbsolute()) { - throw new GiveUpLinkRetargetingException("This rewriting only supports absolute URIs."); - } - int linkPort = link.getPort(); - if (linkPort == -1) { - linkPort = 80; - } - Service s; - try { - s = model.resolve(link.getHost(), linkPort, self); - } catch (IllegalArgumentException e) { - throw new GiveUpLinkRetargetingException(e); - } - newUri.append("/service/").append(s.getIdentifier(linkPort)); - newUri.append(link.getRawPath()); - } - - private Client client() { - return clientBuilderFactory.newBuilder() - .register((ClientRequestFilter) ctx -> ctx.getHeaders().put(HttpHeaders.USER_AGENT, List.of(USER_AGENT))) - .build(); - } -} diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml index a4ca7081f0b..cfff3719d6e 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -69,12 +69,10 @@ <components bundle="orchestrator" /> </rest-api> - <rest-api path="serviceview" jersey2="true"> - <components bundle="configserver"> - <package>com.yahoo.vespa.serviceview</package> - </components> - </rest-api> - + <handler id="com.yahoo.vespa.serviceview.StateRequestHandler" bundle="configserver"> + <binding>http://*/serviceview/v1/</binding> + <binding>http://*/serviceview/v1/*</binding> + </handler> <handler id='com.yahoo.vespa.config.server.http.HttpGetConfigHandler' bundle='configserver'> <binding>http://*/config/v1/*/*</binding> <binding>http://*/config/v1/*</binding> diff --git a/configserver/src/test/java/com/yahoo/vespa/serviceview/StateResourceTest.java b/configserver/src/test/java/com/yahoo/vespa/serviceview/StateRequestHandlerTest.java index 794b825db6e..a0bb8a5acc7 100644 --- a/configserver/src/test/java/com/yahoo/vespa/serviceview/StateResourceTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/serviceview/StateRequestHandlerTest.java @@ -2,7 +2,7 @@ package com.yahoo.vespa.serviceview; import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.container.jaxrs.annotation.Component; +import com.yahoo.jdisc.test.MockMetric; import com.yahoo.vespa.serviceview.bindings.ApplicationView; import com.yahoo.vespa.serviceview.bindings.HealthClient; import com.yahoo.vespa.serviceview.bindings.ModelResponse; @@ -12,30 +12,30 @@ import org.junit.Test; import org.mockito.Mockito; import javax.ws.rs.client.Client; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.UriInfo; import java.net.URI; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; import static org.junit.Assert.assertEquals; /** - * Functional test for {@link StateResource}. + * Functional test for {@link StateRequestHandler}. * * @author Steinar Knutsen + * @author bjorncs */ -public class StateResourceTest { +public class StateRequestHandlerTest { - private static final String EXTERNAL_BASE_URI = "http://someserver:8080/serviceview/"; + private static final String EXTERNAL_BASE_URI = "http://someserver:8080/serviceview/v1/"; - private static class TestResource extends StateResource { + private static class TestHandler extends StateRequestHandler { private static final String BASE_URI = "http://vespa.yahoo.com:8080/state/v1"; - TestResource(@Component ConfigServerLocation configServer, @Context UriInfo ui) { - super(configServer, ui); + TestHandler(ConfigserverConfig config) { + super(new Context(Executors.newSingleThreadExecutor(), new MockMetric()), config); } @Override @@ -44,7 +44,7 @@ public class StateResourceTest { } @Override - protected HealthClient getHealthClient(String apiParams, Service s, int requestedPort, Client client) { + protected HealthClient getHealthClient(String apiParams, Service s, int requestedPort, String uriQuery, Client client) { HealthClient healthClient = Mockito.mock(HealthClient.class); HashMap<Object, Object> dummyHealthData = new HashMap<>(); HashMap<String, String> dummyLink = new HashMap<>(); @@ -55,39 +55,36 @@ public class StateResourceTest { } } - private StateResource testResource; + private StateRequestHandler testHandler; private ServiceModel correspondingModel; @Before public void setUp() throws Exception { - UriInfo base = Mockito.mock(UriInfo.class); - Mockito.when(base.getBaseUri()).thenReturn(new URI(EXTERNAL_BASE_URI)); - ConfigServerLocation dummyLocation = new ConfigServerLocation(new ConfigserverConfig(new ConfigserverConfig.Builder())); - testResource = new TestResource(dummyLocation, base); + testHandler = new TestHandler(new ConfigserverConfig(new ConfigserverConfig.Builder())); correspondingModel = new ServiceModel(ServiceModelTest.syntheticModelResponse()); } @After public void tearDown() { - testResource = null; + testHandler = null; correspondingModel = null; } - @SuppressWarnings("rawtypes") @Test public final void test() { Service s = correspondingModel.resolve("vespa.yahoo.com", 8080, null); String api = "/state/v1"; - HashMap boom = testResource.singleService("default", "default", "default", "default", "default", s.getIdentifier(8080), api); - assertEquals(EXTERNAL_BASE_URI + "v1/tenant/default/application/default/environment/default/region/default/instance/default/service/" + s.getIdentifier(8080) + api, - ((Map) ((List) boom.get("resources")).get(0)).get("url")); + HashMap<?, ?> boom = testHandler.singleService(URI.create(EXTERNAL_BASE_URI), "default", "default", "default", "default", "default", s.getIdentifier(8080), api); + assertEquals(EXTERNAL_BASE_URI + "tenant/default/application/default/environment/default/region/default/instance/default/service/" + s.getIdentifier(8080) + api, + ((Map<?, ?>) ((List<?>) boom.get("resources")).get(0)).get("url")); } @Test public final void testLinkEquality() { - ApplicationView explicitParameters = testResource.getUserInfo("default", "default", "default", "default", "default"); - ApplicationView implicitParameters = testResource.getDefaultUserInfo(); - assertEquals(explicitParameters.clusters.get(0).services.get(0).url, implicitParameters.clusters.get(0).services.get(0).url); + ApplicationView explicitParameters = testHandler.getUserInfo(URI.create(EXTERNAL_BASE_URI), "default", "default", "default", "default", "default"); + assertEquals(EXTERNAL_BASE_URI + "tenant/default/application/default/environment/default/region/default/instance" + + "/default/service/container-clustercontroller-2ul67p8psr451t3w8kdd0qwgg/state/v1/", + explicitParameters.clusters.get(0).services.get(0).url); } } |