aboutsummaryrefslogtreecommitdiffstats
path: root/orchestrator/src/test
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2021-04-12 20:49:31 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2021-04-12 20:57:24 +0200
commit97e6a063049a93d7a78301f29c27148f72dcef67 (patch)
treeb515dcb09a5b6e1380e16ca4aaafe373f45a9d18 /orchestrator/src/test
parent8cf392f9573d4061bef71e426c4940426dd121a7 (diff)
Convert remaining JAX-RS resources to request handlers
Diffstat (limited to 'orchestrator/src/test')
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/ApplicationSuspensionRequestHandlerTest.java157
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostRequestHandlerTest.java (renamed from orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/host/HostResourceTest.java)185
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostSuspensionHandlerTest.java9
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceRequestHandlerTest.java132
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/appsuspension/ApplicationSuspensionResourceTest.java168
-rw-r--r--orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/instance/InstanceResourceTest.java92
6 files changed, 392 insertions, 351 deletions
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/ApplicationSuspensionRequestHandlerTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/ApplicationSuspensionRequestHandlerTest.java
new file mode 100644
index 00000000000..176a95d1c04
--- /dev/null
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/ApplicationSuspensionRequestHandlerTest.java
@@ -0,0 +1,157 @@
+package com.yahoo.vespa.orchestrator.resources;// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.container.jdisc.LoggingRequestHandler;
+import com.yahoo.jdisc.core.SystemTimer;
+import com.yahoo.jdisc.test.MockMetric;
+import com.yahoo.vespa.curator.mock.MockCurator;
+import com.yahoo.vespa.flags.InMemoryFlagSource;
+import com.yahoo.vespa.orchestrator.DummyServiceMonitor;
+import com.yahoo.vespa.orchestrator.Orchestrator;
+import com.yahoo.vespa.orchestrator.OrchestratorImpl;
+import com.yahoo.vespa.orchestrator.config.OrchestratorConfig;
+import com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactoryMock;
+import com.yahoo.vespa.orchestrator.status.ZkStatusService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Set;
+import java.util.concurrent.Executors;
+
+import static com.yahoo.jdisc.http.HttpRequest.Method;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Tests the implementation of the orchestrator Application API.
+ *
+ * @author smorgrav
+ * @author bjorncs
+ */
+class ApplicationSuspensionRequestHandlerTest {
+ private static final String RESOURCE_1 = "mediasearch:imagesearch:default";
+ private static final String RESOURCE_2 = "test-tenant-id:application:instance";
+ private static final String INVALID_RESOURCE_NAME = "something_without_colons";
+
+ ApplicationSuspensionRequestHandler handler;
+
+ @BeforeEach
+ void createHandler() {
+ DummyServiceMonitor serviceMonitor = new DummyServiceMonitor();
+ Orchestrator orchestrator = new OrchestratorImpl(
+ new ClusterControllerClientFactoryMock(),
+ new ZkStatusService(new MockCurator(), new MockMetric(), new SystemTimer(), serviceMonitor),
+ new OrchestratorConfig(new OrchestratorConfig.Builder()),
+ serviceMonitor,
+ new ConfigserverConfig(new ConfigserverConfig.Builder()),
+ new InMemoryFlagSource());
+ var handlerContext = new LoggingRequestHandler.Context(Executors.newSingleThreadExecutor(), new MockMetric());
+ this.handler = new ApplicationSuspensionRequestHandler(handlerContext, orchestrator);
+ }
+
+
+ @Test
+ void get_all_suspended_applications_return_empty_list_initially() throws IOException {
+ HttpResponse httpResponse = executeRequest(Method.GET, "", null);
+ assertEquals(200, httpResponse.getStatus());
+ Set<String> set = parseResponseContent(httpResponse, new TypeReference<>() {});
+ assertEquals(0, set.size());
+ }
+
+ @Test
+ void invalid_application_id_throws_http_400() throws IOException {
+ HttpResponse httpResponse = executeRequest(Method.POST, "", INVALID_RESOURCE_NAME);
+ assertEquals(400, httpResponse.getStatus());
+ }
+
+ @Test
+ void get_application_status_returns_404_for_not_suspended_and_204_for_suspended() throws IOException {
+ // Get on application that is not suspended
+ HttpResponse httpResponse = executeRequest(Method.GET, "/"+RESOURCE_1, null);
+ assertEquals(404, httpResponse.getStatus());
+
+ // Post application
+ httpResponse = executeRequest(Method.POST, "", RESOURCE_1);
+ assertEquals(204, httpResponse.getStatus());
+
+ // Get on the application that now should be in suspended
+ httpResponse = executeRequest(Method.GET, "/"+RESOURCE_1, null);
+ assertEquals(204, httpResponse.getStatus());
+ }
+
+ @Test
+ void delete_works_on_suspended_and_not_suspended_applications() throws IOException {
+ // Delete an application that is not suspended
+ HttpResponse httpResponse = executeRequest(Method.DELETE, "/"+RESOURCE_1, null);
+ assertEquals(204, httpResponse.getStatus());
+
+ // Put application in suspend
+ httpResponse = executeRequest(Method.POST, "", RESOURCE_1);
+ assertEquals(204, httpResponse.getStatus());
+
+ // Check that it is in suspend
+ httpResponse = executeRequest(Method.GET, "/"+RESOURCE_1, null);
+ assertEquals(204, httpResponse.getStatus());
+
+ // Delete it
+ httpResponse = executeRequest(Method.DELETE, "/"+RESOURCE_1, null);
+ assertEquals(204, httpResponse.getStatus());
+
+ // Check that it is not in suspend anymore
+ httpResponse = executeRequest(Method.GET, "/"+RESOURCE_1, null);
+ assertEquals(404, httpResponse.getStatus());
+ }
+
+ @Test
+ void list_applications_returns_the_correct_list_of_suspended_applications() throws IOException {
+ // Test that initially we have the empty set
+ HttpResponse httpResponse = executeRequest(Method.GET, "", null);
+ assertEquals(200, httpResponse.getStatus());
+ Set<String> set = parseResponseContent(httpResponse, new TypeReference<>() {});
+ assertEquals(0, set.size());
+
+ // Add a couple of applications to maintenance
+ executeRequest(Method.POST, "", RESOURCE_1);
+ executeRequest(Method.POST, "", RESOURCE_2);
+
+ // Test that we get them back
+ httpResponse = executeRequest(Method.GET, "", null);
+ assertEquals(200, httpResponse.getStatus());
+ set = parseResponseContent(httpResponse, new TypeReference<>() {});
+ assertEquals(2, set.size());
+
+ // Remove suspend for the first resource
+ executeRequest(Method.DELETE, "/"+RESOURCE_1, null);
+
+ // Test that we are back to the start with the empty set
+ httpResponse = executeRequest(Method.GET, "", null);
+ assertEquals(200, httpResponse.getStatus());
+ set = parseResponseContent(httpResponse, new TypeReference<>() {});
+ assertEquals(1, set.size());
+ assertEquals(RESOURCE_2, set.iterator().next());
+ }
+
+ private HttpResponse executeRequest(Method method, String path, String applicationId) throws IOException {
+ String uri = "http://localhost/orchestrator/v1/suspensions/applications" + path;
+ com.yahoo.container.jdisc.HttpRequest request;
+ if (applicationId != null) {
+ ByteArrayInputStream requestData = new ByteArrayInputStream(applicationId.getBytes(StandardCharsets.UTF_8));
+ request = com.yahoo.container.jdisc.HttpRequest.createTestRequest(uri, method, requestData);
+ } else {
+ request = com.yahoo.container.jdisc.HttpRequest.createTestRequest(uri, method);
+ }
+ return handler.handle(request);
+ }
+
+ private <T> T parseResponseContent(HttpResponse response, TypeReference<T> responseEntityType) throws IOException {
+ assertEquals(200, response.getStatus());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ response.render(out);
+ return handler.restApi().jacksonJsonMapper().readValue(out.toByteArray(), responseEntityType);
+ }
+} \ No newline at end of file
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/host/HostResourceTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostRequestHandlerTest.java
index d056c3730fd..c34775c1910 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/host/HostResourceTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostRequestHandlerTest.java
@@ -1,9 +1,15 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.orchestrator.resources.host;
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.orchestrator.resources;
import com.google.common.util.concurrent.UncheckedTimeoutException;
+import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.container.jdisc.LoggingRequestHandler;
import com.yahoo.jdisc.Metric;
+import com.yahoo.jdisc.http.HttpRequest.Method;
+import com.yahoo.jdisc.test.MockMetric;
import com.yahoo.jdisc.test.TestTimer;
+import com.yahoo.test.json.JsonTestHelper;
import com.yahoo.vespa.applicationmodel.ApplicationInstance;
import com.yahoo.vespa.applicationmodel.ApplicationInstanceId;
import com.yahoo.vespa.applicationmodel.ApplicationInstanceReference;
@@ -41,24 +47,21 @@ import com.yahoo.vespa.orchestrator.status.StatusService;
import com.yahoo.vespa.orchestrator.status.ZkStatusService;
import com.yahoo.vespa.service.monitor.ServiceModel;
import com.yahoo.vespa.service.monitor.ServiceMonitor;
-import org.junit.Before;
-import org.junit.Test;
-
-import javax.ws.rs.BadRequestException;
-import javax.ws.rs.InternalServerErrorException;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.net.URI;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.time.Clock;
import java.time.Instant;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.Executors;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
@@ -68,8 +71,10 @@ import static org.mockito.Mockito.when;
/**
* @author hakonhall
+ * @author bjorncs
*/
-public class HostResourceTest {
+class HostRequestHandlerTest {
+
private static final Clock clock = mock(Clock.class);
private static final int SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS = 0;
private static final TenantId TENANT_ID = new TenantId("tenantId");
@@ -121,14 +126,14 @@ public class HostResourceTest {
private final OrchestratorImpl alwaysAllowOrchestrator = createAlwaysAllowOrchestrator(clock);
private final OrchestratorImpl hostNotFoundOrchestrator = createHostNotFoundOrchestrator(clock);
- private final UriInfo uriInfo = mock(UriInfo.class);
+ private final OrchestratorImpl alwaysRejectOrchestrator = createAlwaysRejectResolver(clock);
- @Before
- public void setUp() {
+ @BeforeEach
+ void setUp() {
when(clock.instant()).thenReturn(Instant.now());
}
- public static OrchestratorImpl createAlwaysAllowOrchestrator(Clock clock) {
+ static OrchestratorImpl createAlwaysAllowOrchestrator(Clock clock) {
return new OrchestratorImpl(
new AlwaysAllowPolicy(),
new ClusterControllerClientFactoryMock(),
@@ -140,7 +145,7 @@ public class HostResourceTest {
new InMemoryFlagSource());
}
- public static OrchestratorImpl createHostNotFoundOrchestrator(Clock clock) {
+ static OrchestratorImpl createHostNotFoundOrchestrator(Clock clock) {
return new OrchestratorImpl(
new AlwaysAllowPolicy(),
new ClusterControllerClientFactoryMock(),
@@ -152,9 +157,9 @@ public class HostResourceTest {
new InMemoryFlagSource());
}
- public static OrchestratorImpl createAlwaysRejectResolver(Clock clock) {
+ static OrchestratorImpl createAlwaysRejectResolver(Clock clock) {
return new OrchestratorImpl(
- new HostResourceTest.AlwaysFailPolicy(),
+ new AlwaysFailPolicy(),
new ClusterControllerClientFactoryMock(),
EVERY_HOST_IS_UP_HOST_STATUS_SERVICE,
serviceMonitor,
@@ -165,27 +170,20 @@ public class HostResourceTest {
}
@Test
- public void returns_200_on_success() {
- HostResource hostResource =
- new HostResource(alwaysAllowOrchestrator, uriInfo);
-
- final String hostName = "hostname";
+ void returns_200_on_success() throws IOException {
+ HostRequestHandler handler = createHandler(alwaysAllowOrchestrator);
- UpdateHostResponse response = hostResource.suspend(hostName);
-
- assertEquals(hostName, response.hostname());
+ HttpResponse response = executeRequest(handler, Method.PUT, "/orchestrator/v1/hosts/hostname/suspended", null);
+ UpdateHostResponse updateHostResponse = parseResponseContent(handler, response, UpdateHostResponse.class);
+ assertEquals("hostname", updateHostResponse.hostname());
}
@Test
- public void throws_404_when_host_unknown() {
- try {
- HostResource hostResource =
- new HostResource(hostNotFoundOrchestrator, uriInfo);
- hostResource.suspend("hostname");
- fail();
- } catch (WebApplicationException w) {
- assertEquals(404, w.getResponse().getStatus());
- }
+ void throws_404_when_host_unknown() throws IOException {
+ HostRequestHandler handler = createHandler(hostNotFoundOrchestrator);
+
+ HttpResponse response = executeRequest(handler, Method.PUT, "/orchestrator/v1/hosts/hostname/suspended", null);
+ assertEquals(404, response.getStatus());
}
private static class AlwaysFailPolicy implements Policy {
@@ -221,79 +219,61 @@ public class HostResourceTest {
}
@Test
- public void throws_409_when_request_rejected_by_policies() {
- final OrchestratorImpl alwaysRejectResolver = new OrchestratorImpl(
- new AlwaysFailPolicy(),
- new ClusterControllerClientFactoryMock(),
- EVERY_HOST_IS_UP_HOST_STATUS_SERVICE,
- serviceMonitor,
- SERVICE_MONITOR_CONVERGENCE_LATENCY_SECONDS,
- clock,
- applicationApiFactory,
- new InMemoryFlagSource());
+ void throws_409_when_request_rejected_by_policies() throws IOException {
+ HostRequestHandler handler = createHandler(alwaysRejectOrchestrator);
- try {
- HostResource hostResource = new HostResource(alwaysRejectResolver, uriInfo);
- hostResource.suspend("hostname");
- fail();
- } catch (WebApplicationException w) {
- assertEquals(409, w.getResponse().getStatus());
- }
+ HttpResponse response = executeRequest(handler, Method.PUT, "/orchestrator/v1/hosts/hostname/suspended", null);
+ assertEquals(409, response.getStatus());
}
- @Test(expected = BadRequestException.class)
- public void patch_state_may_throw_bad_request() {
+ @Test
+ void patch_state_may_throw_bad_request() throws IOException {
Orchestrator orchestrator = mock(Orchestrator.class);
- HostResource hostResource = new HostResource(orchestrator, uriInfo);
+ HostRequestHandler handler = createHandler(orchestrator);
- String hostNameString = "hostname";
PatchHostRequest request = new PatchHostRequest();
request.state = "bad state";
- hostResource.patch(hostNameString, request);
+ HttpResponse response = executeRequest(handler, Method.PATCH, "/orchestrator/v1/hosts/hostname", request);
+ assertEquals(400, response.getStatus());
}
@Test
- public void patch_works() throws OrchestrationException {
+ void patch_works() throws OrchestrationException, IOException {
Orchestrator orchestrator = mock(Orchestrator.class);
- HostResource hostResource = new HostResource(orchestrator, uriInfo);
+ HostRequestHandler handler = createHandler(orchestrator);
String hostNameString = "hostname";
PatchHostRequest request = new PatchHostRequest();
request.state = "NO_REMARKS";
- PatchHostResponse response = hostResource.patch(hostNameString, request);
+ HttpResponse httpResponse = executeRequest(handler, Method.PATCH, "/orchestrator/v1/hosts/hostname", request);
+ PatchHostResponse response = parseResponseContent(handler, httpResponse, PatchHostResponse.class);
assertEquals(response.description, "ok");
verify(orchestrator, times(1)).setNodeStatus(new HostName(hostNameString), HostStatus.NO_REMARKS);
}
- @Test(expected = InternalServerErrorException.class)
- public void patch_handles_exception_in_orchestrator() throws OrchestrationException {
+ @Test
+ void patch_handles_exception_in_orchestrator() throws OrchestrationException, IOException {
Orchestrator orchestrator = mock(Orchestrator.class);
- HostResource hostResource = new HostResource(orchestrator, uriInfo);
+ HostRequestHandler handler = createHandler(orchestrator);
String hostNameString = "hostname";
PatchHostRequest request = new PatchHostRequest();
request.state = "NO_REMARKS";
doThrow(new OrchestrationException("error")).when(orchestrator).setNodeStatus(new HostName(hostNameString), HostStatus.NO_REMARKS);
- hostResource.patch(hostNameString, request);
+ HttpResponse httpResponse = executeRequest(handler, Method.PATCH, "/orchestrator/v1/hosts/hostname", request);
+ assertEquals(500, httpResponse.getStatus());
}
@Test
- public void getHost_works() throws Exception {
+ void getHost_works() throws Exception {
Orchestrator orchestrator = mock(Orchestrator.class);
- HostResource hostResource = new HostResource(orchestrator, uriInfo);
+ HostRequestHandler handler = createHandler(orchestrator);
HostName hostName = new HostName("hostname");
- UriBuilder baseUriBuilder = mock(UriBuilder.class);
- when(uriInfo.getBaseUriBuilder()).thenReturn(baseUriBuilder);
- when(baseUriBuilder.path(any(String.class))).thenReturn(baseUriBuilder);
- when(baseUriBuilder.path(any(Class.class))).thenReturn(baseUriBuilder);
- URI uri = new URI("https://foo.com/bar");
- when(baseUriBuilder.build()).thenReturn(uri);
-
ServiceInstance serviceInstance = new ServiceInstance(
new ConfigId("configId"),
hostName,
@@ -312,8 +292,11 @@ public class HostResourceTest {
new ApplicationInstanceId("applicationId")),
Collections.singletonList(serviceInstance));
when(orchestrator.getHost(hostName)).thenReturn(host);
- GetHostResponse response = hostResource.getHost(hostName.s());
- assertEquals("https://foo.com/bar", response.applicationUrl());
+
+ HttpResponse httpResponse = executeRequest(handler, Method.GET, "/orchestrator/v1/hosts/hostname", null);
+ GetHostResponse response = parseResponseContent(handler, httpResponse, GetHostResponse.class);
+
+ assertEquals("http://localhost/orchestrator/v1/instances/tenantId:applicationId", response.applicationUrl());
assertEquals("hostname", response.hostname());
assertEquals("ALLOWED_TO_BE_DOWN", response.state());
assertEquals("1970-01-01T00:00:00Z", response.suspendedSince());
@@ -325,18 +308,48 @@ public class HostResourceTest {
}
@Test
- public void throws_409_on_timeout() throws HostNameNotFoundException, HostStateChangeDeniedException {
+ void throws_409_on_timeout() throws HostNameNotFoundException, HostStateChangeDeniedException, IOException {
Orchestrator orchestrator = mock(Orchestrator.class);
doThrow(new UncheckedTimeoutException("Timeout Message")).when(orchestrator).resume(any(HostName.class));
- try {
- HostResource hostResource = new HostResource(orchestrator, uriInfo);
- hostResource.resume("hostname");
- fail();
- } catch (WebApplicationException w) {
- assertEquals(409, w.getResponse().getStatus());
- assertEquals("resume failed: Timeout Message [deadline]", w.getMessage());
+ HostRequestHandler handler = createHandler(orchestrator);
+ HttpResponse httpResponse = executeRequest(handler, Method.DELETE, "/orchestrator/v1/hosts/hostname/suspended", null);
+ assertEquals(409, httpResponse.getStatus());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ httpResponse.render(out);
+ JsonTestHelper.assertJsonEquals("{\n" +
+ " \"hostname\" : \"hostname\",\n" +
+ " \"reason\" : {\n" +
+ " \"constraint\" : \"deadline\",\n" +
+ " \"message\" : \"resume failed: Timeout Message\"\n" +
+ " }\n" +
+ "}",
+ out.toString());
+ }
+
+ private HostRequestHandler createHandler(Orchestrator orchestrator) {
+ var handlerContext = new LoggingRequestHandler.Context(Executors.newSingleThreadExecutor(), new MockMetric());
+ return new HostRequestHandler(handlerContext, orchestrator);
+ }
+
+ private HttpResponse executeRequest(HostRequestHandler handler, Method method, String path, Object requestEntity) throws IOException {
+ String uri = "http://localhost" + path;
+ HttpRequest request;
+ if (requestEntity != null) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ handler.restApi().jacksonJsonMapper().writeValue(out, requestEntity);
+ request = HttpRequest.createTestRequest(uri, method, new ByteArrayInputStream(out.toByteArray()));
+ } else {
+ request = HttpRequest.createTestRequest(uri, method);
}
+ return handler.handle(request);
+ }
+
+ private <T> T parseResponseContent(HostRequestHandler handler, HttpResponse response, Class<T> responseEntityType) throws IOException {
+ assertEquals(200, response.getStatus());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ response.render(out);
+ return handler.restApi().jacksonJsonMapper().readValue(out.toByteArray(), responseEntityType);
}
}
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostSuspensionHandlerTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostSuspensionHandlerTest.java
index 9d413526037..be3cb047967 100644
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostSuspensionHandlerTest.java
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/HostSuspensionHandlerTest.java
@@ -12,7 +12,6 @@ import com.yahoo.vespa.orchestrator.BatchInternalErrorException;
import com.yahoo.vespa.orchestrator.Orchestrator;
import com.yahoo.vespa.orchestrator.OrchestratorImpl;
import com.yahoo.vespa.orchestrator.policy.BatchHostStateChangeDeniedException;
-import com.yahoo.vespa.orchestrator.resources.host.HostResourceTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -46,14 +45,14 @@ class HostSuspensionHandlerTest {
@Test
void returns_200_on_success_batch() throws IOException {
- HostSuspensionHandler handler = createHandler(HostResourceTest.createAlwaysAllowOrchestrator(clock));
+ HostSuspensionHandler handler = createHandler(HostRequestHandlerTest.createAlwaysAllowOrchestrator(clock));
HttpResponse response = executeSuspendAllRequest(handler, "parentHostname", List.of("hostname1", "hostname2"));
assertSuccess(response);
}
@Test
void returns_200_empty_batch() throws IOException {
- HostSuspensionHandler handler = createHandler(HostResourceTest.createAlwaysAllowOrchestrator(clock));
+ HostSuspensionHandler handler = createHandler(HostRequestHandlerTest.createAlwaysAllowOrchestrator(clock));
HttpResponse response = executeSuspendAllRequest(handler, "parentHostname", List.of());
assertSuccess(response);
}
@@ -63,14 +62,14 @@ class HostSuspensionHandlerTest {
// hostnames are part of the request body for multi-host.
@Test
void returns_400_when_host_unknown_for_batch() {
- HostSuspensionHandler handler = createHandler(HostResourceTest.createHostNotFoundOrchestrator(clock));
+ HostSuspensionHandler handler = createHandler(HostRequestHandlerTest.createHostNotFoundOrchestrator(clock));
HttpResponse response = executeSuspendAllRequest(handler, "parentHostname", List.of("hostname1", "hostname2"));
assertEquals(400, response.getStatus());
}
@Test
void returns_409_when_request_rejected_by_policies_for_batch() {
- OrchestratorImpl alwaysRejectResolver = HostResourceTest.createAlwaysRejectResolver(clock);
+ OrchestratorImpl alwaysRejectResolver = HostRequestHandlerTest.createAlwaysRejectResolver(clock);
HostSuspensionHandler handler = createHandler(alwaysRejectResolver);
HttpResponse response = executeSuspendAllRequest(handler, "parentHostname", List.of("hostname1", "hostname2"));
assertEquals(409, response.getStatus());
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceRequestHandlerTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceRequestHandlerTest.java
new file mode 100644
index 00000000000..bee19a6d6f5
--- /dev/null
+++ b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/InstanceRequestHandlerTest.java
@@ -0,0 +1,132 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.orchestrator.resources;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.container.jdisc.HttpRequest;
+import com.yahoo.container.jdisc.HttpResponse;
+import com.yahoo.container.jdisc.LoggingRequestHandler;
+import com.yahoo.jdisc.test.MockMetric;
+import com.yahoo.jrt.slobrok.api.Mirror;
+import com.yahoo.vespa.applicationmodel.ClusterId;
+import com.yahoo.vespa.applicationmodel.ConfigId;
+import com.yahoo.vespa.applicationmodel.ServiceStatus;
+import com.yahoo.vespa.applicationmodel.ServiceStatusInfo;
+import com.yahoo.vespa.applicationmodel.ServiceType;
+import com.yahoo.vespa.orchestrator.restapi.wire.SlobrokEntryResponse;
+import com.yahoo.vespa.service.manager.UnionMonitorManager;
+import com.yahoo.vespa.service.monitor.SlobrokApi;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executors;
+
+import static com.yahoo.jdisc.http.HttpRequest.Method.GET;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author bjorncs
+ */
+class InstanceRequestHandlerTest {
+
+ private static final String APPLICATION_INSTANCE_REFERENCE = "tenant:app:prod:us-west-1:instance";
+ private static final ApplicationId APPLICATION_ID = ApplicationId.from(
+ "tenant", "app", "instance");
+ private static final List<Mirror.Entry> ENTRIES = Arrays.asList(
+ new Mirror.Entry("name1", "tcp/spec:1"),
+ new Mirror.Entry("name2", "tcp/spec:2"));
+ private static final ClusterId CLUSTER_ID = new ClusterId("cluster-id");
+ private static final ObjectMapper jsonMapper = new ObjectMapper()
+ .registerModule(new JavaTimeModule())
+ .registerModule(new Jdk8Module());
+
+ private final SlobrokApi slobrokApi = mock(SlobrokApi.class);
+ private final UnionMonitorManager rootManager = mock(UnionMonitorManager.class);
+ private final InstanceRequestHandler handler = new InstanceRequestHandler(
+ new LoggingRequestHandler.Context(Executors.newSingleThreadExecutor(), new MockMetric()),
+ null,
+ null,
+ slobrokApi,
+ rootManager);
+
+
+ @Test
+ void testGetSlobrokEntries() throws Exception {
+ testGetSlobrokEntriesWith("foo", "foo");
+ }
+
+ @Test
+ void testGetSlobrokEntriesWithoutPattern() throws Exception {
+ testGetSlobrokEntriesWith(null, InstanceRequestHandler.DEFAULT_SLOBROK_PATTERN);
+ }
+
+ @Test
+ void testGetServiceStatusInfo() throws IOException {
+ ServiceType serviceType = new ServiceType("serviceType");
+ ConfigId configId = new ConfigId("configId");
+ ServiceStatus serviceStatus = ServiceStatus.UP;
+ when(rootManager.getStatus(APPLICATION_ID, CLUSTER_ID, serviceType, configId))
+ .thenReturn(new ServiceStatusInfo(serviceStatus));
+
+
+ String uriPath = String.format(
+ "/orchestrator/v1/instances/%s/serviceStatusInfo?clusterId=%s&serviceType=%s&configId=%s",
+ APPLICATION_INSTANCE_REFERENCE,
+ CLUSTER_ID.s(),
+ serviceType.s(),
+ configId.s());
+ ServiceStatusInfo serviceStatusInfo = executeRequest(uriPath, new TypeReference<>(){});
+
+ ServiceStatus actualServiceStatus = serviceStatusInfo.serviceStatus();
+ verify(rootManager).getStatus(APPLICATION_ID, CLUSTER_ID, serviceType, configId);
+ assertEquals(serviceStatus, actualServiceStatus);
+ }
+
+ @Test
+ void testBadRequest() {
+ String uriPath = String.format(
+ "/orchestrator/v1/instances/%s/serviceStatusInfo?clusterId=%s",
+ APPLICATION_INSTANCE_REFERENCE,
+ CLUSTER_ID.s());
+ HttpRequest request = HttpRequest.createTestRequest("http://localhost" + uriPath, GET);
+ HttpResponse response = handler.handle(request);
+ assertEquals(400, response.getStatus());
+ }
+
+ private void testGetSlobrokEntriesWith(String pattern, String expectedLookupPattern)
+ throws Exception{
+ when(slobrokApi.lookup(APPLICATION_ID, expectedLookupPattern))
+ .thenReturn(ENTRIES);
+
+ String uriPath = String.format("/orchestrator/v1/instances/%s/slobrok", APPLICATION_INSTANCE_REFERENCE);
+ if (pattern != null) {
+ uriPath += "?pattern=" + pattern;
+ }
+ List<SlobrokEntryResponse> response = executeRequest(uriPath, new TypeReference<>() {});
+
+ verify(slobrokApi).lookup(APPLICATION_ID, expectedLookupPattern);
+
+ String actualJson = jsonMapper.writeValueAsString(response);
+ assertEquals(
+ "[{\"name\":\"name1\",\"spec\":\"tcp/spec:1\"},{\"name\":\"name2\",\"spec\":\"tcp/spec:2\"}]",
+ actualJson);
+ }
+
+ private <T> T executeRequest(String path, TypeReference<T> responseEntityType) throws IOException {
+ HttpRequest request = HttpRequest.createTestRequest("http://localhost" + path, GET);
+ HttpResponse response = handler.handle(request);
+ assertEquals(200, response.getStatus());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ response.render(out);
+ return jsonMapper.readValue(out.toByteArray(), responseEntityType);
+ }
+}
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/appsuspension/ApplicationSuspensionResourceTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/appsuspension/ApplicationSuspensionResourceTest.java
deleted file mode 100644
index a7514de5acd..00000000000
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/appsuspension/ApplicationSuspensionResourceTest.java
+++ /dev/null
@@ -1,168 +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.orchestrator.resources.appsuspension;
-
-import com.yahoo.application.Application;
-import com.yahoo.application.Networking;
-import com.yahoo.container.Container;
-import com.yahoo.jdisc.http.server.jetty.JettyHttpServer;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.GenericType;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.net.URI;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Tests the implementation of the orchestrator Application API.
- *
- * @author smorgrav
- */
-public class ApplicationSuspensionResourceTest {
-
- private static final String BASE_PATH = "/orchestrator/v1/suspensions/applications";
- private static final String RESOURCE_1 = "mediasearch:imagesearch:default";
- private static final String RESOURCE_2 = "test-tenant-id:application:instance";
- private static final String INVALID_RESOURCE_NAME = "something_without_colons";
-
- private Application jdiscApplication;
- private WebTarget webTarget;
-
- @Before
- public void setup() throws Exception {
- jdiscApplication = Application.fromServicesXml(servicesXml(), Networking.enable);
- Client client = ClientBuilder.newClient();
-
- JettyHttpServer serverProvider = (JettyHttpServer) Container.get().getServerProviderRegistry().allComponents().get(0);
- String url = "http://localhost:" + serverProvider.getListenPort() + BASE_PATH;
- webTarget = client.target(new URI(url));
- }
-
- @After
- public void teardown() {
- jdiscApplication.close();
- webTarget = null;
- }
-
- @Ignore
- @Test
- public void run_application_locally_for_manual_browser_testing() throws Exception {
- System.out.println(webTarget.getUri());
- Thread.sleep(3600 * 1000);
- }
-
- @Test
- public void get_all_suspended_applications_return_empty_list_initially() {
- Response reply = webTarget.request().get();
- assertEquals(200, reply.getStatus());
- assertEquals("[]", reply.readEntity(String.class));
- }
-
- @Test
- public void invalid_application_id_throws_http_400() {
- Response reply = webTarget.request().post(Entity.entity(INVALID_RESOURCE_NAME, MediaType.APPLICATION_JSON_TYPE));
- assertEquals(400, reply.getStatus());
- }
-
- @Test
- public void get_application_status_returns_404_for_not_suspended_and_204_for_suspended() {
- // Get on application that is not suspended
- Response reply = webTarget.path(RESOURCE_1).request().get();
- assertEquals(404, reply.getStatus());
-
- // Post application
- reply = webTarget.request().post(Entity.entity(RESOURCE_1, MediaType.APPLICATION_JSON_TYPE));
- assertEquals(204, reply.getStatus());
-
- // Get on the application that now should be in suspended
- reply = webTarget.path(RESOURCE_1).request().get();
- assertEquals(204, reply.getStatus());
- }
-
- @Test
- public void delete_works_on_suspended_and_not_suspended_applications() {
- // Delete an application that is not suspended
- Response reply = webTarget.path(RESOURCE_1).request().delete();
- assertEquals(204, reply.getStatus());
-
- // Put application in suspend
- reply = webTarget.request().post(Entity.entity(RESOURCE_1, MediaType.APPLICATION_JSON_TYPE));
- assertEquals(204, reply.getStatus());
-
- // Check that it is in suspend
- reply = webTarget.path(RESOURCE_1).request(MediaType.APPLICATION_JSON).get();
- assertEquals(204, reply.getStatus());
-
- // Delete it
- reply = webTarget.path(RESOURCE_1).request().delete();
- assertEquals(204, reply.getStatus());
-
- // Check that it is not in suspend anymore
- reply = webTarget.path(RESOURCE_1).request(MediaType.APPLICATION_JSON).get();
- assertEquals(404, reply.getStatus());
- }
-
- @Test
- public void list_applications_returns_the_correct_list_of_suspended_applications() {
- // Test that initially we have the empty set
- Response reply = webTarget.request(MediaType.APPLICATION_JSON).get();
- assertEquals(200, reply.getStatus());
- assertEquals("[]", reply.readEntity(String.class));
-
- // Add a couple of applications to maintenance
- webTarget.request().post(Entity.entity(RESOURCE_1, MediaType.APPLICATION_JSON_TYPE));
- webTarget.request().post(Entity.entity(RESOURCE_2, MediaType.APPLICATION_JSON_TYPE));
- assertEquals(200, reply.getStatus());
-
- // Test that we get them back
- Set<String> responses = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
- .get(new GenericType<Set<String>>() {});
- assertEquals(2, responses.size());
-
- // Remove suspend for the first resource
- webTarget.path(RESOURCE_1).request().delete();
-
- // Test that we are back to the start with the empty set
- responses = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
- .get(new GenericType<Set<String>>() {});
- assertEquals(1, responses.size());
- assertEquals(RESOURCE_2, responses.iterator().next());
- }
-
- private String servicesXml() {
- return "<services>\n" +
- " <container version=\"1.0\" jetty=\"true\">\n" +
- " <accesslog type=\"disabled\"/>\n" +
- " <config name=\"container.handler.threadpool\">\n" +
- " <maxthreads>10</maxthreads>\n" +
- " </config>\n" +
- " <component id=\"com.yahoo.vespa.flags.InMemoryFlagSource\" bundle=\"flags\" />\n" +
- " <component id=\"com.yahoo.vespa.curator.mock.MockCurator\" bundle=\"zkfacade\" />\n" +
- " <component id=\"com.yahoo.vespa.orchestrator.status.ZkStatusService\" bundle=\"orchestrator\" />\n" +
- " <component id=\"com.yahoo.vespa.orchestrator.DummyServiceMonitor\" bundle=\"orchestrator\" />\n" +
- " <component id=\"com.yahoo.vespa.orchestrator.OrchestratorImpl\" bundle=\"orchestrator\" />\n" +
- " <component id=\"com.yahoo.vespa.orchestrator.controller.ClusterControllerClientFactoryMock\" bundle=\"orchestrator\" />\n" +
- "\n" +
- " <rest-api path=\"orchestrator/v1/suspensions/applications\" jersey2=\"true\">\n" +
- " <components bundle=\"orchestrator\">\n" +
- " <package>com.yahoo.vespa.orchestrator.resources.appsuspension</package>\n" +
- " </components>\n" +
- " </rest-api>\n" +
- "\n" +
- " <http>\n" +
- " <server id=\"foo\" port=\"0\"/>\n" +
- " </http>\n" +
- " </container>\n" +
- "</services>\n";
- }
-
-}
diff --git a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/instance/InstanceResourceTest.java b/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/instance/InstanceResourceTest.java
deleted file mode 100644
index 8e2eeb7410d..00000000000
--- a/orchestrator/src/test/java/com/yahoo/vespa/orchestrator/resources/instance/InstanceResourceTest.java
+++ /dev/null
@@ -1,92 +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.orchestrator.resources.instance;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.jrt.slobrok.api.Mirror;
-import com.yahoo.vespa.applicationmodel.ClusterId;
-import com.yahoo.vespa.applicationmodel.ConfigId;
-import com.yahoo.vespa.applicationmodel.ServiceStatus;
-import com.yahoo.vespa.applicationmodel.ServiceStatusInfo;
-import com.yahoo.vespa.applicationmodel.ServiceType;
-import com.yahoo.vespa.orchestrator.resources.instance.InstanceResource;
-import com.yahoo.vespa.orchestrator.restapi.wire.SlobrokEntryResponse;
-import com.yahoo.vespa.service.manager.UnionMonitorManager;
-import com.yahoo.vespa.service.monitor.SlobrokApi;
-import org.junit.Test;
-
-import javax.ws.rs.WebApplicationException;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class InstanceResourceTest {
- private static final String APPLICATION_INSTANCE_REFERENCE = "tenant:app:prod:us-west-1:instance";
- private static final ApplicationId APPLICATION_ID = ApplicationId.from(
- "tenant", "app", "instance");
- private static final List<Mirror.Entry> ENTRIES = Arrays.asList(
- new Mirror.Entry("name1", "tcp/spec:1"),
- new Mirror.Entry("name2", "tcp/spec:2"));
- private static final ClusterId CLUSTER_ID = new ClusterId("cluster-id");
-
- private final SlobrokApi slobrokApi = mock(SlobrokApi.class);
- private final UnionMonitorManager rootManager = mock(UnionMonitorManager.class);
- private final InstanceResource resource = new InstanceResource(
- null,
- null,
- slobrokApi,
- rootManager);
-
- @Test
- public void testGetSlobrokEntries() throws Exception {
- testGetSlobrokEntriesWith("foo", "foo");
- }
-
- @Test
- public void testGetSlobrokEntriesWithoutPattern() throws Exception {
- testGetSlobrokEntriesWith(null, InstanceResource.DEFAULT_SLOBROK_PATTERN);
- }
-
- @Test
- public void testGetServiceStatusInfo() {
- ServiceType serviceType = new ServiceType("serviceType");
- ConfigId configId = new ConfigId("configId");
- ServiceStatus serviceStatus = ServiceStatus.UP;
- when(rootManager.getStatus(APPLICATION_ID, CLUSTER_ID, serviceType, configId))
- .thenReturn(new ServiceStatusInfo(serviceStatus));
- ServiceStatus actualServiceStatus = resource.getServiceStatus(
- APPLICATION_INSTANCE_REFERENCE,
- CLUSTER_ID.s(),
- serviceType.s(),
- configId.s()).serviceStatus();
- verify(rootManager).getStatus(APPLICATION_ID, CLUSTER_ID, serviceType, configId);
- assertEquals(serviceStatus, actualServiceStatus);
- }
-
- @Test(expected = WebApplicationException.class)
- public void testBadRequest() {
- resource.getServiceStatus(APPLICATION_INSTANCE_REFERENCE, CLUSTER_ID.s(), null, null);
- }
-
- private void testGetSlobrokEntriesWith(String pattern, String expectedLookupPattern)
- throws Exception{
- when(slobrokApi.lookup(APPLICATION_ID, expectedLookupPattern))
- .thenReturn(ENTRIES);
-
- List<SlobrokEntryResponse> response = resource.getSlobrokEntries(
- APPLICATION_INSTANCE_REFERENCE,
- pattern);
-
- verify(slobrokApi).lookup(APPLICATION_ID, expectedLookupPattern);
-
- ObjectMapper mapper = new ObjectMapper();
- String actualJson = mapper.writeValueAsString(response);
- assertEquals(
- "[{\"name\":\"name1\",\"spec\":\"tcp/spec:1\"},{\"name\":\"name2\",\"spec\":\"tcp/spec:2\"}]",
- actualJson);
- }
-} \ No newline at end of file