From 73f4bf56dc43d0698c1d5db6463dddb07005b4b2 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Wed, 2 Oct 2024 10:15:32 -0400 Subject: [PATCH] Initial implementation to support multiple labels in SVN and Git EnvironmentRepos (#2561) Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com> --- .../AbstractScmEnvironmentRepository.java | 35 +++++++++++++++---- .../server/CompositeIntegrationTests.java | 10 ++++-- .../JGitEnvironmentRepositoryTests.java | 7 ++++ .../SVNKitEnvironmentRepositoryTests.java | 9 +++++ 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AbstractScmEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AbstractScmEnvironmentRepository.java index 3b8a253c..2373afaf 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AbstractScmEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AbstractScmEnvironmentRepository.java @@ -16,6 +16,11 @@ package org.springframework.cloud.config.server.environment; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import io.micrometer.observation.ObservationRegistry; import org.springframework.cloud.config.environment.Environment; @@ -23,6 +28,7 @@ import org.springframework.cloud.config.server.support.AbstractScmAccessor; import org.springframework.cloud.config.server.support.AbstractScmAccessorProperties; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.util.StringUtils; /** * @author Dave Syer @@ -57,12 +63,29 @@ public abstract class AbstractScmEnvironmentRepository extends AbstractScmAccess @Override public synchronized Environment findOne(String application, String profile, String label, boolean includeOrigin) { - NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(getEnvironment(), - new NativeEnvironmentProperties(), this.observationRegistry); - Locations locations = getLocations(application, profile, label); - delegate.setSearchLocations(locations.getLocations()); - Environment result = delegate.findOne(application, profile, "", includeOrigin); - result.setVersion(locations.getVersion()); + Environment result; + if (StringUtils.hasText(label) && label.contains(",")) { + List labels = Arrays.asList(StringUtils.commaDelimitedListToStringArray(label)); + Collections.reverse(labels); + List environmentRepositories = new ArrayList<>(); + Environment env = new Environment(application, new String[] { profile }, label, null, null); + for (String l : labels) { + NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(getEnvironment(), + new NativeEnvironmentProperties(), this.observationRegistry); + Locations locations = getLocations(application, profile, l); + delegate.setSearchLocations(locations.getLocations()); + env.addAll(delegate.findOne(application, profile, "", includeOrigin).getPropertySources()); + } + result = env; + } + else { + NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(getEnvironment(), + new NativeEnvironmentProperties(), this.observationRegistry); + Locations locations = getLocations(application, profile, label); + delegate.setSearchLocations(locations.getLocations()); + result = delegate.findOne(application, profile, "", includeOrigin); + result.setVersion(locations.getVersion()); + } result.setLabel(label); return this.cleaner.clean(result, getWorkingDirectory().toURI().toString(), getUri()); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeIntegrationTests.java index 660751a9..51ee665d 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeIntegrationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeIntegrationTests.java @@ -19,6 +19,7 @@ package org.springframework.cloud.config.server; import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.util.SystemReader; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @@ -41,6 +42,7 @@ import static org.springframework.cloud.config.server.test.ConfigServerTestUtils */ public class CompositeIntegrationTests { + @Nested @SpringBootTest(classes = TestConfigServerApplication.class, properties = { "spring.config.name:compositeconfigserver", "spring.cloud.config.server.svn.uri:file:///./target/repos/svn-config-repo", @@ -49,7 +51,7 @@ public class CompositeIntegrationTests { "spring.cloud.config.server.git.order:1" }, webEnvironment = RANDOM_PORT) @ActiveProfiles({ "test", "git", "subversion" }) - public static class StaticTests { + class StaticTests { @LocalServerPort private int port; @@ -92,6 +94,7 @@ public class CompositeIntegrationTests { } + @Nested @SpringBootTest(classes = TestConfigServerApplication.class, properties = { "spring.config.name:compositeconfigserver", "spring.cloud.config.server.svn.uri:file:///./target/repos/svn-config-repo", @@ -100,7 +103,7 @@ public class CompositeIntegrationTests { "spring.cloud.config.server.git.order:1", "spring.cloud.config.server.reverseLocationOrder:true" }, webEnvironment = RANDOM_PORT) @ActiveProfiles({ "test", "git", "subversion" }) - public static class ReverseLocationOrderTest { + class ReverseLocationOrderTest { @LocalServerPort private int port; @@ -130,6 +133,7 @@ public class CompositeIntegrationTests { } + @Nested @SpringBootTest(classes = TestConfigServerApplication.class, properties = { "spring.config.name:compositeconfigserver", "spring.cloud.config.server.composite[0].uri:file:./target/repos/config-repo", @@ -138,7 +142,7 @@ public class CompositeIntegrationTests { "spring.cloud.config.server.composite[1].type:svn" }, webEnvironment = RANDOM_PORT) @ActiveProfiles({ "test", "composite" }) - public static class ListTests { + class ListTests { @LocalServerPort private int port; diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java index 7ccae2d3..30d4e5ee 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java @@ -210,6 +210,13 @@ public class JGitEnvironmentRepositoryTests { assertVersion(environment); } + @Test + public void multipleLabels() { + this.repository.setBasedir(this.basedir); + Environment environment = this.repository.findOne("bar", "staging", "master,foo,raw"); + assertThat(environment.getPropertySources()).hasSize(6); + } + @Test public void basedirExists() throws Exception { assertThat(this.basedir.mkdirs()).isTrue(); diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/SVNKitEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/SVNKitEnvironmentRepositoryTests.java index 22cc50e1..a14095c6 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/SVNKitEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/SVNKitEnvironmentRepositoryTests.java @@ -115,6 +115,15 @@ public class SVNKitEnvironmentRepositoryTests { assertThat(environment.getPropertySources().get(1).getName()).contains("application.yml"); } + @Test + public void testMultipleLabels() { + Environment environment = this.repository.findOne("bar", "staging", "branches/demobranch,trunk"); + assertThat(environment.getPropertySources()).hasSize(3); + assertThat(environment.getPropertySources().get(0).getName()).contains("bar.properties"); + assertThat(environment.getPropertySources().get(1).getName()).contains("application.yml"); + assertThat(environment.getPropertySources().get(2).getName()).contains("branches/demobranch/bar.properties"); + } + @Test public void invalidLabel() { Assertions.assertThatThrownBy(() -> {