From 6828a15d31ac7d1ca1bfd560cfa05c393b3b7128 Mon Sep 17 00:00:00 2001 From: Hans Schulz Date: Thu, 7 Nov 2019 11:11:32 +0100 Subject: [PATCH 1/2] Handle JSON keys containing a dot from CF environment as a single path segment See gh-18915 --- .../CloudFoundryVcapEnvironmentPostProcessor.java | 3 +++ .../CloudFoundryVcapEnvironmentPostProcessorTests.java | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java index 587cd0eedc3..7fec2ea7b33 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java @@ -230,6 +230,9 @@ public class CloudFoundryVcapEnvironmentPostProcessor if (key.startsWith("[")) { return path + key; } + if (key.contains(".")) { + return path + "[" + key + "]"; + } return path + "." + key; } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java index 1dfc56386c2..3293acf56d9 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java @@ -117,6 +117,16 @@ public class CloudFoundryVcapEnvironmentPostProcessorTests { assertThat(getProperty("vcap.services.mysql.credentials.port")).isEqualTo("3306"); } + @Test + void testServicePropertiesContainingKeysWithDot() { + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, + "VCAP_SERVICES={\"user-provided\":[{\"name\":\"test\",\"label\":\"test-label\"," + + "\"credentials\":{\"key.with.dots\":\"some-value\"}}]}"); + this.initializer.postProcessEnvironment(this.context.getEnvironment(), null); + assertThat(getProperty("vcap.services.test.name")).isEqualTo("test"); + assertThat(getProperty("vcap.services.test.credentials[key.with.dots]")).isEqualTo("some-value"); + } + private String getProperty(String key) { return this.context.getEnvironment().getProperty(key); } From 544dca7f1b8a2adf7921f7c56b86f7abb8f37964 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Tue, 11 Feb 2020 14:47:25 -0800 Subject: [PATCH 2/2] Polish contribution Along with surrounding map keys with dot from VCAP_SERVICES with `[ ]`, this commit also does that for non-alphanumeric and `-` characters so that they are not stripped off later. See gh-18915 --- .../CloudFoundryVcapEnvironmentPostProcessor.java | 12 +++++++++++- ...udFoundryVcapEnvironmentPostProcessorTests.java | 14 +++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java index 7fec2ea7b33..8e0497ec28a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.java @@ -87,6 +87,7 @@ import org.springframework.util.StringUtils; * * @author Dave Syer * @author Andy Wilkinson + * @author Madhura Bhave * @since 1.3.0 */ public class CloudFoundryVcapEnvironmentPostProcessor @@ -230,10 +231,19 @@ public class CloudFoundryVcapEnvironmentPostProcessor if (key.startsWith("[")) { return path + key; } - if (key.contains(".")) { + if (shouldWrap(key)) { return path + "[" + key + "]"; } return path + "." + key; } + private boolean shouldWrap(String key) { + for (char ch : key.toCharArray()) { + if (!Character.isLowerCase(ch) && !Character.isDigit(ch) && ch != '-') { + return true; + } + } + return false; + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java index 3293acf56d9..84a35556a92 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/cloudfoundry/CloudFoundryVcapEnvironmentPostProcessorTests.java @@ -30,6 +30,8 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Dave Syer * @author Andy Wilkinson + * @author Hans Schulz + * @author Madhura Bhave */ public class CloudFoundryVcapEnvironmentPostProcessorTests { @@ -118,7 +120,7 @@ public class CloudFoundryVcapEnvironmentPostProcessorTests { } @Test - void testServicePropertiesContainingKeysWithDot() { + public void testServicePropertiesContainingKeysWithDot() { TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, "VCAP_SERVICES={\"user-provided\":[{\"name\":\"test\",\"label\":\"test-label\"," + "\"credentials\":{\"key.with.dots\":\"some-value\"}}]}"); @@ -127,6 +129,16 @@ public class CloudFoundryVcapEnvironmentPostProcessorTests { assertThat(getProperty("vcap.services.test.credentials[key.with.dots]")).isEqualTo("some-value"); } + @Test + public void testServicePropertiesContainingKeysWithUpperCaseAndNonAlphaNumericCharacters() { + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, + "VCAP_SERVICES={\"user-provided\":[{\"name\":\"test\",\"label\":\"test-label\"," + + "\"credentials\":{\"My-Key\":\"some-value\", \"foo@\":\"bar\"}}]}"); + this.initializer.postProcessEnvironment(this.context.getEnvironment(), null); + assertThat(getProperty("vcap.services.test.credentials[My-Key]")).isEqualTo("some-value"); + assertThat(getProperty("vcap.services.test.credentials[foo@]")).isEqualTo("bar"); + } + private String getProperty(String key) { return this.context.getEnvironment().getProperty(key); }