Add support for matching profiles as well as applications
Patterns in the form {application}/{profile} are now supported with
the old behaviour being the default (all profiles matched if none
are specified).
Fixes gh-214
This commit is contained in:
@@ -143,7 +143,10 @@ the URL if you are using a command line client like curl (e.g. escape
|
||||
them from the shell with quotes '').
|
||||
|
||||
Spring Cloud Config Server supports a single or multiple git
|
||||
repositories:
|
||||
repositories with pattern matching on the application and profile
|
||||
name. The pattern format is a comma-separated list of
|
||||
`{application}/{profile}` names with wildcards (where a pattern
|
||||
beginning with a wildcard may need to be quoted). Example:
|
||||
|
||||
----
|
||||
spring:
|
||||
@@ -155,25 +158,59 @@ spring:
|
||||
repos:
|
||||
simple: https://github.com/simple/config-repo
|
||||
special:
|
||||
pattern: pattern*,*pattern1*
|
||||
pattern: special*/dev*,*special*/dev*
|
||||
uri: https://github.com/special/config-repo
|
||||
local:
|
||||
pattern: local*
|
||||
uri: file:/home/configsvc/config-repo
|
||||
----
|
||||
|
||||
In the above example, if `{application}` does not match any of the
|
||||
patterns, it will use the default uri defined under
|
||||
"spring.cloud.config.server.git.uri". For the "simple" repository, the
|
||||
pattern is "simple" (i.e. it only matches one application named "simple").
|
||||
The pattern format is a comma-separated list of application names with
|
||||
wildcards (a pattern beginning with a wildcard may need to be quoted).
|
||||
If `{application}/{profile}` does not match any of the patterns, it
|
||||
will use the default uri defined under
|
||||
"spring.cloud.config.server.git.uri". In the above example, for the
|
||||
"simple" repository, the pattern is `simple/\*` (i.e. it only matches
|
||||
one application named "simple" in all profiles). The "local"
|
||||
repository matches all application names beginning with "local" in all
|
||||
profiles (the `/*` suffix is added automatically to any pattern that
|
||||
doesn't have a profile matcher).
|
||||
|
||||
NOTE: the "one-liner" short cut used in the "simple" example above can
|
||||
only be used if the only property to be set is the URI. If you need to
|
||||
set anything else (credentials, pattern, etc.) you need to use the full
|
||||
form.
|
||||
|
||||
The `pattern` property in the repo is actually an array, so you can
|
||||
use a YAML array (or `[0]`, `[1]`, etc. suffixes in properties files)
|
||||
to bind to multiple patterns. You may need to do this if you are going
|
||||
to run apps with multiple profiles. Example:
|
||||
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
git:
|
||||
uri: https://github.com/spring-cloud-samples/config-repo
|
||||
repos:
|
||||
development:
|
||||
pattern:
|
||||
- */development
|
||||
- */staging
|
||||
uri: https://github.com/development/config-repo
|
||||
staging:
|
||||
pattern:
|
||||
- */qa
|
||||
- */production
|
||||
uri: https://github.com/staging/config-repo
|
||||
----
|
||||
|
||||
NOTE: Spring Cloud will guess that a pattern containing a profile that
|
||||
doesn't end in `\*` implies that you actually want to match a list of
|
||||
profiles starting with this pattern (so `*/staging` is a shortcut for
|
||||
`["\*/staging", "*/staging,*"]`). This is common where you need to run
|
||||
apps in the "development" profile locally but also the "cloud" profile
|
||||
remotely, for instance.
|
||||
|
||||
Every repository can also optionally store config files in
|
||||
sub-directories, and patterns to search for those directories can be
|
||||
specified as `searchPaths`. For example at the top level:
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package org.springframework.cloud.config.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -87,10 +91,10 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
return super.findOne(application, profile, label);
|
||||
}
|
||||
|
||||
public static class PatternMatchingJGitEnvironmentRepository extends
|
||||
JGitEnvironmentRepository {
|
||||
public static class PatternMatchingJGitEnvironmentRepository
|
||||
extends JGitEnvironmentRepository {
|
||||
|
||||
private String[] pattern;
|
||||
private String[] pattern = new String[0];
|
||||
private String name;
|
||||
|
||||
public PatternMatchingJGitEnvironmentRepository() {
|
||||
@@ -109,7 +113,8 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
return null;
|
||||
}
|
||||
|
||||
if (PatternMatchUtils.simpleMatch(this.pattern, application)) {
|
||||
if (PatternMatchUtils.simpleMatch(this.pattern,
|
||||
application + "/" + profile)) {
|
||||
return super.findOne(application, profile, label);
|
||||
}
|
||||
|
||||
@@ -130,7 +135,27 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
}
|
||||
|
||||
public void setPattern(String[] pattern) {
|
||||
this.pattern = pattern;
|
||||
Collection<String> patterns = new ArrayList<>();
|
||||
List<String> otherProfiles = new ArrayList<>();
|
||||
for (String p : pattern) {
|
||||
if (p != null) {
|
||||
if (!p.contains("/")) {
|
||||
// Match any profile
|
||||
patterns.add(p + "/*");
|
||||
}
|
||||
if (!p.endsWith("*")) {
|
||||
// If user supplies only one profile, allow others
|
||||
otherProfiles.add(p + ",*");
|
||||
}
|
||||
}
|
||||
patterns.add(p);
|
||||
}
|
||||
patterns.addAll(otherProfiles);
|
||||
if (!patterns.contains(null)) {
|
||||
// Make sure they are unique
|
||||
patterns = new LinkedHashSet<>(patterns);
|
||||
}
|
||||
this.pattern = patterns.toArray(new String[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ import org.junit.Test;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.ConfigServerTestUtils;
|
||||
import org.springframework.cloud.config.server.EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -39,6 +37,7 @@ import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* @author Andy Chan (iceycake)
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class MultipleJGitEnvironmentRepositoryIntegrationTests {
|
||||
@@ -49,25 +48,25 @@ public class MultipleJGitEnvironmentRepositoryIntegrationTests {
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
if (basedir.exists()) {
|
||||
FileUtils.delete(basedir, FileUtils.RECURSIVE);
|
||||
if (this.basedir.exists()) {
|
||||
FileUtils.delete(this.basedir, FileUtils.RECURSIVE);
|
||||
}
|
||||
ConfigServerTestUtils.deleteLocalRepo("config-copy");
|
||||
}
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultRepo() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri).run();
|
||||
EnvironmentRepository repository = context.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -80,27 +79,82 @@ public class MultipleJGitEnvironmentRepositoryIntegrationTests {
|
||||
|
||||
Map<String, Object> repoMapping = new LinkedHashMap<String, Object>();
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern", "*test1*");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri);
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri);
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri)
|
||||
.properties(repoMapping).run();
|
||||
EnvironmentRepository repository = context.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = repository.findOne("test1-svc", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepoWithProfile() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
String test1RepoUri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
|
||||
|
||||
Map<String, Object> repoMapping = new LinkedHashMap<String, Object>();
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern", "*/staging");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri);
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri)
|
||||
.properties(repoMapping).run();
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = repository.findOne("test1-svc", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepoWithProfileDefaultPatterns() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
String test1RepoUri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
|
||||
|
||||
Map<String, Object> repoMapping = new LinkedHashMap<String, Object>();
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern", "*/staging");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri);
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri)
|
||||
.properties(repoMapping).run();
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = repository.findOne("test1-svc", "staging,cloud", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepoWithProfiles() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
String test1RepoUri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
|
||||
|
||||
Map<String, Object> repoMapping = new LinkedHashMap<String, Object>();
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern[0]", "*/staging,*");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern[1]", "*/*,staging");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern[2]", "*/staging");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri);
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri)
|
||||
.properties(repoMapping).run();
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = repository.findOne("test1-svc", "cloud,staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
environment = repository.findOne("test1-svc", "staging,cloud", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepoWithJustUri() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
String test1RepoUri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
|
||||
|
||||
Map<String, Object> repoMapping = new LinkedHashMap<String, Object>();
|
||||
repoMapping.put("spring.cloud.config.server.git.repos.test1-svc", test1RepoUri);
|
||||
context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
repoMapping.put("spring.cloud.config.server.git.repos.test1-svc", test1RepoUri);
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri)
|
||||
.properties(repoMapping).run();
|
||||
EnvironmentRepository repository = context.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = repository.findOne("test1-svc", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
|
||||
Reference in New Issue
Block a user