diff --git a/docs/src/main/asciidoc/spring-cloud-config.adoc b/docs/src/main/asciidoc/spring-cloud-config.adoc index 130a62ec..1070b1e3 100644 --- a/docs/src/main/asciidoc/spring-cloud-config.adoc +++ b/docs/src/main/asciidoc/spring-cloud-config.adoc @@ -767,6 +767,23 @@ For example, if you run the following Vault command, all applications using the $ vault write secret/application foo=bar baz=bam ---- +===== CredHub Server + +When using CredHub as a backend, you can share configuration with all applications by placing configuration in `/application/` or by placing it in the `default` profile for the application. +For example, if you run the following CredHub command, all applications using the config server will have the properties `shared.color1` and `shared.color2` available to them: + +[source,sh] +---- +credhub set --name "/application/profile/master/shared" --type=json +value: {"shared.color1": "blue", "shared.color": "red"} +---- + +[source,sh] +---- +credhub set --name "/my-app/default/master/more-shared" --type=json +value: {"shared.word1": "hello", "shared.word2": "world"} +---- + ==== JDBC Backend Spring Cloud Config Server supports JDBC (relational database) as a backend for configuration properties. @@ -917,6 +934,7 @@ All client applications with the name `spring.cloud.config.name=demo-app` will h ---- NOTE: When no profile is specified `default` will be used and when no label is specified `master` will be used as a default value. +NOTE: Values added to `application` will be shared by all the applications. ===== OAuth 2.0 You can authenticate with link:https://oauth.net/2/[OAuth 2.0] using link:https://docs.cloudfoundry.org/concepts/architecture/uaa.html[UAA] as a provider. 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 47707d27..e5746b73 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 @@ -16,7 +16,7 @@ package org.springframework.cloud.config.server.environment; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; import org.springframework.cloud.config.environment.Environment; @@ -36,6 +36,12 @@ public class CredhubEnvironmentRepository implements EnvironmentRepository { private CredHubOperations credHubOperations; + private static final String DEFAULT_PROFILE = "default"; + + private static final String DEFAULT_LABEL = "master"; + + private static final String DEFAULT_APPLICATION = "application"; + public CredhubEnvironmentRepository(CredHubOperations credHubOperations) { this.credHubOperations = credHubOperations; } @@ -43,25 +49,49 @@ public class CredhubEnvironmentRepository implements EnvironmentRepository { @Override public Environment findOne(String application, String profilesList, String label) { if (StringUtils.isEmpty(profilesList)) { - profilesList = "default"; + profilesList = DEFAULT_PROFILE; } if (StringUtils.isEmpty(label)) { - label = "master"; + label = DEFAULT_LABEL; } String[] profiles = StringUtils.commaDelimitedListToStringArray(profilesList); Environment environment = new Environment(application, profiles, label, null, null); - Map properties = new HashMap<>(); for (String profile : profiles) { - properties.putAll(findProperties(application, profile, label)); + environment.add(new PropertySource( + "credhub-" + application + "-" + profile + "-" + label, + findProperties(application, profile, label))); + if (!DEFAULT_APPLICATION.equals(application)) { + addDefaultPropertySource(environment, DEFAULT_APPLICATION, profile, + label); + } + } + + if (!Arrays.asList(profiles).contains(DEFAULT_PROFILE)) { + addDefaultPropertySource(environment, application, DEFAULT_PROFILE, label); + } + + if (!Arrays.asList(profiles).contains(DEFAULT_PROFILE) + && !DEFAULT_APPLICATION.equals(application)) { + addDefaultPropertySource(environment, DEFAULT_APPLICATION, DEFAULT_PROFILE, + label); } - environment.add(new PropertySource("credhub-" + application, properties)); return environment; } + private void addDefaultPropertySource(Environment environment, String application, + String profile, String label) { + Map properties = findProperties(application, profile, label); + if (!properties.isEmpty()) { + PropertySource propertySource = new PropertySource( + "credhub-" + application + "-" + profile + "-" + label, properties); + environment.add(propertySource); + } + } + private Map findProperties(String application, String profile, String label) { String path = "/" + application + "/" + profile + "/" + label; diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubCompositeConfigServerIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubCompositeConfigServerIntegrationTests.java index 56912bb8..c34298be 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubCompositeConfigServerIntegrationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubCompositeConfigServerIntegrationTests.java @@ -50,7 +50,7 @@ public class CredhubCompositeConfigServerIntegrationTests extends CredhubIntegra assertThat(environment.getPropertySources().isEmpty()).isFalse(); assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-myapp"); + .isEqualTo("credhub-myapp-master-default"); assertThat(environment.getPropertySources().get(0).getSource().toString()) .isEqualTo("{key=value}"); } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubConfigServerIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubConfigServerIntegrationTests.java index 764e2d1a..1c7ad188 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubConfigServerIntegrationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CredhubConfigServerIntegrationTests.java @@ -49,7 +49,7 @@ public class CredhubConfigServerIntegrationTests extends CredhubIntegrationTest assertThat(environment.getPropertySources().isEmpty()).isFalse(); assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-myapp"); + .isEqualTo("credhub-myapp-master-default"); assertThat(environment.getPropertySources().get(0).getSource().toString()) .isEqualTo("{key=value}"); } 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 b7322322..ad655c45 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 @@ -68,11 +68,13 @@ public class CredhubEnvironmentRepositoryTests { Environment environment = this.credhubEnvironmentRepository .findOne("my-application", "production", "mylabel"); - assertThat(environment.getLabel()).isEqualTo("mylabel"); - assertThat(environment.getProfiles()).containsExactly("production"); assertThat(environment.getName()).isEqualTo("my-application"); + assertThat(environment.getProfiles()).containsExactly("production"); + assertThat(environment.getLabel()).isEqualTo("mylabel"); + + assertThat(environment.getPropertySources().size()).isEqualTo(1); assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-my-application"); + .isEqualTo("credhub-my-application-production-mylabel"); assertThat(environment.getPropertySources().get(0).getSource()).isEmpty(); } @@ -83,11 +85,13 @@ public class CredhubEnvironmentRepositoryTests { Environment environment = this.credhubEnvironmentRepository .findOne("my-application", null, null); - assertThat(environment.getLabel()).isEqualTo("master"); - assertThat(environment.getProfiles()).containsExactly("default"); assertThat(environment.getName()).isEqualTo("my-application"); + assertThat(environment.getProfiles()).containsExactly("default"); + assertThat(environment.getLabel()).isEqualTo("master"); + + assertThat(environment.getPropertySources().size()).isEqualTo(1); assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-my-application"); + .isEqualTo("credhub-my-application-default-master"); assertThat(environment.getPropertySources().get(0).getSource()) .isEqualTo(singletonMap("key1", "value1")); } @@ -100,11 +104,13 @@ public class CredhubEnvironmentRepositoryTests { Environment environment = this.credhubEnvironmentRepository .findOne("my-application", "production", "mylabel"); - assertThat(environment.getLabel()).isEqualTo("mylabel"); - assertThat(environment.getProfiles()).containsExactly("production"); assertThat(environment.getName()).isEqualTo("my-application"); + assertThat(environment.getProfiles()).containsExactly("production"); + assertThat(environment.getLabel()).isEqualTo("mylabel"); + + assertThat(environment.getPropertySources().size()).isEqualTo(1); assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-my-application"); + .isEqualTo("credhub-my-application-production-mylabel"); assertThat(environment.getPropertySources().get(0).getSource()) .isEqualTo(singletonMap("key1", "value1")); } @@ -118,16 +124,20 @@ public class CredhubEnvironmentRepositoryTests { Environment environment = this.credhubEnvironmentRepository .findOne("my-application", "production,cloud", "mylabel"); - assertThat(environment.getLabel()).isEqualTo("mylabel"); - assertThat(environment.getProfiles()).containsExactly("production", "cloud"); assertThat(environment.getName()).isEqualTo("my-application"); + assertThat(environment.getProfiles()).containsExactly("production", "cloud"); + assertThat(environment.getLabel()).isEqualTo("mylabel"); + + assertThat(environment.getPropertySources().size()).isEqualTo(2); assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-my-application"); - HashMap expectedValues = new HashMap<>(); - expectedValues.put("key1", "value1"); - expectedValues.put("key2", "value2"); + .isEqualTo("credhub-my-application-production-mylabel"); assertThat(environment.getPropertySources().get(0).getSource()) - .isEqualTo(expectedValues); + .isEqualTo(singletonMap("key1", "value1")); + assertThat(environment.getPropertySources().get(1).getName()) + + .isEqualTo("credhub-my-application-cloud-mylabel"); + assertThat(environment.getPropertySources().get(1).getSource()) + .isEqualTo(singletonMap("key2", "value2")); } @Test @@ -158,12 +168,13 @@ public class CredhubEnvironmentRepositoryTests { Environment environment = this.credhubEnvironmentRepository .findOne("my-application", "production", "mylabel"); - assertThat(environment.getLabel()).isEqualTo("mylabel"); - assertThat(environment.getProfiles()).containsExactly("production"); assertThat(environment.getName()).isEqualTo("my-application"); - assertThat(environment.getPropertySources().get(0).getName()) - .isEqualTo("credhub-my-application"); + assertThat(environment.getProfiles()).containsExactly("production"); + assertThat(environment.getLabel()).isEqualTo("mylabel"); + assertThat(environment.getPropertySources().size()).isEqualTo(1); + assertThat(environment.getPropertySources().get(0).getName()) + .isEqualTo("credhub-my-application-production-mylabel"); HashMap expectedValues = new HashMap<>(); expectedValues.put("key1", "value1"); expectedValues.put("key2", "value2"); @@ -171,6 +182,64 @@ public class CredhubEnvironmentRepositoryTests { .isEqualTo(expectedValues); } + @Test + public void shouldIncludeDefaultApplicationWhenOtherProvided() { + stubCredentials("/my-application/production/mylabel", "toggles", "key1", + "value1"); + stubCredentials("/application/production/mylabel", "abs", "key2", "value2"); + + Environment environment = this.credhubEnvironmentRepository + .findOne("my-application", "production", "mylabel"); + + assertThat(environment.getName()).isEqualTo("my-application"); + assertThat(environment.getProfiles()).containsExactly("production"); + assertThat(environment.getLabel()).isEqualTo("mylabel"); + + assertThat(environment.getPropertySources().size()).isEqualTo(2); + assertThat(environment.getPropertySources().get(0).getName()) + .isEqualTo("credhub-my-application-production-mylabel"); + assertThat(environment.getPropertySources().get(0).getSource()) + .isEqualTo(singletonMap("key1", "value1")); + assertThat(environment.getPropertySources().get(1).getName()) + .isEqualTo("credhub-application-production-mylabel"); + assertThat(environment.getPropertySources().get(1).getSource()) + .isEqualTo(singletonMap("key2", "value2")); + } + + @Test + public void shouldIncludeDefaultProfileWhenOtherProvided() { + stubCredentials("/my-application/production/mylabel", "toggles", "key1", + "value1"); + stubCredentials("/application/production/mylabel", "abs", "key2", "value2"); + stubCredentials("/my-application/default/mylabel", "abs", "key3", "value3"); + stubCredentials("/application/default/mylabel", "abs", "key4", "value4"); + + Environment environment = this.credhubEnvironmentRepository + .findOne("my-application", "production", "mylabel"); + + assertThat(environment.getName()).isEqualTo("my-application"); + assertThat(environment.getProfiles()).contains("production"); + assertThat(environment.getLabel()).isEqualTo("mylabel"); + + assertThat(environment.getPropertySources().size()).isEqualTo(4); + assertThat(environment.getPropertySources().get(0).getName()) + .isEqualTo("credhub-my-application-production-mylabel"); + assertThat(environment.getPropertySources().get(0).getSource()) + .isEqualTo(singletonMap("key1", "value1")); + assertThat(environment.getPropertySources().get(1).getName()) + .isEqualTo("credhub-application-production-mylabel"); + assertThat(environment.getPropertySources().get(1).getSource()) + .isEqualTo(singletonMap("key2", "value2")); + assertThat(environment.getPropertySources().get(2).getName()) + .isEqualTo("credhub-my-application-default-mylabel"); + assertThat(environment.getPropertySources().get(2).getSource()) + .isEqualTo(singletonMap("key3", "value3")); + assertThat(environment.getPropertySources().get(3).getName()) + .isEqualTo("credhub-application-default-mylabel"); + assertThat(environment.getPropertySources().get(3).getSource()) + .isEqualTo(singletonMap("key4", "value4")); + } + private void stubCredentials(String expectedPath, String name, String key, String value) { SimpleCredentialName credentialsName = new SimpleCredentialName(