From 1711966b766f76265d7036589aa25e951ca8438f Mon Sep 17 00:00:00 2001 From: 98001yash Date: Mon, 2 Nov 2026 12:59:35 +0530 Subject: [PATCH 1/3] Trim whitespace from CredHub application names Signed-off-by: 98001yash --- .../CredhubEnvironmentRepository.java | 2 +- .../CredhubEnvironmentRepositoryTests.java | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java index 909526c7ce..2043757ec8 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java @@ -103,10 +103,10 @@ private List normalize(String commaDelimitedItems, String defaultItem) { */ private List normalize(String commaDelimitedItems) { var items = Arrays.stream(split(commaDelimitedItems)) + .map(String::trim) .distinct() .filter(StringUtils::hasText) .collect(Collectors.toList()); - Collections.reverse(items); return items; } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java index 26a3a56b77..78002de3f7 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java @@ -16,6 +16,7 @@ package org.springframework.cloud.config.server.environment; +import java.nio.file.Path; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; @@ -163,6 +164,18 @@ public void shouldRetrieveGivenMultipleApplicationNames() { assertThat(environment.getPropertySources().get(1).getSource()).isEqualTo(Map.of("k1", "v1")); } + @Test + public void shouldTrimWhitespaceFromApplicationNames() { + stubCredentials("/myApp/prod/myLabel", credential("c1", "k1", "v1")); + stubCredentials("/application/prod/myLabel", credential("c2", "k2", "v2")); + + Environment environment = this.credhubEnvironmentRepository.findOne("myApp, application ", "prod", "myLabel"); + + assertThat(environment.getPropertySources()).hasSize(2); + assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k1", "v1")); + assertThat(environment.getPropertySources().get(1).getSource()).isEqualTo(Map.of("k2", "v2")); + } + @Test public void shouldMergeWhenMoreThanOneCredentialsFound() { stubCredentials("/myApp/prod/myLabel", credential("c1", Map.of("k1", "v1")), @@ -327,7 +340,9 @@ public void shouldUseBasePathIfProvided() { @SafeVarargs private void stubCredentials(String path, CredentialDetails... details) { - when(this.credhubCredentialOperations.findByPath(path)).thenReturn( + String normalizedPath = Path.of("/", path.substring(1).split("/")).toString(); + + when(this.credhubCredentialOperations.findByPath(normalizedPath)).thenReturn( Arrays.stream(details).map(it -> new CredentialSummary(it.getName())).collect(Collectors.toList())); for (CredentialDetails d : details) { From bde84b21897e0eae16038e8358eb883a287d0d2c Mon Sep 17 00:00:00 2001 From: 98001yash Date: Tue, 3 Nov 2026 02:48:33 +0530 Subject: [PATCH 2/3] Trim whitespace from CredHub application names Signed-off-by: 98001yash --- .../CredhubEnvironmentRepository.java | 23 ++++- .../CredhubEnvironmentRepositoryTests.java | 96 +++++++++++-------- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java index 2043757ec8..1dbefc84cc 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java @@ -30,7 +30,6 @@ import org.springframework.credhub.support.CredentialDetails; import org.springframework.credhub.support.SimpleCredentialName; import org.springframework.credhub.support.json.JsonCredential; -import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import static java.util.stream.Collectors.toMap; @@ -67,10 +66,10 @@ public CredhubEnvironmentRepository(CredHubOperations credHubOperations, Credhub @Override public Environment findOne(String application, String profile, String label) { - if (ObjectUtils.isEmpty(profile)) { + if (!StringUtils.hasText(profile)) { profile = DEFAULT_PROFILE; } - if (ObjectUtils.isEmpty(label)) { + if (!StringUtils.hasText(label)) { label = this.defaultLabel; } @@ -78,7 +77,23 @@ public Environment findOne(String application, String profile, String label) { List profiles = normalize(profile, DEFAULT_PROFILE); List labels = normalize(label); - Environment environment = new Environment(application, split(profile), label, null, null); + String normalizedApplication = Arrays.stream(split(application)) + .map(String::trim) + .filter(StringUtils::hasText) + .collect(Collectors.joining(",")); + + String[] normalizedProfiles = Arrays.stream(split(profile)) + .map(String::trim) + .filter(StringUtils::hasText) + .toArray(String[]::new); + + String normalizedLabel = Arrays.stream(split(label)) + .map(String::trim) + .filter(StringUtils::hasText) + .collect(Collectors.joining(",")); + + Environment environment = new Environment(normalizedApplication, normalizedProfiles, normalizedLabel, null, + null); for (String l : labels) { for (String prof : profiles) { for (String app : applications) { diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java index 78002de3f7..4e42f617e8 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepositoryTests.java @@ -57,7 +57,7 @@ public void setUp() { @Test public void shouldDisplayEmptyPropertiesWhenNoPathFound() { - stubCredentials("/myApp/prod/myLabel"); + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString()); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "prod", "myLabel"); @@ -72,7 +72,7 @@ public void shouldDisplayEmptyPropertiesWhenNoPathFound() { @Test public void shouldRetrieveDefaultsWhenNoLabelNorProfileProvided() { - stubCredentials("/myApp/default/master", credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "myApp", "default", "master").toString(), credential("c1", "k1", "v1")); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", null, null); @@ -81,14 +81,28 @@ public void shouldRetrieveDefaultsWhenNoLabelNorProfileProvided() { assertThat(environment.getLabel()).isEqualTo("master"); assertThat(environment.getPropertySources()).hasSize(1); + assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("credhub-myApp-default-master"); + assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k1", "v1")); + } + + @Test + public void shouldRetrieveDefaultsWhenWhitespaceOnlyProfileAndLabelProvided() { + stubCredentials(Path.of("/", "myApp", "default", "master").toString(), credential("c1", "k1", "v1")); + + Environment environment = this.credhubEnvironmentRepository.findOne("myApp", " ", " "); + assertThat(environment.getName()).isEqualTo("myApp"); + assertThat(environment.getProfiles()).containsExactly("default"); + assertThat(environment.getLabel()).isEqualTo("master"); + + assertThat(environment.getPropertySources()).hasSize(1); assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("credhub-myApp-default-master"); assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k1", "v1")); } @Test public void shouldRetrieveGivenProfileAndLabel() { - stubCredentials("/myApp/prod/myLabel", credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString(), credential("c1", "k1", "v1")); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "prod", "myLabel"); @@ -97,15 +111,14 @@ public void shouldRetrieveGivenProfileAndLabel() { assertThat(environment.getLabel()).isEqualTo("myLabel"); assertThat(environment.getPropertySources()).hasSize(1); - assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("credhub-myApp-prod-myLabel"); assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k1", "v1")); } @Test public void shouldRetrieveGivenMultipleProfiles() { - stubCredentials("/myApp/prod/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/myApp/cloud/myLabel", credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "myApp", "cloud", "myLabel").toString(), credential("c2", "k2", "v2")); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "prod,cloud", "myLabel"); @@ -124,9 +137,9 @@ public void shouldRetrieveGivenMultipleProfiles() { @Test public void shouldRetrieveGivenLabelsProfiles() { - stubCredentials("/myApp/prod/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/myApp/cloud/mySecondLabel", credential("c2", "k2", "v2")); - stubCredentials("/myApp/prod/master", credential("c3", "k3", "v3")); + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "myApp", "cloud", "mySecondLabel").toString(), credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "myApp", "prod", "master").toString(), credential("c3", "k3", "v3")); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "prod,cloud", "myLabel,mySecondLabel"); @@ -146,8 +159,8 @@ public void shouldRetrieveGivenLabelsProfiles() { @Test public void shouldRetrieveGivenMultipleApplicationNames() { - stubCredentials("/app1/default/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/app2/default/myLabel", credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "app1", "default", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "app2", "default", "myLabel").toString(), credential("c2", "k2", "v2")); Environment environment = this.credhubEnvironmentRepository.findOne("app1,app2", null, "myLabel"); @@ -166,8 +179,8 @@ public void shouldRetrieveGivenMultipleApplicationNames() { @Test public void shouldTrimWhitespaceFromApplicationNames() { - stubCredentials("/myApp/prod/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/application/prod/myLabel", credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "application", "prod", "myLabel").toString(), credential("c2", "k2", "v2")); Environment environment = this.credhubEnvironmentRepository.findOne("myApp, application ", "prod", "myLabel"); @@ -176,9 +189,19 @@ public void shouldTrimWhitespaceFromApplicationNames() { assertThat(environment.getPropertySources().get(1).getSource()).isEqualTo(Map.of("k2", "v2")); } + @Test + public void shouldTrimWhitespaceFromEnvironmentMetadata() { + Environment environment = this.credhubEnvironmentRepository.findOne(" myApp , app2 ", " prod , cloud ", + " myLabel , mySecondLabel "); + + assertThat(environment.getName()).isEqualTo("myApp,app2"); + assertThat(environment.getProfiles()).containsExactly("prod", "cloud"); + assertThat(environment.getLabel()).isEqualTo("myLabel,mySecondLabel"); + } + @Test public void shouldMergeWhenMoreThanOneCredentialsFound() { - stubCredentials("/myApp/prod/myLabel", credential("c1", Map.of("k1", "v1")), + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString(), credential("c1", Map.of("k1", "v1")), credential("c2", Map.of("k2", "v2"))); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "prod", "myLabel"); @@ -194,12 +217,12 @@ public void shouldMergeWhenMoreThanOneCredentialsFound() { @Test public void shouldIncludeDefaultApplicationWhenOtherProvided() { - stubCredentials("/app1/prod/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/app2/prod/myLabel", credential("c2", "k2", "v2")); - stubCredentials("/application/prod/myLabel", credential("c3", "k3", "v3")); - stubCredentials("/app1/default/myLabel", credential("c4", "k4", "v4")); - stubCredentials("/app2/default/myLabel", credential("c5", "k5", "v5")); - stubCredentials("/application/default/myLabel", credential("c6", "k6", "v6")); + stubCredentials(Path.of("/", "app1", "prod", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "app2", "prod", "myLabel").toString(), credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "application", "prod", "myLabel").toString(), credential("c3", "k3", "v3")); + stubCredentials(Path.of("/", "app1", "default", "myLabel").toString(), credential("c4", "k4", "v4")); + stubCredentials(Path.of("/", "app2", "default", "myLabel").toString(), credential("c5", "k5", "v5")); + stubCredentials(Path.of("/", "application", "default", "myLabel").toString(), credential("c6", "k6", "v6")); Environment environment = this.credhubEnvironmentRepository.findOne("app1,app2", "prod", "myLabel"); @@ -230,12 +253,12 @@ public void shouldIncludeDefaultApplicationWhenOtherProvided() { @Test public void shouldIncludeDefaultProfileWhenOtherProvided() { - stubCredentials("/myApp/dev/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/application/dev/myLabel", credential("c2", "k2", "v2")); - stubCredentials("/myApp/prod/myLabel", credential("c3", "k3", "v3")); - stubCredentials("/application/prod/myLabel", credential("c4", "k4", "v4")); - stubCredentials("/myApp/default/myLabel", credential("c5", "k5", "v5")); - stubCredentials("/application/default/myLabel", credential("c6", "k6", "v6")); + stubCredentials(Path.of("/", "myApp", "dev", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "application", "dev", "myLabel").toString(), credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "myApp", "prod", "myLabel").toString(), credential("c3", "k3", "v3")); + stubCredentials(Path.of("/", "application", "prod", "myLabel").toString(), credential("c4", "k4", "v4")); + stubCredentials(Path.of("/", "myApp", "default", "myLabel").toString(), credential("c5", "k5", "v5")); + stubCredentials(Path.of("/", "application", "default", "myLabel").toString(), credential("c6", "k6", "v6")); Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "dev,prod", "myLabel"); @@ -266,10 +289,10 @@ public void shouldIncludeDefaultProfileWhenOtherProvided() { @Test public void shouldIncludeDefaultProfileAndApplicationNameAtTheEnd() { - stubCredentials("/myApp/dev/myLabel", credential("c1", "k1", "v1")); - stubCredentials("/application/dev/myLabel", credential("c2", "k2", "v2")); - stubCredentials("/myApp/default/myLabel", credential("c3", "k3", "v3")); - stubCredentials("/application/default/myLabel", credential("c4", "k4", "v4")); + stubCredentials(Path.of("/", "myApp", "dev", "myLabel").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "application", "dev", "myLabel").toString(), credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "myApp", "default", "myLabel").toString(), credential("c3", "k3", "v3")); + stubCredentials(Path.of("/", "application", "default", "myLabel").toString(), credential("c4", "k4", "v4")); Environment environment = this.credhubEnvironmentRepository.findOne("application,myApp", "default,dev", "myLabel"); @@ -295,8 +318,8 @@ public void shouldIncludeDefaultProfileAndApplicationNameAtTheEnd() { @Test public void shouldUseCustomDefaultLabelIfProvided() { - stubCredentials("/myApp/default/master", credential("c1", "k1", "v1")); - stubCredentials("/myApp/default/main", credential("c2", "k2", "v2")); + stubCredentials(Path.of("/", "myApp", "default", "master").toString(), credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "myApp", "default", "main").toString(), credential("c2", "k2", "v2")); var credhubOperations = Mockito.mock(CredHubOperations.class); when(credhubOperations.credentials()).thenReturn(this.credhubCredentialOperations); @@ -311,14 +334,14 @@ public void shouldUseCustomDefaultLabelIfProvided() { assertThat(environment.getLabel()).isEqualTo("main"); assertThat(environment.getPropertySources()).hasSize(1); - assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("credhub-myApp-default-main"); assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k2", "v2")); } @Test public void shouldUseBasePathIfProvided() { - stubCredentials("/base/path/myApp/default/master", credential("c1", "k1", "v1")); + stubCredentials(Path.of("/", "base", "path", "myApp", "default", "master").toString(), + credential("c1", "k1", "v1")); var credhubOperations = Mockito.mock(CredHubOperations.class); when(credhubOperations.credentials()).thenReturn(this.credhubCredentialOperations); @@ -333,16 +356,13 @@ public void shouldUseBasePathIfProvided() { assertThat(environment.getLabel()).isEqualTo("master"); assertThat(environment.getPropertySources()).hasSize(1); - assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("credhub-myApp-default-master"); assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k1", "v1")); } @SafeVarargs private void stubCredentials(String path, CredentialDetails... details) { - String normalizedPath = Path.of("/", path.substring(1).split("/")).toString(); - - when(this.credhubCredentialOperations.findByPath(normalizedPath)).thenReturn( + when(this.credhubCredentialOperations.findByPath(path)).thenReturn( Arrays.stream(details).map(it -> new CredentialSummary(it.getName())).collect(Collectors.toList())); for (CredentialDetails d : details) { From 7ef4cbd5a0ac0d3687dff8805aabf256818f86c6 Mon Sep 17 00:00:00 2001 From: 98001yash Date: Tue, 3 Nov 2026 20:31:30 +0530 Subject: [PATCH 3/3] Reuse normalized values in CredHub environment Signed-off-by: 98001yash --- .../CredhubEnvironmentRepository.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java index 1dbefc84cc..ddb26e37be 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentRepository.java @@ -77,23 +77,18 @@ public Environment findOne(String application, String profile, String label) { List profiles = normalize(profile, DEFAULT_PROFILE); List labels = normalize(label); - String normalizedApplication = Arrays.stream(split(application)) - .map(String::trim) - .filter(StringUtils::hasText) - .collect(Collectors.joining(",")); + List normalizedApplications = normalize(application); + Collections.reverse(normalizedApplications); - String[] normalizedProfiles = Arrays.stream(split(profile)) - .map(String::trim) - .filter(StringUtils::hasText) - .toArray(String[]::new); + List normalizedProfiles = normalize(profile); + Collections.reverse(normalizedProfiles); - String normalizedLabel = Arrays.stream(split(label)) - .map(String::trim) - .filter(StringUtils::hasText) - .collect(Collectors.joining(",")); + List normalizedLabels = normalize(label); + Collections.reverse(normalizedLabels); + + Environment environment = new Environment(String.join(",", normalizedApplications), + normalizedProfiles.toArray(new String[0]), String.join(",", normalizedLabels), null, null); - Environment environment = new Environment(normalizedApplication, normalizedProfiles, normalizedLabel, null, - null); for (String l : labels) { for (String prof : profiles) { for (String app : applications) {