From 86f9f85848f7ff5ae34cd33c50a18e52f064fb87 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Thu, 11 Jul 2019 14:13:23 +0200 Subject: Decouple flags REST API from config server --- .../config/server/http/flags/DefinedFlag.java | 47 ----- .../config/server/http/flags/DefinedFlags.java | 45 ----- .../server/http/flags/FlagDataListResponse.java | 59 ------ .../config/server/http/flags/FlagDataResponse.java | 31 ---- .../config/server/http/flags/FlagsHandler.java | 120 ------------- .../vespa/config/server/http/flags/OKResponse.java | 20 --- .../vespa/config/server/http/flags/V1Response.java | 34 ---- .../main/resources/configserver-app/services.xml | 4 - .../config/server/http/flags/FlagsHandlerTest.java | 200 --------------------- 9 files changed, 560 deletions(-) delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlag.java delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlags.java delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataListResponse.java delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataResponse.java delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagsHandler.java delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/OKResponse.java delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/V1Response.java delete mode 100644 configserver/src/test/java/com/yahoo/vespa/config/server/http/flags/FlagsHandlerTest.java (limited to 'configserver') diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlag.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlag.java deleted file mode 100644 index 92397fc84a7..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlag.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.http.HttpConfigResponse; -import com.yahoo.vespa.flags.FlagDefinition; -import com.yahoo.vespa.flags.json.DimensionHelper; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * @author hakonhall - */ -public class DefinedFlag extends HttpResponse { - private static ObjectMapper mapper = new ObjectMapper(); - - private final FlagDefinition flagDefinition; - - public DefinedFlag(FlagDefinition flagDefinition) { - super(Response.Status.OK); - this.flagDefinition = flagDefinition; - } - - @Override - public void render(OutputStream outputStream) throws IOException { - ObjectNode rootNode = mapper.createObjectNode(); - renderFlagDefinition(flagDefinition, rootNode); - mapper.writeValue(outputStream, rootNode); - } - - static void renderFlagDefinition(FlagDefinition flagDefinition, ObjectNode definitionNode) { - definitionNode.put("description", flagDefinition.getDescription()); - definitionNode.put("modification-effect", flagDefinition.getModificationEffect()); - ArrayNode dimensionsNode = definitionNode.putArray("dimensions"); - flagDefinition.getDimensions().forEach(dimension -> dimensionsNode.add(DimensionHelper.toWire(dimension))); - } - - @Override - public String getContentType() { - return HttpConfigResponse.JSON_CONTENT_TYPE; - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlags.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlags.java deleted file mode 100644 index 9604c51ee4b..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/DefinedFlags.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.http.HttpConfigResponse; -import com.yahoo.vespa.flags.FlagDefinition; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Comparator; -import java.util.List; - -/** - * @author hakonhall - */ -public class DefinedFlags extends HttpResponse { - private static ObjectMapper mapper = new ObjectMapper(); - private static final Comparator sortByFlagId = - (left, right) -> left.getUnboundFlag().id().compareTo(right.getUnboundFlag().id()); - - private final List flags; - - public DefinedFlags(List flags) { - super(Response.Status.OK); - this.flags = flags; - } - - @Override - public void render(OutputStream outputStream) throws IOException { - ObjectNode rootNode = mapper.createObjectNode(); - flags.stream().sorted(sortByFlagId).forEach(flagDefinition -> { - ObjectNode definitionNode = rootNode.putObject(flagDefinition.getUnboundFlag().id().toString()); - DefinedFlag.renderFlagDefinition(flagDefinition, definitionNode); - }); - mapper.writeValue(outputStream, rootNode); - } - - @Override - public String getContentType() { - return HttpConfigResponse.JSON_CONTENT_TYPE; - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataListResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataListResponse.java deleted file mode 100644 index b33fc7c2b04..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataListResponse.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.http.HttpConfigResponse; -import com.yahoo.vespa.flags.FlagId; -import com.yahoo.vespa.flags.json.FlagData; -import com.yahoo.vespa.flags.json.wire.WireFlagDataList; - -import java.io.OutputStream; -import java.util.Map; -import java.util.TreeMap; - -import static com.yahoo.yolean.Exceptions.uncheck; - -/** - * @author hakonhall - */ -public class FlagDataListResponse extends HttpResponse { - private static ObjectMapper mapper = new ObjectMapper(); - - private final String flagsV1Uri; - private final TreeMap flags; - private final boolean recursive; - - public FlagDataListResponse(String flagsV1Uri, Map flags, boolean recursive) { - super(Response.Status.OK); - this.flagsV1Uri = flagsV1Uri; - this.flags = new TreeMap<>(flags); - this.recursive = recursive; - } - - @Override - public void render(OutputStream outputStream) { - if (recursive) { - WireFlagDataList list = new WireFlagDataList(); - flags.values().forEach(flagData -> list.flags.add(flagData.toWire())); - list.serializeToOutputStream(outputStream); - } else { - ObjectNode rootNode = mapper.createObjectNode(); - ArrayNode flagsArray = rootNode.putArray("flags"); - flags.forEach((flagId, flagData) -> { - ObjectNode object = flagsArray.addObject(); - object.put("id", flagId.toString()); - object.put("url", flagsV1Uri + "/data/" + flagId.toString()); - }); - uncheck(() -> mapper.writeValue(outputStream, rootNode)); - } - } - - @Override - public String getContentType() { - return HttpConfigResponse.JSON_CONTENT_TYPE; - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataResponse.java deleted file mode 100644 index 054b218ff2d..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagDataResponse.java +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.http.HttpConfigResponse; -import com.yahoo.vespa.flags.json.FlagData; - -import java.io.OutputStream; - -/** - * @author hakonhall - */ -public class FlagDataResponse extends HttpResponse { - private final FlagData data; - - FlagDataResponse(FlagData data) { - super(Response.Status.OK); - this.data = data; - } - - @Override - public void render(OutputStream outputStream) { - data.serializeToOutputStream(outputStream); - } - - @Override - public String getContentType() { - return HttpConfigResponse.JSON_CONTENT_TYPE; - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagsHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagsHandler.java deleted file mode 100644 index 00f3d457d3d..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/FlagsHandler.java +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.google.inject.Inject; -import com.yahoo.container.jdisc.HttpRequest; -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.container.jdisc.LoggingRequestHandler; -import com.yahoo.restapi.Path; -import com.yahoo.vespa.config.server.http.HttpErrorResponse; -import com.yahoo.vespa.config.server.http.HttpHandler; -import com.yahoo.vespa.config.server.http.NotFoundException; -import com.yahoo.vespa.configserver.flags.FlagsDb; -import com.yahoo.vespa.flags.FlagDefinition; -import com.yahoo.vespa.flags.FlagId; -import com.yahoo.vespa.flags.Flags; -import com.yahoo.vespa.flags.json.FlagData; -import com.yahoo.yolean.Exceptions; - -import java.io.UncheckedIOException; -import java.net.URI; -import java.util.Objects; - -/** - * Handles /flags/v1 requests - * - * @author hakonhall - */ -public class FlagsHandler extends HttpHandler { - private final FlagsDb flagsDb; - - @Inject - public FlagsHandler(LoggingRequestHandler.Context context, FlagsDb flagsDb) { - super(context); - this.flagsDb = flagsDb; - } - - @Override - protected HttpResponse handleGET(HttpRequest request) { - Path path = new Path(request.getUri()); - if (path.matches("/flags/v1")) return new V1Response(flagsV1Uri(request), "data", "defined"); - if (path.matches("/flags/v1/data")) return getFlagDataList(request); - if (path.matches("/flags/v1/data/{flagId}")) return getFlagData(findFlagId(request, path)); - if (path.matches("/flags/v1/defined")) return new DefinedFlags(Flags.getAllFlags()); - if (path.matches("/flags/v1/defined/{flagId}")) return getDefinedFlag(findFlagId(request, path)); - throw new NotFoundException("Nothing at path '" + path + "'"); - } - - @Override - protected HttpResponse handlePUT(HttpRequest request) { - Path path = new Path(request.getUri()); - if (path.matches("/flags/v1/data/{flagId}")) return putFlagData(request, findFlagId(request, path)); - throw new NotFoundException("Nothing at path '" + path + "'"); - } - - @Override - protected HttpResponse handleDELETE(HttpRequest request) { - Path path = new Path(request.getUri()); - if (path.matches("/flags/v1/data/{flagId}")) return deleteFlagData(findFlagId(request, path)); - throw new NotFoundException("Nothing at path '" + path + "'"); - } - - private String flagsV1Uri(HttpRequest request) { - URI uri = request.getUri(); - String port = uri.getPort() < 0 ? "" : ":" + uri.getPort(); - return uri.getScheme() + "://" + uri.getHost() + port + "/flags/v1"; - } - - private HttpResponse getDefinedFlag(FlagId flagId) { - FlagDefinition definition = Flags.getFlag(flagId) - .orElseThrow(() -> new NotFoundException("Flag " + flagId + " not defined")); - return new DefinedFlag(definition); - } - - private HttpResponse getFlagDataList(HttpRequest request) { - return new FlagDataListResponse(flagsV1Uri(request), flagsDb.getAllFlags(), - Objects.equals(request.getProperty("recursive"), "true")); - } - - private HttpResponse getFlagData(FlagId flagId) { - FlagData data = flagsDb.getValue(flagId).orElseThrow(() -> new NotFoundException("Flag " + flagId + " not set")); - return new FlagDataResponse(data); - } - - private HttpResponse putFlagData(HttpRequest request, FlagId flagId) { - FlagData data; - try { - data = FlagData.deserialize(request.getData()); - } catch (UncheckedIOException e) { - return HttpErrorResponse.badRequest("Failed to deserialize request data: " + Exceptions.toMessageString(e)); - } - - if (!isForce(request)) { - FlagDefinition definition = Flags.getFlag(flagId).get(); // FlagId has been validated in findFlagId() - data.validate(definition.getUnboundFlag().serializer()); - } - - flagsDb.setValue(flagId, data); - return new OKResponse(); - } - - private HttpResponse deleteFlagData(FlagId flagId) { - flagsDb.removeValue(flagId); - return new OKResponse(); - } - - private FlagId findFlagId(HttpRequest request, Path path) { - FlagId flagId = new FlagId(path.get("flagId")); - - if (!isForce(request)) { - Flags.getFlag(flagId).orElseThrow(() -> - new NotFoundException("There is no flag '" + flagId + "' (use ?force=true to override)")); - } - - return flagId; - } - - private boolean isForce(HttpRequest request) { - return Objects.equals(request.getProperty("force"), "true"); - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/OKResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/OKResponse.java deleted file mode 100644 index 87c02ae56f1..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/OKResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.yahoo.container.jdisc.EmptyResponse; -import com.yahoo.jdisc.Response; -import com.yahoo.vespa.config.server.http.HttpConfigResponse; - -/** - * @author hakonhall - */ -public class OKResponse extends EmptyResponse { - public OKResponse() { - super(Response.Status.OK); - } - - @Override - public String getContentType() { - return HttpConfigResponse.JSON_CONTENT_TYPE; - } -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/V1Response.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/V1Response.java deleted file mode 100644 index 3594c801ca8..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/flags/V1Response.java +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.yahoo.jdisc.Response; -import com.yahoo.slime.Cursor; -import com.yahoo.slime.Slime; -import com.yahoo.text.Utf8; -import com.yahoo.vespa.config.SlimeUtils; -import com.yahoo.vespa.config.server.http.HttpConfigResponse; -import com.yahoo.vespa.config.server.http.StaticResponse; - -import java.util.Arrays; -import java.util.List; - -import static com.yahoo.yolean.Exceptions.uncheck; - -/** - * @author hakonhall - */ -public class V1Response extends StaticResponse { - public V1Response(String flagsV1Uri, String... names) { - super(Response.Status.OK, HttpConfigResponse.JSON_CONTENT_TYPE, generateBody(flagsV1Uri, Arrays.asList(names))); - } - - private static String generateBody(String flagsV1Uri, List names) { - Slime slime = new Slime(); - Cursor root = slime.setObject(); - names.forEach(name -> { - Cursor data = root.setObject(name); - data.setString("url", flagsV1Uri + "/" + name); - }); - return Utf8.toString(uncheck(() -> SlimeUtils.toJsonBytes(slime))); - } -} diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml index cfacd6ff8c9..e57024413c9 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -92,10 +92,6 @@ http://*/status - - http://*/flags/v1 - http://*/flags/v1/* - http://*/application/v2/tenant/ http://*/application/v2/tenant/* diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/flags/FlagsHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/flags/FlagsHandlerTest.java deleted file mode 100644 index 5ae6ce9820b..00000000000 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/flags/FlagsHandlerTest.java +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.http.flags; - -import com.yahoo.container.jdisc.HttpRequest; -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.jdisc.http.HttpRequest.Method; -import com.yahoo.text.Utf8; -import com.yahoo.vespa.config.server.http.SessionHandlerTest; -import com.yahoo.vespa.configserver.flags.db.FlagsDbImpl; -import com.yahoo.vespa.curator.mock.MockCurator; -import com.yahoo.vespa.flags.FetchVector; -import com.yahoo.vespa.flags.FlagId; -import com.yahoo.vespa.flags.Flags; -import com.yahoo.vespa.flags.UnboundBooleanFlag; -import org.junit.Test; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static com.yahoo.yolean.Exceptions.uncheck; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; - -/** - * @author hakonhall - */ -public class FlagsHandlerTest { - private static final UnboundBooleanFlag FLAG1 = Flags.defineFeatureFlag( - "id1", false, "desc1", "mod1"); - private static final UnboundBooleanFlag FLAG2 = Flags.defineFeatureFlag( - "id2", true, "desc2", "mod2", - FetchVector.Dimension.HOSTNAME, FetchVector.Dimension.APPLICATION_ID); - - private static final String FLAGS_V1_URL = "https://foo.com:4443/flags/v1"; - - private final FlagsDbImpl flagsDb = new FlagsDbImpl(new MockCurator()); - private final FlagsHandler handler = new FlagsHandler(FlagsHandler.testOnlyContext(), flagsDb); - - @Test - public void testV1() { - String expectedResponse = "{" + - Stream.of("data", "defined") - .map(name -> "\"" + name + "\":{\"url\":\"https://foo.com:4443/flags/v1/" + name + "\"}") - .collect(Collectors.joining(",")) + - "}"; - verifySuccessfulRequest(Method.GET, "", "", expectedResponse); - verifySuccessfulRequest(Method.GET, "/", "", expectedResponse); - } - - @Test - public void testDefined() { - try (Flags.Replacer replacer = Flags.clearFlagsForTesting()) { - fixUnusedWarning(replacer); - Flags.defineFeatureFlag("id", false, "desc", "mod", FetchVector.Dimension.HOSTNAME); - verifySuccessfulRequest(Method.GET, "/defined", "", - "{\"id\":{\"description\":\"desc\",\"modification-effect\":\"mod\",\"dimensions\":[\"hostname\"]}}"); - - verifySuccessfulRequest(Method.GET, "/defined/id", "", - "{\"description\":\"desc\",\"modification-effect\":\"mod\",\"dimensions\":[\"hostname\"]}"); - } - } - - private void fixUnusedWarning(Flags.Replacer replacer) { } - - @Test - public void testData() { - // PUT flag with ID id1 - verifySuccessfulRequest(Method.PUT, "/data/" + FLAG1.id(), - "{\n" + - " \"id\": \"id1\",\n" + - " \"rules\": [\n" + - " {\n" + - " \"value\": true\n" + - " }\n" + - " ]\n" + - "}", - ""); - - // GET on ID id1 should return the same as the put. - verifySuccessfulRequest(Method.GET, "/data/" + FLAG1.id(), - "", "{\"id\":\"id1\",\"rules\":[{\"value\":true}]}"); - - // List all flags should list only id1 - verifySuccessfulRequest(Method.GET, "/data", - "", "{\"flags\":[{\"id\":\"id1\",\"url\":\"https://foo.com:4443/flags/v1/data/id1\"}]}"); - - // Should be identical to above: suffix / on path should be ignored - verifySuccessfulRequest(Method.GET, "/data/", - "", "{\"flags\":[{\"id\":\"id1\",\"url\":\"https://foo.com:4443/flags/v1/data/id1\"}]}"); - - // Verify absent port => absent in response - assertThat(handleWithPort(Method.GET, -1, "/data", "", 200), - is("{\"flags\":[{\"id\":\"id1\",\"url\":\"https://foo.com/flags/v1/data/id1\"}]}")); - - // PUT id2 - verifySuccessfulRequest(Method.PUT, "/data/" + FLAG2.id(), - "{\n" + - " \"id\": \"id2\",\n" + - " \"rules\": [\n" + - " {\n" + - " \"conditions\": [\n" + - " {\n" + - " \"type\": \"whitelist\",\n" + - " \"dimension\": \"hostname\",\n" + - " \"values\": [ \"host1\", \"host2\" ]\n" + - " },\n" + - " {\n" + - " \"type\": \"blacklist\",\n" + - " \"dimension\": \"application\",\n" + - " \"values\": [ \"app1\", \"app2\" ]\n" + - " }\n" + - " ],\n" + - " \"value\": true\n" + - " }\n" + - " ],\n" + - " \"attributes\": {\n" + - " \"zone\": \"zone1\"\n" + - " }\n" + - "}\n", - ""); - - // GET on id2 should now return what was put - verifySuccessfulRequest(Method.GET, "/data/" + FLAG2.id(), "", - "{\"id\":\"id2\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"hostname\",\"values\":[\"host1\",\"host2\"]},{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"app1\",\"app2\"]}],\"value\":true}],\"attributes\":{\"zone\":\"zone1\"}}"); - - // The list of flag data should return id1 and id2 - verifySuccessfulRequest(Method.GET, "/data", - "", - "{\"flags\":[{\"id\":\"id1\",\"url\":\"https://foo.com:4443/flags/v1/data/id1\"},{\"id\":\"id2\",\"url\":\"https://foo.com:4443/flags/v1/data/id2\"}]}"); - - // Putting (overriding) id1 should work silently - verifySuccessfulRequest(Method.PUT, "/data/" + FLAG1.id(), - "{\n" + - " \"id\": \"id1\",\n" + - " \"rules\": [\n" + - " {\n" + - " \"value\": false\n" + - " }\n" + - " ]\n" + - "}\n", - ""); - - // Verify PUT - verifySuccessfulRequest(Method.GET, "/data/" + FLAG1.id(), "", "{\"id\":\"id1\",\"rules\":[{\"value\":false}]}"); - - // Get all recursivelly displays all flag data - verifySuccessfulRequest(Method.GET, "/data?recursive=true", "", - "{\"flags\":[{\"id\":\"id1\",\"rules\":[{\"value\":false}]},{\"id\":\"id2\",\"rules\":[{\"conditions\":[{\"type\":\"whitelist\",\"dimension\":\"hostname\",\"values\":[\"host1\",\"host2\"]},{\"type\":\"blacklist\",\"dimension\":\"application\",\"values\":[\"app1\",\"app2\"]}],\"value\":true}],\"attributes\":{\"zone\":\"zone1\"}}]}"); - - // Deleting both flags - verifySuccessfulRequest(Method.DELETE, "/data/" + FLAG1.id(), "", ""); - verifySuccessfulRequest(Method.DELETE, "/data/" + FLAG2.id(), "", ""); - - // And the list of data flags should now be empty - verifySuccessfulRequest(Method.GET, "/data", "", "{\"flags\":[]}"); - } - - @Test - public void testForcing() { - assertThat(handle(Method.PUT, "/data/" + new FlagId("undef"), "", 404), - containsString("There is no flag 'undef'")); - - assertThat(handle(Method.PUT, "/data/" + new FlagId("undef") + "?force=true", "", 400), - containsString("No content to map due to end-of-input")); - - assertThat(handle(Method.PUT, "/data/" + FLAG1.id(), "{}", 400), - containsString("Flag ID missing")); - - assertThat(handle(Method.PUT, "/data/" + FLAG1.id(), "{\"id\": \"id1\",\"rules\": [{\"value\":\"string\"}]}", 400), - containsString("Wrong type of JsonNode: STRING")); - - assertThat(handle(Method.PUT, "/data/" + FLAG1.id() + "?force=true", "{\"id\": \"id1\",\"rules\": [{\"value\":\"string\"}]}", 200), - is("")); - } - - private void verifySuccessfulRequest(Method method, String pathSuffix, String requestBody, String expectedResponseBody) { - assertThat(handle(method, pathSuffix, requestBody, 200), is(expectedResponseBody)); - } - - private String handle(Method method, String pathSuffix, String requestBody, int expectedStatus) { - return handleWithPort(method, 4443, pathSuffix, requestBody, expectedStatus); - } - - private String handleWithPort(Method method, int port, String pathSuffix, String requestBody, int expectedStatus) { - String uri = "https://foo.com" + (port < 0 ? "" : ":" + port) + "/flags/v1" + pathSuffix; - HttpRequest request = HttpRequest.createTestRequest(uri, method, makeInputStream(requestBody)); - HttpResponse response = handler.handle(request); - assertEquals(expectedStatus, response.getStatus()); - assertEquals("application/json", response.getContentType()); - return uncheck(() -> SessionHandlerTest.getRenderedString(response)); - } - - private InputStream makeInputStream(String content) { - return new ByteArrayInputStream(Utf8.toBytes(content)); - } -} \ No newline at end of file -- cgit v1.2.3