From b3c179f6bb2d82c98b0a7a8f4dce6495e24526fd Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 19 Dec 2024 11:50:05 -0500 Subject: [PATCH] Honor order set in configuration properties for composite profile (#2686) Fixes #2438 --- ...teEnvironmentBeanFactoryPostProcessor.java | 7 ++- ...wsParameterStoreEnvironmentProperties.java | 3 +- .../AwsS3EnvironmentProperties.java | 2 +- ...wsSecretsManagerEnvironmentProperties.java | 3 +- .../CredhubEnvironmentProperties.java | 3 +- ...gleSecretManagerEnvironmentProperties.java | 3 +- .../JdbcEnvironmentProperties.java | 3 +- .../NativeEnvironmentProperties.java | 3 +- .../RedisEnvironmentProperties.java | 3 +- .../VaultEnvironmentProperties.java | 3 +- .../AbstractScmAccessorProperties.java | 4 +- .../EnvironmentRepositoryProperties.java | 7 +++ .../server/CompositeIntegrationTests.java | 50 +++++++++++++++++++ 13 files changed, 73 insertions(+), 21 deletions(-) diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/composite/CompositeEnvironmentBeanFactoryPostProcessor.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/composite/CompositeEnvironmentBeanFactoryPostProcessor.java index f5aa4955f0..c0172628dd 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/composite/CompositeEnvironmentBeanFactoryPostProcessor.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/composite/CompositeEnvironmentBeanFactoryPostProcessor.java @@ -29,6 +29,7 @@ import org.springframework.boot.context.properties.bind.Binder; import org.springframework.cloud.config.server.environment.EnvironmentRepository; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; +import org.springframework.core.Ordered; import org.springframework.core.env.Environment; /** @@ -80,7 +81,11 @@ private

P bindProperties(int index, Binder binder = Binder.get(environment); String environmentConfigurationPropertyName = String.format("spring.cloud.config.server.composite[%d]", index); P properties = binder.bindOrCreate(environmentConfigurationPropertyName, propertiesClass); - properties.setOrder(index + 1); + if (properties instanceof Ordered + && ((Ordered) properties).getOrder() == EnvironmentRepositoryProperties.DEFAULT_ORDER) { + // The order is not set, it is the default so set it to the order in the list + properties.setOrder(index + 1); + } return properties; } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentProperties.java index 5577dcfa8e..f8a8b2290d 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsParameterStoreEnvironmentProperties.java @@ -24,7 +24,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; import org.springframework.validation.annotation.Validated; /** @@ -45,7 +44,7 @@ public class AwsParameterStoreEnvironmentProperties implements EnvironmentReposi /** * The order of the environment repository. */ - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; /** * The region to be used by the AWS Parameter Store client. diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentProperties.java index c14a13efb0..5213d40a6d 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentProperties.java @@ -40,7 +40,7 @@ public class AwsS3EnvironmentProperties implements EnvironmentRepositoryProperti */ private String bucket; - private int order; + private int order = DEFAULT_ORDER; public String getRegion() { return region; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java index f9decfa954..d6f00fa959 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java @@ -21,7 +21,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; /** * @author Tejas Pandilwar @@ -62,7 +61,7 @@ public class AwsSecretsManagerEnvironmentProperties implements EnvironmentReposi /** * The order of the environment repository. */ - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; /** * Prefix indicating first level for every property loaded from AWS Secrets Manager. diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentProperties.java index f9380ec615..61844ba88a 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/CredhubEnvironmentProperties.java @@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; /** * @author Alberto C. Ríos @@ -32,7 +31,7 @@ public class CredhubEnvironmentProperties implements EnvironmentRepositoryProper /** The default label to be used when is not provided by client applications. */ private String defaultLabel = "master"; - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; public String getPath() { return this.path; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/GoogleSecretManagerEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/GoogleSecretManagerEnvironmentProperties.java index dd472d3995..49b128a4b1 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/GoogleSecretManagerEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/GoogleSecretManagerEnvironmentProperties.java @@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; /** * @author Jose Maria Alvarez @@ -26,7 +25,7 @@ @ConfigurationProperties("spring.cloud.config.server.gcp-secret-manager") public class GoogleSecretManagerEnvironmentProperties implements EnvironmentRepositoryProperties { - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; private String applicationLabel = "application"; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JdbcEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JdbcEnvironmentProperties.java index 16079d4f81..089d7d5ca4 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JdbcEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JdbcEnvironmentProperties.java @@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; /** * @author Dylan Roberts @@ -38,7 +37,7 @@ public class JdbcEnvironmentProperties implements EnvironmentRepositoryPropertie */ private boolean enabled = true; - private int order = Ordered.LOWEST_PRECEDENCE - 10; + private int order = DEFAULT_ORDER - 10; /** SQL used to query database for keys and values. */ private String sql = DEFAULT_SQL; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentProperties.java index e78dc66f18..ac8a74adff 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentProperties.java @@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; /** * @author Dylan Roberts @@ -49,7 +48,7 @@ public class NativeEnvironmentProperties implements EnvironmentRepositoryPropert */ private String version; - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; public Boolean getFailOnError() { return this.failOnError; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/RedisEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/RedisEnvironmentProperties.java index d1d6595a45..26dee40228 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/RedisEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/RedisEnvironmentProperties.java @@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties; -import org.springframework.core.Ordered; /** * @author Piotr Mińkowski @@ -26,7 +25,7 @@ @ConfigurationProperties("spring.cloud.config.server.redis") public class RedisEnvironmentProperties implements EnvironmentRepositoryProperties { - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; public int getOrder() { return this.order; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java index 2e25ee9050..c5386e8c60 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java @@ -26,7 +26,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.config.server.proxy.ProxyHostProperties; import org.springframework.cloud.config.server.support.HttpEnvironmentRepositoryProperties; -import org.springframework.core.Ordered; import org.springframework.core.io.Resource; import org.springframework.validation.annotation.Validated; @@ -83,7 +82,7 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp */ private Map proxy = new HashMap<>(); - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; /** * Value to indicate which version of Vault kv backend is used. Defaults to 1. diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AbstractScmAccessorProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AbstractScmAccessorProperties.java index 3261876785..bc159d8d15 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AbstractScmAccessorProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/AbstractScmAccessorProperties.java @@ -18,8 +18,6 @@ import java.io.File; -import org.springframework.core.Ordered; - /** * @author Dylan Roberts */ @@ -63,7 +61,7 @@ public class AbstractScmAccessorProperties implements EnvironmentRepositoryPrope private boolean strictHostKeyChecking = true; /** The order of the environment repository. */ - private int order = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; /** The default label to be used with the remote repository. */ private String defaultLabel; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentRepositoryProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentRepositoryProperties.java index c5e7f47c5a..b9b501286e 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentRepositoryProperties.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentRepositoryProperties.java @@ -16,11 +16,18 @@ package org.springframework.cloud.config.server.support; +import org.springframework.core.Ordered; + /** * @author Dylan Roberts */ public interface EnvironmentRepositoryProperties { + /** + * Default order value. + */ + int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE; + void setOrder(int order); } 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 660751a9d0..44c71e1ede 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 @@ -92,6 +92,56 @@ public void resourceEndpointsWork() { } + @SpringBootTest(classes = TestConfigServerApplication.class, properties = { + "spring.config.name:compositeconfigserver", "spring.cloud.config.server.composite[0].type: svn", + "spring.cloud.config.server.composite[0].uri:file:///./target/repos/svn-config-repo", + "spring.cloud.config.server.composite[0].order:2", "spring.cloud.config.server.composite[1].type: git", + "spring.cloud.config.server.composite[1].uri:file:./target/repos/config-repo", + "spring.cloud.config.server.composite[1].order:1" }, webEnvironment = RANDOM_PORT) + @ActiveProfiles({ "test", "composite" }) + public static class StaticCompositeTests { + + @LocalServerPort + private int port; + + @BeforeAll + public static void init() throws Exception { + // mock Git configuration to make tests independent of local Git configuration + SystemReader.setInstance(new MockSystemReader()); + + ConfigServerTestUtils.prepareLocalRepo(); + ConfigServerTestUtils.prepareLocalSvnRepo("src/test/resources/svn-config-repo", + "target/repos/svn-config-repo"); + } + + @Test + public void contextLoads() { + ResponseEntity response = new TestRestTemplate().exchange( + "http://localhost:" + this.port + "/foo/development", HttpMethod.GET, getV2AcceptEntity(), + Environment.class); + Environment environment = response.getBody(); + assertThat(3).isEqualTo(environment.getPropertySources().size()); + assertThat("overrides").isEqualTo(environment.getPropertySources().get(0).getName()); + assertThat(environment.getPropertySources().get(1).getName().contains("config-repo") + && !environment.getPropertySources().get(1).getName().contains("svn-config-repo")) + .isTrue(); + assertThat(environment.getPropertySources().get(2).getName()).contains("svn-config-repo"); + ConfigServerTestUtils.assertConfigEnabled(environment); + } + + @Test + public void resourceEndpointsWork() { + // This request will get the file from the Git Repo because its order is first + // The SVN repo should have the content foo: bar + String text = new TestRestTemplate().getForObject( + "http://localhost:" + this.port + "/foo/development/composite/bar.properties", String.class); + + String expected = "foo: barconfig\n"; + assertThat(expected).isEqualTo(text).as("invalid content"); + } + + } + @SpringBootTest(classes = TestConfigServerApplication.class, properties = { "spring.config.name:compositeconfigserver", "spring.cloud.config.server.svn.uri:file:///./target/repos/svn-config-repo",