Support for multiple profiles in profile placeholders

In a file-based repository up to now we only support single profiles in
a placeholder. This change adds full support for multiple profiles in
the native profile and slightly limited support for git backends (only
the first profile to match an actual repository will be used to locate
the physical repository, but all profiles will be applied to the search
inside that repository).
This commit is contained in:
Dave Syer
2015-12-02 13:18:09 +00:00
parent 87a1e773a0
commit edcb153571
6 changed files with 285 additions and 40 deletions

View File

@@ -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<JGitEnvironmentRepository> getRepositories(
JGitEnvironmentRepository repository, String application, String profile,
String label) {
List<JGitEnvironmentRepository> 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;
}

View File

@@ -122,21 +122,27 @@ public class NativeEnvironmentRepository
}
List<String> output = new ArrayList<String>();
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;
}

View File

@@ -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);

View File

@@ -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<String, PatternMatchingJGitEnvironmentRepository> createRepositories()
throws Exception {
String test1Uri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
ConfigServerTestUtils.prepareLocalRepo("test2-config-repo");
Map<String, PatternMatchingJGitEnvironmentRepository> 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<String, PatternMatchingJGitEnvironmentRepository> 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;
}
}

View File

@@ -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}");