Merge branch 'main' of github.com:spring-cloud/spring-cloud-config
This commit is contained in:
@@ -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<String> labels = Arrays.asList(StringUtils.commaDelimitedListToStringArray(label));
|
||||
Collections.reverse(labels);
|
||||
List<EnvironmentRepository> 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());
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -93,15 +94,28 @@ public class AwsS3EnvironmentRepository implements EnvironmentRepository, Ordere
|
||||
final Environment environment = new Environment(application, profileArray);
|
||||
environment.setLabel(label);
|
||||
|
||||
for (String profile : profileArray) {
|
||||
for (String app : apps) {
|
||||
addPropertySource(environment, app, profile, label);
|
||||
List<String> labels;
|
||||
if (StringUtils.hasText(label) && label.contains(",")) {
|
||||
labels = Arrays.asList(StringUtils.commaDelimitedListToStringArray(label));
|
||||
Collections.reverse(labels);
|
||||
}
|
||||
else {
|
||||
labels = Collections.singletonList(label);
|
||||
}
|
||||
|
||||
for (String l : labels) {
|
||||
for (String profile : profileArray) {
|
||||
for (String app : apps) {
|
||||
addPropertySource(environment, app, profile, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add propertysources without profiles as well
|
||||
for (String app : apps) {
|
||||
addPropertySource(environment, app, null, label);
|
||||
for (String l : labels) {
|
||||
for (String app : apps) {
|
||||
addPropertySource(environment, app, null, l);
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
|
||||
@@ -101,29 +101,37 @@ public class AwsSecretsManagerEnvironmentRepository implements EnvironmentReposi
|
||||
environment.add(new PropertySource("overrides", overrides));
|
||||
}
|
||||
|
||||
List<String> labels;
|
||||
if (StringUtils.hasText(label) && label.contains(",")) {
|
||||
labels = Arrays.asList(StringUtils.commaDelimitedListToStringArray(label));
|
||||
Collections.reverse(labels);
|
||||
}
|
||||
else {
|
||||
labels = Collections.singletonList(label);
|
||||
}
|
||||
|
||||
List<String> reversedProfiles = new ArrayList<>(Arrays.asList(profiles));
|
||||
Collections.reverse(reversedProfiles);
|
||||
for (String profile : reversedProfiles) {
|
||||
addPropertySource(environment, application, profile, label);
|
||||
if (!defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, defaultApplication, profile, label);
|
||||
for (String l : labels) {
|
||||
for (String profile : reversedProfiles) {
|
||||
addPropertySource(environment, application, profile, l);
|
||||
if (!defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, defaultApplication, profile, l);
|
||||
}
|
||||
}
|
||||
if (!Arrays.asList(profiles).contains(defaultProfile)) {
|
||||
addPropertySource(environment, application, defaultProfile, l);
|
||||
}
|
||||
if (!Arrays.asList(profiles).contains(defaultProfile) && !defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, defaultApplication, defaultProfile, l);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Arrays.asList(profiles).contains(defaultProfile)) {
|
||||
addPropertySource(environment, application, defaultProfile, label);
|
||||
if (!defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, application, null, l);
|
||||
}
|
||||
addPropertySource(environment, defaultApplication, null, l);
|
||||
}
|
||||
|
||||
if (!Arrays.asList(profiles).contains(defaultProfile) && !defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, defaultApplication, defaultProfile, label);
|
||||
}
|
||||
|
||||
if (!defaultApplication.equals(application)) {
|
||||
addPropertySource(environment, application, null, label);
|
||||
}
|
||||
|
||||
addPropertySource(environment, defaultApplication, null, label);
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,11 +77,14 @@ public class CredhubEnvironmentRepository implements EnvironmentRepository, Orde
|
||||
|
||||
List<String> applications = normalize(application, DEFAULT_APPLICATION);
|
||||
List<String> profiles = normalize(profile, DEFAULT_PROFILE);
|
||||
List<String> labels = normalize(label, this.defaultLabel);
|
||||
|
||||
Environment environment = new Environment(application, split(profile), label, null, null);
|
||||
for (String prof : profiles) {
|
||||
for (String app : applications) {
|
||||
addPropertySource(environment, app, prof, label);
|
||||
for (String l : labels) {
|
||||
for (String prof : profiles) {
|
||||
for (String app : applications) {
|
||||
addPropertySource(environment, app, prof, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -210,9 +211,19 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
|
||||
if (this.addLabelLocations) {
|
||||
for (String location : locations) {
|
||||
if (StringUtils.hasText(label)) {
|
||||
String labelled = location + label.trim() + "/";
|
||||
if (isDirectory(labelled)) {
|
||||
output.add(labelled);
|
||||
List<String> labels;
|
||||
if (label.contains(",")) {
|
||||
labels = Arrays.asList(StringUtils.commaDelimitedListToStringArray(label));
|
||||
Collections.reverse(labels);
|
||||
}
|
||||
else {
|
||||
labels = Collections.singletonList(label);
|
||||
}
|
||||
for (String l : labels) {
|
||||
String labelled = location + l + "/";
|
||||
if (isDirectory(labelled)) {
|
||||
output.add(labelled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,15 @@ public class AwsS3IntegrationTests {
|
||||
objectResponse = s3Client.putObject((request) -> request.bucket("test-bucket").key("data-dev.properties"),
|
||||
RequestBody.fromString("bar=1"));
|
||||
LOG.info("object response " + objectResponse);
|
||||
objectResponse = s3Client.putObject((request) -> request.bucket("test-bucket").key("main/foo.properties"),
|
||||
RequestBody.fromString("foo=1"));
|
||||
LOG.info("object response " + objectResponse);
|
||||
objectResponse = s3Client.putObject((request) -> request.bucket("test-bucket").key("dev/foo.properties"),
|
||||
RequestBody.fromString("devfoo=1"));
|
||||
LOG.info("object response " + objectResponse);
|
||||
objectResponse = s3Client.putObject((request) -> request.bucket("test-bucket").key("test/foo.properties"),
|
||||
RequestBody.fromString("testfoo=1"));
|
||||
LOG.info("object response " + objectResponse);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -124,6 +133,16 @@ public class AwsS3IntegrationTests {
|
||||
.isEqualTo("this is a test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleLabels() throws IOException {
|
||||
RestTemplate rest = new RestTemplateBuilder().build();
|
||||
String configServerUrl = "http://localhost:" + configServerPort;
|
||||
Environment env = rest.getForObject(configServerUrl + "/foo/default/main,dev,test", Environment.class);
|
||||
assertThat(env.getPropertySources().get(0).getSource().get("testfoo")).isEqualTo("1");
|
||||
assertThat(env.getPropertySources().get(1).getSource().get("devfoo")).isEqualTo("1");
|
||||
assertThat(env.getPropertySources().get(2).getSource().get("foo")).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultApplicationAndProfileIncluded() throws IOException {
|
||||
RestTemplate rest = new RestTemplateBuilder().build();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -1595,6 +1596,41 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndDefaultProfileAndExistingLabelWhenMultipleLabelIsSet() {
|
||||
String application = "foo";
|
||||
String profile = configServerProperties.getDefaultProfile();
|
||||
String label = "release,test";
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
|
||||
String fooPropertiesName = "aws:secrets:/secret/foo/";
|
||||
PropertySource fooProperties = new PropertySource(fooPropertiesName, getFooReleaseProperties());
|
||||
|
||||
String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
|
||||
PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
|
||||
getFooDefaultReleaseProperties());
|
||||
|
||||
String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
|
||||
PropertySource applicationDefaultProperties = new PropertySource(applicationDefaultPropertiesName,
|
||||
getApplicationDefaultReleaseProperties());
|
||||
|
||||
String applicationPropertiesName = "aws:secrets:/secret/application/";
|
||||
PropertySource applicationProperties = new PropertySource(applicationPropertiesName,
|
||||
getApplicationReleaseProperties());
|
||||
|
||||
Environment expectedEnv = new Environment(application, profiles, label, null, null);
|
||||
expectedEnv.addAll(Arrays.asList(applicationDefaultProperties, fooProperties));
|
||||
|
||||
putSecrets("release", Collections.singletonList(fooProperties));
|
||||
putSecrets("dev", Collections.singletonList(fooDefaultProperties));
|
||||
putSecrets("test", Collections.singletonList(applicationDefaultProperties));
|
||||
putSecrets("", Collections.singletonList(applicationProperties));
|
||||
|
||||
Environment resultEnv = labeledRepository.findOne(application, profile, label);
|
||||
|
||||
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(expectedEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneWithExistingApplicationAndNonExistingProfileAndExistingLabelWhenDefaultLabelIsSet() {
|
||||
String application = "foo";
|
||||
@@ -2640,7 +2676,11 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
|
||||
private void putSecrets(Environment environment) {
|
||||
String label = environment.getLabel() != null ? environment.getLabel()
|
||||
: environmentProperties.getDefaultLabel();
|
||||
for (PropertySource ps : environment.getPropertySources()) {
|
||||
putSecrets(label, environment.getPropertySources());
|
||||
}
|
||||
|
||||
private void putSecrets(String label, List<PropertySource> propertySources) {
|
||||
for (PropertySource ps : propertySources) {
|
||||
String path = StringUtils.delete(ps.getName(), environmentProperties.getOrigin());
|
||||
String secrets = getSecrets(ps);
|
||||
CreateSecretResponse response = smClient
|
||||
|
||||
@@ -121,6 +121,28 @@ public class CredhubEnvironmentRepositoryTests {
|
||||
assertThat(environment.getPropertySources().get(1).getSource()).isEqualTo(Map.of("k1", "v1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRetrieveGivenLabelsProfiles() {
|
||||
stubCredentials("/myApp/prod/myLabel", credential("c1", "k1", "v1"));
|
||||
stubCredentials("/myApp/cloud/mySecondLabel", credential("c2", "k2", "v2"));
|
||||
stubCredentials("/myApp/prod/myThirdLabel", credential("c3", "k3", "v3"));
|
||||
|
||||
Environment environment = this.credhubEnvironmentRepository.findOne("myApp", "prod,cloud",
|
||||
"myLabel,mySecondLabel");
|
||||
|
||||
assertThat(environment.getName()).isEqualTo("myApp");
|
||||
assertThat(environment.getProfiles()).containsExactly("prod", "cloud");
|
||||
assertThat(environment.getLabel()).isEqualTo("myLabel,mySecondLabel");
|
||||
|
||||
assertThat(environment.getPropertySources()).hasSize(2);
|
||||
|
||||
assertThat(environment.getPropertySources().get(0).getName()).isEqualTo("credhub-myApp-cloud-mySecondLabel");
|
||||
assertThat(environment.getPropertySources().get(0).getSource()).isEqualTo(Map.of("k2", "v2"));
|
||||
|
||||
assertThat(environment.getPropertySources().get(1).getName()).isEqualTo("credhub-myApp-prod-myLabel");
|
||||
assertThat(environment.getPropertySources().get(1).getSource()).isEqualTo(Map.of("k1", "v1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRetrieveGivenMultipleApplicationNames() {
|
||||
stubCredentials("/app1/default/myLabel", credential("c1", "k1", "v1"));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -244,6 +244,16 @@ public class NativeEnvironmentRepositoryTests {
|
||||
assertThat(environment.getPropertySources().get(0).getSource().get("foo")).isNotEqualTo("dev_bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locationAddMultipleLabelLocations() {
|
||||
this.repository.setSearchLocations("classpath:/test/dev/");
|
||||
Environment environment = this.repository.findOne("foo", "development", "ignore,applicationxyz");
|
||||
assertThat(environment.getPropertySources()).hasSize(3);
|
||||
assertThat(environment.getPropertySources().get(0).getSource().get("foo")).isEqualTo("app");
|
||||
assertThat(environment.getPropertySources().get(1).getSource().get("foo")).isEqualTo("default-app");
|
||||
assertThat(environment.getPropertySources().get(2).getSource().get("foo")).isEqualTo("dev_bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tryToStartReactive() {
|
||||
this.repository.setSearchLocations("classpath:/test/reactive/");
|
||||
|
||||
@@ -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(() -> {
|
||||
|
||||
Reference in New Issue
Block a user