From b52f35351da2e8eba99eedd9a0b2a30ce08c8eff Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Wed, 22 Nov 2017 14:27:18 +0100 Subject: Reimplement /zone/v2 --- .../hosted/controller/ConfigServerProxyMock.java | 43 ++++++++ .../restapi/ControllerContainerTest.java | 5 + .../controller/restapi/zone/v2/ZoneApiTest.java | 117 +++++++++++++++++++++ .../controller/restapi/zone/v2/responses/root.json | 26 +++++ .../restapi/zone/v2/responses/unknown-zone.json | 4 + 5 files changed, 195 insertions(+) create mode 100644 controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerProxyMock.java create mode 100644 controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java create mode 100644 controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/root.json create mode 100644 controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/unknown-zone.json (limited to 'controller-server/src/test/java/com/yahoo') diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerProxyMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerProxyMock.java new file mode 100644 index 00000000000..cc915d4d9a1 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ConfigServerProxyMock.java @@ -0,0 +1,43 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller; + +import com.yahoo.component.AbstractComponent; +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.vespa.hosted.controller.proxy.ConfigServerRestExecutor; +import com.yahoo.vespa.hosted.controller.proxy.ProxyException; +import com.yahoo.vespa.hosted.controller.proxy.ProxyRequest; +import com.yahoo.vespa.hosted.controller.restapi.StringResponse; + +import java.io.InputStream; +import java.util.Optional; +import java.util.Scanner; + +/** + * @author mpolden + */ +public class ConfigServerProxyMock extends AbstractComponent implements ConfigServerRestExecutor { + + private volatile ProxyRequest lastReceived = null; + private volatile String requestBody = null; + + @Override + public HttpResponse handle(ProxyRequest proxyRequest) throws ProxyException { + lastReceived = proxyRequest; + // Copy request body as the input stream is drained once the request completes + requestBody = asString(proxyRequest.getData()); + return new StringResponse("ok"); + } + + public Optional lastReceived() { + return Optional.ofNullable(lastReceived); + } + + public Optional lastRequestBody() { + return Optional.ofNullable(requestBody); + } + + private static String asString(InputStream inputStream) { + Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"); + return scanner.hasNext() ? scanner.next() : ""; + } +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java index 19c4def819f..044c5d75d12 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java @@ -48,6 +48,7 @@ public class ControllerContainerTest { " " + " " + " " + + " " + " " + " " + " " + @@ -74,6 +75,10 @@ public class ControllerContainerTest { " http://*/zone/v1" + " http://*/zone/v1/*" + " " + + " " + + " http://*/zone/v2" + + " http://*/zone/v2/*" + + " " + ""; protected void assertResponse(Request request, int responseStatus, String responseMessage) throws IOException { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java new file mode 100644 index 00000000000..63899d808f9 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java @@ -0,0 +1,117 @@ +package com.yahoo.vespa.hosted.controller.restapi.zone.v2; + +import com.yahoo.application.container.handler.Request; +import com.yahoo.application.container.handler.Request.Method; +import com.yahoo.config.provision.Environment; +import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.Zone; +import com.yahoo.text.Utf8; +import com.yahoo.vespa.hosted.controller.ConfigServerProxyMock; +import com.yahoo.vespa.hosted.controller.ZoneRegistryMock; +import com.yahoo.vespa.hosted.controller.restapi.ContainerControllerTester; +import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * @author mpolden + */ +public class ZoneApiTest extends ControllerContainerTest { + + private static final String responseFiles = "src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/"; + private static final List zones = Arrays.asList( + new Zone(Environment.prod, RegionName.from("us-north-1")), + new Zone(Environment.dev, RegionName.from("us-north-2")), + new Zone(Environment.test, RegionName.from("us-north-3")), + new Zone(Environment.staging, RegionName.from("us-north-4")) + ); + + private ContainerControllerTester tester; + private ConfigServerProxyMock proxy; + + @Before + public void before() { + ZoneRegistryMock zoneRegistry = (ZoneRegistryMock) container.components() + .getComponent(ZoneRegistryMock.class.getName()); + zoneRegistry.setDefaultRegionForEnvironment(Environment.dev, RegionName.from("us-north-2")) + .setZones(zones); + this.tester = new ContainerControllerTester(container, responseFiles); + this.proxy = (ConfigServerProxyMock) container.components().getComponent(ConfigServerProxyMock.class.getName()); + } + + @Test + public void test_requests() throws Exception { + // GET /zone/v2 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2"), + new File("root.json")); + + // GET /zone/v2/prod/us-north-1 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/prod/us-north-1"), + "ok"); + assertEquals("prod", proxy.lastReceived().get().getEnvironment()); + assertEquals("us-north-1", proxy.lastReceived().get().getRegion()); + assertEquals("", proxy.lastReceived().get().getConfigServerRequest()); + assertEquals("GET", proxy.lastReceived().get().getMethod()); + + // GET /zone/v2/nodes/v2/node/?recursive=true + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/prod/us-north-1/nodes/v2/node/?recursive=true"), + "ok"); + + assertEquals("prod", proxy.lastReceived().get().getEnvironment()); + assertEquals("us-north-1", proxy.lastReceived().get().getRegion()); + assertEquals("/nodes/v2/node/?recursive=true", proxy.lastReceived().get().getConfigServerRequest()); + assertEquals("GET", proxy.lastReceived().get().getMethod()); + + // POST /zone/v2/dev/us-north-2/nodes/v2/command/restart?hostname=node1 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/dev/us-north-2/nodes/v2/command/restart?hostname=node1", + new byte[0], Method.POST), + "ok"); + assertEquals("dev", proxy.lastReceived().get().getEnvironment()); + assertEquals("us-north-2", proxy.lastReceived().get().getRegion()); + assertEquals("/nodes/v2/command/restart?hostname=node1", proxy.lastReceived().get().getConfigServerRequest()); + assertEquals("POST", proxy.lastReceived().get().getMethod()); + + // PUT /zone/v2/prod/us-north-1/nodes/v2/state/dirty/node1 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/prod/us-north-1/nodes/v2/state/dirty/node1", + new byte[0], Method.PUT), "ok"); + assertEquals("prod", proxy.lastReceived().get().getEnvironment()); + assertEquals("us-north-1", proxy.lastReceived().get().getRegion()); + assertEquals("/nodes/v2/state/dirty/node1", proxy.lastReceived().get().getConfigServerRequest()); + assertEquals("PUT", proxy.lastReceived().get().getMethod()); + + // DELETE /zone/v2/prod/us-north-1/nodes/v2/node/node1 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/prod/us-north-1/nodes/v2/node/node1", + new byte[0], Method.DELETE), "ok"); + assertEquals("prod", proxy.lastReceived().get().getEnvironment()); + assertEquals("us-north-1", proxy.lastReceived().get().getRegion()); + assertEquals("/nodes/v2/node/node1", proxy.lastReceived().get().getConfigServerRequest()); + assertEquals("DELETE", proxy.lastReceived().get().getMethod()); + + // PATCH /zone/v2/prod/us-north-1/nodes/v2/node/node1 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/prod/us-north-1/nodes/v2/node/node1", + Utf8.toBytes("{\"currentRestartGeneration\": 1}"), + Method.PATCH), "ok"); + assertEquals("prod", proxy.lastReceived().get().getEnvironment()); + assertEquals("us-north-1", proxy.lastReceived().get().getRegion()); + assertEquals("/nodes/v2/node/node1", proxy.lastReceived().get().getConfigServerRequest()); + assertEquals("PATCH", proxy.lastReceived().get().getMethod()); + assertEquals("{\"currentRestartGeneration\": 1}", proxy.lastRequestBody().get()); + } + + @Test + public void test_invalid_requests() throws Exception { + // GET /zone/v2/prod/us-north-34/nodes/v2 + tester.containerTester().assertResponse(new Request("http://localhost:8080/zone/v2/prod/us-north-42/nodes/v2", + new byte[0], Method.POST), + new File("unknown-zone.json"), 400); + assertFalse(proxy.lastReceived().isPresent()); + } + +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/root.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/root.json new file mode 100644 index 00000000000..ab168854267 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/root.json @@ -0,0 +1,26 @@ +{ + "uris": [ + "http://localhost:8080/zone/v2/prod/us-north-1", + "http://localhost:8080/zone/v2/dev/us-north-2", + "http://localhost:8080/zone/v2/test/us-north-3", + "http://localhost:8080/zone/v2/staging/us-north-4" + ], + "zones": [ + { + "environment": "prod", + "region": "us-north-1" + }, + { + "environment": "dev", + "region": "us-north-2" + }, + { + "environment": "test", + "region": "us-north-3" + }, + { + "environment": "staging", + "region": "us-north-4" + } + ] +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/unknown-zone.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/unknown-zone.json new file mode 100644 index 00000000000..c7d6e4b8400 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/responses/unknown-zone.json @@ -0,0 +1,4 @@ +{ + "error-code": "BAD_REQUEST", + "message": "No such zone: prod.us-north-42" +} -- cgit v1.2.3