diff options
-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/StateResourceTest.java (renamed from configserver/src/test/java/com/yahoo/vespa/serviceview/StateRequestHandlerTest.java) | 43 |
5 files changed, 320 insertions, 283 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 new file mode 100644 index 00000000000..05d1119aa4f --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/serviceview/ConfigServerLocation.java @@ -0,0 +1,38 @@ +// 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 deleted file mode 100644 index 38c74b16c1f..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java +++ /dev/null @@ -1,259 +0,0 @@ -// 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 new file mode 100644 index 00000000000..138e6c8798c --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/serviceview/StateResource.java @@ -0,0 +1,253 @@ +// 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 cfff3719d6e..a4ca7081f0b 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -69,10 +69,12 @@ <components bundle="orchestrator" /> </rest-api> - <handler id="com.yahoo.vespa.serviceview.StateRequestHandler" bundle="configserver"> - <binding>http://*/serviceview/v1/</binding> - <binding>http://*/serviceview/v1/*</binding> - </handler> + <rest-api path="serviceview" jersey2="true"> + <components bundle="configserver"> + <package>com.yahoo.vespa.serviceview</package> + </components> + </rest-api> + <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/StateRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/serviceview/StateResourceTest.java index a0bb8a5acc7..794b825db6e 100644 --- a/configserver/src/test/java/com/yahoo/vespa/serviceview/StateRequestHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/serviceview/StateResourceTest.java @@ -2,7 +2,7 @@ package com.yahoo.vespa.serviceview; import com.yahoo.cloud.config.ConfigserverConfig; -import com.yahoo.jdisc.test.MockMetric; +import com.yahoo.container.jaxrs.annotation.Component; 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 StateRequestHandler}. + * Functional test for {@link StateResource}. * * @author Steinar Knutsen - * @author bjorncs */ -public class StateRequestHandlerTest { +public class StateResourceTest { - private static final String EXTERNAL_BASE_URI = "http://someserver:8080/serviceview/v1/"; + private static final String EXTERNAL_BASE_URI = "http://someserver:8080/serviceview/"; - private static class TestHandler extends StateRequestHandler { + private static class TestResource extends StateResource { private static final String BASE_URI = "http://vespa.yahoo.com:8080/state/v1"; - TestHandler(ConfigserverConfig config) { - super(new Context(Executors.newSingleThreadExecutor(), new MockMetric()), config); + TestResource(@Component ConfigServerLocation configServer, @Context UriInfo ui) { + super(configServer, ui); } @Override @@ -44,7 +44,7 @@ public class StateRequestHandlerTest { } @Override - protected HealthClient getHealthClient(String apiParams, Service s, int requestedPort, String uriQuery, Client client) { + protected HealthClient getHealthClient(String apiParams, Service s, int requestedPort, Client client) { HealthClient healthClient = Mockito.mock(HealthClient.class); HashMap<Object, Object> dummyHealthData = new HashMap<>(); HashMap<String, String> dummyLink = new HashMap<>(); @@ -55,36 +55,39 @@ public class StateRequestHandlerTest { } } - private StateRequestHandler testHandler; + private StateResource testResource; private ServiceModel correspondingModel; @Before public void setUp() throws Exception { - testHandler = new TestHandler(new ConfigserverConfig(new ConfigserverConfig.Builder())); + 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); correspondingModel = new ServiceModel(ServiceModelTest.syntheticModelResponse()); } @After public void tearDown() { - testHandler = null; + testResource = 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 = 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")); + 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")); } @Test public final void testLinkEquality() { - 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); + 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); } } |