From e94b4039a67e9f705df29041fba5be9fb492cdc9 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 19 May 2015 10:53:51 +0100 Subject: [PATCH] Strip "document" prefix from YAML by default It's pretty uncommon for Spring apps, but sometimes YAML is not a map, but more naturally a String or Collection. In these cases Spring puts a "document" prefix in the Map it creates, so we can strip that off if the user prefers it. Fixes gh-143 --- .../server/ConfigServerMvcConfiguration.java | 1 + .../config/server/ConfigServerProperties.java | 14 ++++++++ .../config/server/EnvironmentController.java | 25 ++++++++++++++- .../server/EnvironmentControllerTests.java | 32 +++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerMvcConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerMvcConfiguration.java index ba9091a2..ac94539b 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerMvcConfiguration.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerMvcConfiguration.java @@ -44,6 +44,7 @@ public class ConfigServerMvcConfiguration { EnvironmentController controller = new EnvironmentController(repository, encryptionController()); controller.setDefaultLabel(getDefaultLabel()); controller.setOverrides(server.getOverrides()); + controller.setStripDocumentFromYaml(server.isStripDocumentFromYaml()); return controller; } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerProperties.java index 127fe913..6b9b6acc 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/ConfigServerProperties.java @@ -51,6 +51,12 @@ public class ConfigServerProperties { */ private Map overrides = new LinkedHashMap(); + /** + * Flag to indicate that YAML documents that are text or collections (not a map) + * should be returned in "native" form. + */ + private boolean stripDocumentFromYaml = true; + public String getDefaultLabel() { return defaultLabel; } @@ -83,4 +89,12 @@ public class ConfigServerProperties { this.overrides = overrides; } + public boolean isStripDocumentFromYaml() { + return stripDocumentFromYaml; + } + + public void setStripDocumentFromYaml(boolean stripDocumentFromYaml) { + this.stripDocumentFromYaml = stripDocumentFromYaml; + } + } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EnvironmentController.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EnvironmentController.java index 5387a3b1..278f660b 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EnvironmentController.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/EnvironmentController.java @@ -17,6 +17,7 @@ package org.springframework.cloud.config.server; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -27,7 +28,6 @@ import java.util.TreeMap; import javax.servlet.http.HttpServletResponse; -import org.yaml.snakeyaml.Yaml; import org.springframework.boot.bind.PropertiesConfigurationFactory; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.environment.PropertySource; @@ -43,6 +43,9 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.yaml.snakeyaml.DumperOptions.FlowStyle; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.nodes.Tag; /** * @author Dave Syer @@ -63,6 +66,8 @@ public class EnvironmentController { private Map overrides = new LinkedHashMap<>(); + private boolean stripDocument = true; + public EnvironmentController(EnvironmentRepository repository, EncryptionController encryption) { super(); @@ -71,6 +76,15 @@ public class EnvironmentController { this.encryption = encryption; } + /** + * Flag to indicate that YAML documents which are not a map should be stripped of the + * "document" prefix that is added by Spring (to facilitate conversion to Properties). + * @param stripDocument the flag to set + */ + public void setStripDocumentFromYaml(boolean stripDocument) { + this.stripDocument = stripDocument; + } + @RequestMapping("/{name}/{profiles:.*[^-].*}") public Environment defaultLabel(@PathVariable String name, @PathVariable String profiles) { @@ -141,6 +155,15 @@ public class EnvironmentController { @PathVariable String profiles, @PathVariable String label) throws Exception { validateNameAndProfiles(name, profiles); Map result = convertToMap(labelled(name, profiles, label)); + if (this.stripDocument && result.size() == 1 + && result.keySet().iterator().next().equals("document")) { + Object value = result.get("document"); + if (value instanceof Collection) { + return getSuccess(new Yaml().dumpAs(value, Tag.SEQ, FlowStyle.BLOCK)); + } else { + return getSuccess(new Yaml().dumpAs(value, Tag.STR, FlowStyle.BLOCK)); + } + } return getSuccess(new Yaml().dumpAsMap(result)); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EnvironmentControllerTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EnvironmentControllerTests.java index 19b69e8b..22100990 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EnvironmentControllerTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/EnvironmentControllerTests.java @@ -91,6 +91,38 @@ public class EnvironmentControllerTests { assertEquals("a:\n b:\n - c\n - d\n", yaml); } + @Test + public void textAtTopLevelInYaml() throws Exception { + Map map = new LinkedHashMap(); + map.put("document", "blah"); + environment.add(new PropertySource("one", map)); + Mockito.when(repository.findOne("foo", "bar", "master")).thenReturn(environment); + String yaml = controller.yaml("foo", "bar").getBody(); + assertEquals("blah\n", yaml); + } + + @Test + public void arrayAtTopLevelInYaml() throws Exception { + Map map = new LinkedHashMap(); + map.put("document[0]", "c"); + map.put("document[1]", "d"); + environment.add(new PropertySource("one", map)); + Mockito.when(repository.findOne("foo", "bar", "master")).thenReturn(environment); + String yaml = controller.yaml("foo", "bar").getBody(); + assertEquals("- c\n- d\n", yaml); + } + + @Test + public void arrayObObjectAtTopLevelInYaml() throws Exception { + Map map = new LinkedHashMap(); + map.put("document[0].a", "c"); + map.put("document[1].a", "d"); + environment.add(new PropertySource("one", map)); + Mockito.when(repository.findOne("foo", "bar", "master")).thenReturn(environment); + String yaml = controller.yaml("foo", "bar").getBody(); + assertEquals("- a: c\n- a: d\n", yaml); + } + @Test public void arrayOfObjectInYaml() throws Exception { Map map = new LinkedHashMap();