diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java index 3f3b3ef4..987cfcef 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java @@ -87,17 +87,24 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository public Locations getLocations(String application, String profile, String label) { for (PatternMatchingJGitEnvironmentRepository repository : this.repos.values()) { if (repository.matches(application, profile, label)) { - JGitEnvironmentRepository candidate = getRepository(repository, - application, profile, label); - Environment source = candidate.findOne(application, profile, label); - if (source != null) { - return repository.getLocations(application, profile, label); + for (JGitEnvironmentRepository candidate : getRepositories(repository, + application, profile, label)) { + try { + Environment source = candidate.findOne(application, profile, + label); + if (source != null) { + return candidate.getLocations(application, profile, label); + } + } + catch (Exception e) { + continue; + } } } } - JGitEnvironmentRepository candidate = getRepository(this, - application, profile, label); - if (candidate==this) { + JGitEnvironmentRepository candidate = getRepository(this, application, profile, + label); + if (candidate == this) { return super.getLocations(application, profile, label); } return candidate.getLocations(application, profile, label); @@ -107,35 +114,56 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository public Environment findOne(String application, String profile, String label) { for (PatternMatchingJGitEnvironmentRepository repository : this.repos.values()) { if (repository.matches(application, profile, label)) { - JGitEnvironmentRepository candidate = getRepository(repository, - application, profile, label); - Environment source = candidate.findOne(application, profile, label); - if (source != null) { - return source; + for (JGitEnvironmentRepository candidate : getRepositories(repository, + application, profile, label)) { + try { + Environment source = candidate.findOne(application, profile, + label); + if (source != null) { + return source; + } + } + catch (Exception e) { + this.logger.info( + "Cannot load configuration from " + candidate.getUri()); + continue; + } } } } - JGitEnvironmentRepository candidate = getRepository(this, - application, profile, label); - if (candidate==this) { + JGitEnvironmentRepository candidate = getRepository(this, application, profile, + label); + if (candidate == this) { return super.findOne(application, profile, label); } return candidate.findOne(application, profile, label); } + private List getRepositories( + JGitEnvironmentRepository repository, String application, String profile, + String label) { + List list = new ArrayList<>(); + String[] profiles = profile == null ? new String[] { null } + : StringUtils.commaDelimitedListToStringArray(profile); + for (int i = profiles.length; i-- > 0;) { + list.add(getRepository(repository, application, profiles[i], label)); + } + return list; + } + private JGitEnvironmentRepository getRepository(JGitEnvironmentRepository repository, String application, String profile, String label) { if (!repository.getUri().contains("{")) { return repository; } String key = repository.getUri(); - if (application!=null) { + if (application != null) { key = key.replace("{application}", application); } - if (profile!=null) { + if (profile != null) { key = key.replace("{profile}", profile); } - if (label!=null) { + if (label != null) { key = key.replace("{label}", label); } if (!this.repos.containsKey(key)) { @@ -173,10 +201,12 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository if (this.pattern == null || this.pattern.length == 0) { return false; } - - if (PatternMatchUtils.simpleMatch(this.pattern, - application + "/" + profile)) { - return true; + String[] profiles = StringUtils.commaDelimitedListToStringArray(profile); + for (int i = profiles.length; i-- > 0;) { + if (PatternMatchUtils.simpleMatch(this.pattern, + application + "/" + profiles[i])) { + return true; + } } return false; } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java index 8b31479f..2dff7fba 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java @@ -122,21 +122,27 @@ public class NativeEnvironmentRepository } List output = new ArrayList(); for (String location : locations) { - String value = location; - if (application != null) { - value = value.replace("{application}", application); - } + String[] profiles = new String[] { profile }; if (profile != null) { - value = value.replace("{profile}", profile); + profiles = StringUtils.commaDelimitedListToStringArray(profile); } - if (label != null) { - value = value.replace("{label}", label); - } - if (!value.endsWith("/")) { - value = value + "/"; - } - if (isDirectory(value)) { - output.add(value); + for (String prof : profiles) { + String value = location; + if (application != null) { + value = value.replace("{application}", application); + } + if (prof != null) { + value = value.replace("{profile}", prof); + } + if (label != null) { + value = value.replace("{label}", label); + } + if (!value.endsWith("/")) { + value = value + "/"; + } + if (isDirectory(value)) { + output.add(value); + } } } for (String location : locations) { @@ -175,9 +181,10 @@ public class NativeEnvironmentRepository .cleanPath(new File(normal.substring("file:".length())) .getAbsolutePath()); } - String profile = result.getProfiles() == null ? null : StringUtils.arrayToCommaDelimitedString(result.getProfiles()); - for (String pattern : getLocations(result.getName(), profile, result.getLabel()) - .getLocations()) { + String profile = result.getProfiles() == null ? null + : StringUtils.arrayToCommaDelimitedString(result.getProfiles()); + for (String pattern : getLocations(result.getName(), profile, + result.getLabel()).getLocations()) { if (!pattern.contains(":")) { pattern = "file:" + pattern; } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentUriTemplateRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentApplicationPlaceholderRepositoryTests.java similarity index 81% rename from spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentUriTemplateRepositoryTests.java rename to spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentApplicationPlaceholderRepositoryTests.java index 840c7a5d..3a0046ea 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentUriTemplateRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentApplicationPlaceholderRepositoryTests.java @@ -23,9 +23,11 @@ import java.util.HashMap; import java.util.Map; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.cloud.config.environment.Environment; import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.PatternMatchingJGitEnvironmentRepository; +import org.springframework.cloud.config.server.environment.SearchPathLocator.Locations; import org.springframework.cloud.config.server.test.ConfigServerTestUtils; import org.springframework.core.env.StandardEnvironment; @@ -33,7 +35,7 @@ import org.springframework.core.env.StandardEnvironment; * @author Dave Syer * */ -public class MultipleJGitEnvironmentUriTemplateRepositoryTests { +public class MultipleJGitEnvironmentApplicationPlaceholderRepositoryTests { private StandardEnvironment environment = new StandardEnvironment(); private MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository( @@ -76,6 +78,17 @@ public class MultipleJGitEnvironmentUriTemplateRepositoryTests { assertVersion(environment); } + @Test + public void missingRepo() { + Environment environment = this.repository.findOne("missing-config-repo", + "staging", "master"); + assertEquals("Wrong property sources: " + environment, 1, + environment.getPropertySources().size()); + assertEquals(this.repository.getUri() + "/application.yml", + environment.getPropertySources().get(0).getName()); + assertVersion(environment); + } + @Test public void mappingRepo() { Environment environment = this.repository.findOne("test1-config-repo", "staging", @@ -100,6 +113,16 @@ public class MultipleJGitEnvironmentUriTemplateRepositoryTests { assertVersion(environment); } + @Test + @Ignore("not supported yet (placeholders in search paths)") + public void profilesInSearchPaths() { + this.repository.setSearchPaths("{profile}"); + Locations locations = this.repository.getLocations("foo", "dev,one,two", + "master"); + assertEquals(3, locations.getLocations().length); + assertEquals("classpath:/test/dev/", locations.getLocations()[0]); + } + private void assertVersion(Environment environment) { String version = environment.getVersion(); assertNotNull("version was null", version); diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentProfilePlaceholderRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentProfilePlaceholderRepositoryTests.java new file mode 100644 index 00000000..732ed9f3 --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentProfilePlaceholderRepositoryTests.java @@ -0,0 +1,167 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cloud.config.server.environment; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.config.environment.Environment; +import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.PatternMatchingJGitEnvironmentRepository; +import org.springframework.cloud.config.server.environment.SearchPathLocator.Locations; +import org.springframework.cloud.config.server.test.ConfigServerTestUtils; +import org.springframework.core.env.StandardEnvironment; + +/** + * @author Dave Syer + * + */ +public class MultipleJGitEnvironmentProfilePlaceholderRepositoryTests { + + private StandardEnvironment environment = new StandardEnvironment(); + private MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository( + this.environment); + + @Before + public void init() throws Exception { + String defaultUri = ConfigServerTestUtils.prepareLocalRepo("config-repo"); + this.repository.setUri(defaultUri); + this.repository.setRepos(createRepositories()); + } + + private Map createRepositories() + throws Exception { + String test1Uri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo"); + ConfigServerTestUtils.prepareLocalRepo("test2-config-repo"); + + Map repos = new HashMap<>(); + repos.put("templates", createRepository("test", "*-config-repo", + test1Uri.replace("test1-config-repo", "{profile}"))); + return repos; + } + + private PatternMatchingJGitEnvironmentRepository createRepository(String name, + String pattern, String uri) { + PatternMatchingJGitEnvironmentRepository repo = new PatternMatchingJGitEnvironmentRepository(); + repo.setEnvironment(this.environment); + repo.setName(name); + repo.setPattern(new String[] { pattern }); + repo.setUri(uri); + return repo; + } + + @Test + public void defaultRepo() { + Environment environment = this.repository.findOne("bar", "staging", "master"); + assertEquals(2, environment.getPropertySources().size()); + assertEquals(this.repository.getUri() + "/bar.properties", + environment.getPropertySources().get(0).getName()); + assertVersion(environment); + } + + @Test + public void mappingRepo() { + Environment environment = this.repository.findOne("application", + "test1-config-repo", "master"); + assertEquals(1, environment.getPropertySources().size()); + assertEquals( + getUri("*").replace("{profile}", "test1-config-repo") + + "/application.yml", + environment.getPropertySources().get(0).getName()); + assertVersion(environment); + } + + @Test + public void otherMappingRepo() { + Environment environment = this.repository.findOne("application", + "test2-config-repo", "master"); + assertEquals(1, environment.getPropertySources().size()); + assertEquals( + getUri("*").replace("{profile}", "test2-config-repo") + + "/application.properties", + environment.getPropertySources().get(0).getName()); + assertVersion(environment); + } + + @Test + public void locationsTwoProfiles() throws Exception { + Locations locations = this.repository.getLocations("application", + "test1-config-repo,test2-config-repo", "master"); + assertEquals(1, locations.getLocations().length); + assertEquals( + new File(getUri("*").replace("{profile}", "test2-config-repo") + .replace("file:", "")).getCanonicalPath(), + new File(locations.getLocations()[0].replace("file:", "")) + .getCanonicalPath()); + } + + @Test + public void locationsMissingProfile() throws Exception { + Locations locations = this.repository.getLocations("application", + "not-there,another-not-there", "master"); + assertEquals(1, locations.getLocations().length); + assertEquals( + new File(this.repository.getUri().replace("file:", "")) + .getCanonicalPath(), + new File(locations.getLocations()[0].replace("file:", "")) + .getCanonicalPath()); + } + + @Test + public void twoMappingRepos() { + Environment environment = this.repository.findOne("application", + "test1-config-repo,test2-config-repo,missing-config-repo", "master"); + assertEquals(1, environment.getPropertySources().size()); + assertEquals( + getUri("*").replace("{profile}", "test2-config-repo") + + "/application.properties", + environment.getPropertySources().get(0).getName()); + assertVersion(environment); + assertArrayEquals(environment.getProfiles(), new String[] { "test1-config-repo", + "test2-config-repo", "missing-config-repo" }); + } + + private void assertVersion(Environment environment) { + String version = environment.getVersion(); + assertNotNull("version was null", version); + assertTrue("version length was wrong", + version.length() >= 40 && version.length() <= 64); + } + + private String getUri(String pattern) { + String uri = null; + + Map repoMappings = this.repository + .getRepos(); + + for (PatternMatchingJGitEnvironmentRepository repo : repoMappings.values()) { + String[] mappingPattern = repo.getPattern(); + if (mappingPattern != null && mappingPattern.length != 0) { + uri = repo.getUri(); + break; + } + } + + return uri; + } +} diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepositoryTests.java index b35ee909..14d0e0e8 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepositoryTests.java @@ -110,6 +110,15 @@ public class NativeEnvironmentRepositoryTests { environment.getPropertySources().get(0).getSource().get("foo")); } + @Test + public void placeholdersProfiles() { + this.repository.setSearchLocations("classpath:/test/{profile}/"); + Environment environment = this.repository.findOne("foo", "dev,mysql", "master"); + assertEquals(2, environment.getPropertySources().size()); + assertEquals("mysql", + environment.getPropertySources().get(0).getSource().get("foo")); + } + @Test public void placeholdersApplicationAndProfile() { this.repository.setSearchLocations("classpath:/test/{profile}/{application}/"); @@ -127,6 +136,14 @@ public class NativeEnvironmentRepositoryTests { assertEquals("classpath:/test/foo/", locations.getLocations()[0]); } + @Test + public void locationProfilesApplication() { + this.repository.setSearchLocations("classpath:/test/{profile}"); + Locations locations = this.repository.getLocations("foo", "dev,one,two", "master"); + assertEquals(3, locations.getLocations().length); + assertEquals("classpath:/test/dev/", locations.getLocations()[0]); + } + @Test public void placeholdersNoTrailingSlash() { this.repository.setSearchLocations("classpath:/test/{label}"); diff --git a/spring-cloud-config-server/src/test/resources/test/mysql/application.properties b/spring-cloud-config-server/src/test/resources/test/mysql/application.properties new file mode 100644 index 00000000..10291126 --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/test/mysql/application.properties @@ -0,0 +1 @@ +foo:mysql \ No newline at end of file