aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2021-03-23 15:23:07 +0100
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2021-03-24 16:58:43 +0100
commit4cbdca5561e5e37865a26ab551134bc624087c64 (patch)
treee0ebcb52cdd34e2099ec6a38583257d3754e9ee5
parent32eab56d7dc6ade8a8eb1d359c50dd5dcfa90ef9 (diff)
Convert StateResource as request handler
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/serviceview/ConfigServerLocation.java38
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/serviceview/StateRequestHandler.java259
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/serviceview/StateResource.java253
-rw-r--r--configserver/src/main/resources/configserver-app/services.xml10
-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);
}
}