Fix native profile so it behaves as described in docs
The SCM repositories have a "clean()" method to strip out the server's own configuration files from the property sources shipped to remote clients. The "native" one didn't have that method so this change adds it with a similar implementation to the SCM case, except slightly more complicated because of the extra search locations added by the "label" parameter. Also changes the name SpringApplicationEnvironmentRepository to NativeEnvironmentRepository to match the profile and the config properties. Fixes gh-109
This commit is contained in:
@@ -40,11 +40,11 @@ public abstract class AbstractScmEnvironmentRepository implements EnvironmentRep
|
||||
InitializingBean {
|
||||
private static Log logger = LogFactory.getLog(AbstractScmEnvironmentRepository.class);
|
||||
|
||||
protected File basedir;
|
||||
protected String uri;
|
||||
protected ConfigurableEnvironment environment;
|
||||
protected String username;
|
||||
protected String password;
|
||||
private File basedir;
|
||||
private String uri;
|
||||
private ConfigurableEnvironment environment;
|
||||
private String username;
|
||||
private String password;
|
||||
private String[] searchPaths = new String[0];
|
||||
|
||||
public AbstractScmEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
@@ -72,6 +72,14 @@ public abstract class AbstractScmEnvironmentRepository implements EnvironmentRep
|
||||
throw new IllegalStateException("Cannot create temp dir", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected ConfigurableEnvironment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
protected void setEnvironment(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
while (uri.endsWith("/")) {
|
||||
@@ -148,12 +156,6 @@ public abstract class AbstractScmEnvironmentRepository implements EnvironmentRep
|
||||
for (PropertySource source : value.getPropertySources()) {
|
||||
String name = source.getName().replace(
|
||||
getWorkingDirectory().toURI().toString(), "");
|
||||
if (name.contains(("classpath:/"))) {
|
||||
continue;
|
||||
}
|
||||
if (environment.getPropertySources().contains(name)) {
|
||||
continue;
|
||||
}
|
||||
name = name.replace("applicationConfig: [", "");
|
||||
name = uri + "/" + name.replace("]", "");
|
||||
result.add(new PropertySource(name, source.getSource()));
|
||||
|
||||
@@ -35,10 +35,15 @@ public class ConfigServerConfiguration {
|
||||
@Configuration
|
||||
@Profile("native")
|
||||
protected static class NativeRepositoryConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository() {
|
||||
return new SpringApplicationEnvironmentRepository();
|
||||
return new NativeEnvironmentRepository(environment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -64,14 +64,6 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
super(environment);
|
||||
}
|
||||
|
||||
protected ConfigurableEnvironment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
protected void setEnvironment(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String profile, String label) {
|
||||
initialize();
|
||||
@@ -100,12 +92,13 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(uri != null, "You need to configure a uri for the git repository");
|
||||
Assert.state(getUri() != null,
|
||||
"You need to configure a uri for the git repository");
|
||||
}
|
||||
|
||||
private synchronized Environment loadEnvironment(Git git, String application,
|
||||
String profile, String label) throws GitAPIException {
|
||||
SpringApplicationEnvironmentRepository environment = new SpringApplicationEnvironmentRepository();
|
||||
NativeEnvironmentRepository environment = new NativeEnvironmentRepository(getEnvironment());
|
||||
git.getRepository().getConfig().setString("branch", label, "merge", label);
|
||||
Ref ref = checkout(git, label);
|
||||
if (shouldPull(git, ref)) {
|
||||
@@ -145,7 +138,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
private void pull(Git git, String label, Ref ref) {
|
||||
PullCommand pull = git.pull();
|
||||
try {
|
||||
if (hasText(username)) {
|
||||
if (hasText(getUsername())) {
|
||||
setCredentialsProvider(pull);
|
||||
}
|
||||
pull.call();
|
||||
@@ -162,7 +155,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private Git createGitClient() throws IOException, GitAPIException {
|
||||
if (new File(basedir, ".git").exists()) {
|
||||
if (new File(getBasedir(), ".git").exists()) {
|
||||
return openGitRepository();
|
||||
}
|
||||
else {
|
||||
@@ -172,8 +165,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
private Git copyRepository() throws IOException, GitAPIException {
|
||||
deleteBaseDirIfExists();
|
||||
Assert.state(basedir.mkdirs(), "Could not create basedir: " + basedir);
|
||||
if (uri.startsWith("file:")) {
|
||||
Assert.state(getBasedir().mkdirs(), "Could not create basedir: " + getBasedir());
|
||||
if (getUri().startsWith("file:")) {
|
||||
return copyFromLocalRepository();
|
||||
}
|
||||
else {
|
||||
@@ -189,18 +182,19 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
private Git copyFromLocalRepository() throws IOException {
|
||||
Git git;
|
||||
File remote = new UrlResource(StringUtils.cleanPath(uri)).getFile();
|
||||
Assert.state(remote.isDirectory(), "No directory at " + uri);
|
||||
File remote = new UrlResource(StringUtils.cleanPath(getUri())).getFile();
|
||||
Assert.state(remote.isDirectory(), "No directory at " + getUri());
|
||||
File gitDir = new File(remote, ".git");
|
||||
Assert.state(gitDir.exists(), "No .git at " + uri);
|
||||
Assert.state(gitDir.isDirectory(), "No .git directory at " + uri);
|
||||
Assert.state(gitDir.exists(), "No .git at " + getUri());
|
||||
Assert.state(gitDir.isDirectory(), "No .git directory at " + getUri());
|
||||
git = Git.open(remote);
|
||||
return git;
|
||||
}
|
||||
|
||||
private Git cloneToBasedir() throws GitAPIException {
|
||||
CloneCommand clone = Git.cloneRepository().setURI(uri).setDirectory(basedir);
|
||||
if (hasText(username)) {
|
||||
CloneCommand clone = Git.cloneRepository().setURI(getUri())
|
||||
.setDirectory(getBasedir());
|
||||
if (hasText(getUsername())) {
|
||||
setCredentialsProvider(clone);
|
||||
}
|
||||
return clone.call();
|
||||
@@ -209,7 +203,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
private void tryFetch(Git git) {
|
||||
try {
|
||||
FetchCommand fetch = git.fetch();
|
||||
if (hasText(username)) {
|
||||
if (hasText(getUsername())) {
|
||||
setCredentialsProvider(fetch);
|
||||
}
|
||||
fetch.call();
|
||||
@@ -220,9 +214,9 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private void deleteBaseDirIfExists() {
|
||||
if (basedir.exists()) {
|
||||
if (getBasedir().exists()) {
|
||||
try {
|
||||
FileUtils.delete(basedir, FileUtils.RECURSIVE);
|
||||
FileUtils.delete(getBasedir(), FileUtils.RECURSIVE);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to initialize base directory", e);
|
||||
@@ -231,7 +225,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (uri.startsWith("file:") && !initialized) {
|
||||
if (getUri().startsWith("file:") && !initialized) {
|
||||
SshSessionFactory.setInstance(new JschConfigSessionFactory() {
|
||||
@Override
|
||||
protected void configure(Host hc, Session session) {
|
||||
@@ -243,8 +237,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private void setCredentialsProvider(TransportCommand<?, ?> cmd) {
|
||||
cmd.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username,
|
||||
password));
|
||||
cmd.setCredentialsProvider(new UsernamePasswordCredentialsProvider(getUsername(),
|
||||
getPassword()));
|
||||
}
|
||||
|
||||
private void trackBranch(Git git, CheckoutCommand checkout, String label) {
|
||||
|
||||
@@ -16,35 +16,53 @@
|
||||
|
||||
package org.springframework.cloud.config.server;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link EnvironmentRepository} that just reflects an existing
|
||||
* Spring Environment.
|
||||
* Simple implementation of {@link EnvironmentRepository} that uses a SpringApplication
|
||||
* and configuration files located through the normal protocols. The resulting Environment
|
||||
* is composed of property sources located using the application name as the config file
|
||||
* stem (spring.config.name) and the environment name as a Spring profile.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.native")
|
||||
public class NativeEnvironmentRepository implements EnvironmentRepository {
|
||||
|
||||
private Set<String> standardSources = new HashSet<String>(Arrays.asList(
|
||||
"vcap",
|
||||
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME,
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
|
||||
StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME,
|
||||
StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
|
||||
StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||
private static Log logger = LogFactory
|
||||
.getLog(NativeEnvironmentRepository.class);
|
||||
|
||||
/**
|
||||
* Locations to search for configuration files. Defaults to the same as a Spring Boot
|
||||
* app so [classpath:/,classpath:/config/,file:./,file:./config/].
|
||||
*/
|
||||
private String[] searchLocations;
|
||||
|
||||
/**
|
||||
* Flag to determine how to handle exceptions during decryption (default false).
|
||||
*/
|
||||
private boolean failOnError = false;
|
||||
|
||||
private static final String[] DEFAULT_LOCATIONS = new String[] { "classpath:/",
|
||||
"classpath:/config/", "file:./", "file:./config/" };
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@@ -52,17 +70,146 @@ public class NativeEnvironmentRepository implements EnvironmentRepository {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public void setFailOnError(boolean failOnError) {
|
||||
this.failOnError = failOnError;
|
||||
}
|
||||
|
||||
public boolean isFailOnError() {
|
||||
return failOnError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String env, String label) {
|
||||
Environment result = new Environment(application, StringUtils.commaDelimitedListToStringArray(env), label);
|
||||
for (org.springframework.core.env.PropertySource<?> source : environment.getPropertySources()) {
|
||||
public Environment findOne(String config, String profile, String label) {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
ConfigurableEnvironment environment = getEnvironment(profile);
|
||||
builder.environment(environment);
|
||||
builder.web(false).showBanner(false);
|
||||
String[] args = getArgs(config, label);
|
||||
// Explicitly set the listeners (to exclude logging listener which would change
|
||||
// log
|
||||
// levels in the caller)
|
||||
builder.application().setListeners(
|
||||
Collections.singletonList(new ConfigFileApplicationListener()));
|
||||
ConfigurableApplicationContext context = builder.run(args);
|
||||
environment.getPropertySources().remove("profiles");
|
||||
try {
|
||||
return clean(new PassthruEnvironmentRepository(environment).findOne(config,
|
||||
profile, label));
|
||||
}
|
||||
finally {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurableEnvironment getEnvironment(String profile) {
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
environment.getPropertySources()
|
||||
.addFirst(
|
||||
new MapPropertySource("profiles", Collections
|
||||
.<String, Object> singletonMap("spring.profiles.active",
|
||||
profile)));
|
||||
return environment;
|
||||
}
|
||||
|
||||
protected Environment clean(Environment value) {
|
||||
Environment result = new Environment(value.getName(), value.getProfiles(),
|
||||
value.getLabel());
|
||||
for (PropertySource source : value.getPropertySources()) {
|
||||
String name = source.getName();
|
||||
if (!standardSources.contains(name) && source instanceof MapPropertySource) {
|
||||
result.add(new PropertySource(name, (Map<?, ?>) source.getSource()));
|
||||
if (environment.getPropertySources().contains(name)) {
|
||||
continue;
|
||||
}
|
||||
name = name.replace("applicationConfig: [", "");
|
||||
name = name.replace("]", "");
|
||||
if (searchLocations != null) {
|
||||
boolean matches = false;
|
||||
String normal = name;
|
||||
if (normal.startsWith("file:")) {
|
||||
normal = new File(normal.substring("file:".length()))
|
||||
.getAbsolutePath();
|
||||
}
|
||||
for (String pattern : StringUtils
|
||||
.commaDelimitedListToStringArray(getLocations(searchLocations,
|
||||
result.getLabel()))) {
|
||||
if (!pattern.contains(":")) {
|
||||
pattern = "file:" + pattern;
|
||||
}
|
||||
if (pattern.startsWith("file:")) {
|
||||
pattern = StringUtils.cleanPath(new File(pattern
|
||||
.substring("file:".length())).getAbsolutePath()) + "/";
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Testing pattern: " + pattern
|
||||
+ " with property source: " + name);
|
||||
}
|
||||
if (normal.startsWith(pattern)
|
||||
&& !normal.substring(pattern.length()).contains("/")) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matches) {
|
||||
// Don't include this one: it wasn't matched by our search locations
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not adding property source: " + name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
logger.info("Adding property source: " + name);
|
||||
result.add(new PropertySource(name, source.getSource()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String[] getArgs(String config, String label) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
if (!config.startsWith("application")) {
|
||||
config = "application," + config;
|
||||
}
|
||||
list.add("--spring.config.name=" + config);
|
||||
list.add("--spring.cloud.bootstrap.enabled=false");
|
||||
list.add("--encrypt.failOnError=" + failOnError);
|
||||
String[] locations = this.searchLocations;
|
||||
if (searchLocations == null) {
|
||||
locations = DEFAULT_LOCATIONS;
|
||||
}
|
||||
list.add("--spring.config.location=" + getLocations(locations, label));
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private String getLocations(String[] locations, String label) {
|
||||
List<String> output = new ArrayList<String>();
|
||||
for (String location : locations) {
|
||||
output.add(location);
|
||||
}
|
||||
for (String location : locations) {
|
||||
if (isDirectory(location) && StringUtils.hasText(label)) {
|
||||
output.add(location + label.trim() + "/");
|
||||
}
|
||||
}
|
||||
return StringUtils.collectionToCommaDelimitedString(output);
|
||||
}
|
||||
|
||||
public String[] getSearchLocations() {
|
||||
return searchLocations;
|
||||
}
|
||||
|
||||
public void setSearchLocations(String... locations) {
|
||||
this.searchLocations = locations;
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
String location = locations[i];
|
||||
if (isDirectory(location) && !location.endsWith("/")) {
|
||||
location = location + "/";
|
||||
}
|
||||
locations[i] = location;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDirectory(String location) {
|
||||
return !location.endsWith(".properties") && !location.endsWith(".yml")
|
||||
&& !location.endsWith(".yaml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2013-2014 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link EnvironmentRepository} that just reflects an existing
|
||||
* Spring Environment.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class PassthruEnvironmentRepository implements EnvironmentRepository {
|
||||
|
||||
private Set<String> standardSources = new HashSet<String>(Arrays.asList(
|
||||
"vcap",
|
||||
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME,
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
|
||||
StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME,
|
||||
StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
|
||||
StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
public PassthruEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String env, String label) {
|
||||
Environment result = new Environment(application, StringUtils.commaDelimitedListToStringArray(env), label);
|
||||
for (org.springframework.core.env.PropertySource<?> source : environment.getPropertySources()) {
|
||||
String name = source.getName();
|
||||
if (!standardSources.contains(name) && source instanceof MapPropertySource) {
|
||||
result.add(new PropertySource(name, (Map<?, ?>) source.getSource()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link EnvironmentRepository} that uses a SpringApplication
|
||||
* and configuration files located through the normal protocols. The resulting Environment
|
||||
* is composed of property sources located using the application name as the config file
|
||||
* stem (spring.config.name) and the environment name as a Spring profile.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.native")
|
||||
public class SpringApplicationEnvironmentRepository implements EnvironmentRepository {
|
||||
|
||||
/**
|
||||
* Locations to search for configuration files. Defaults to the same as a Spring Boot
|
||||
* app so [classpath:/,classpath:/config/,file:./,file:./config/].
|
||||
*/
|
||||
private String[] searchLocations;
|
||||
|
||||
/**
|
||||
* Flag to determine how to handle exceptions during decryption (default false).
|
||||
*/
|
||||
private boolean failOnError = false;
|
||||
|
||||
private static final String[] DEFAULT_LOCATIONS = new String[] { "classpath:/",
|
||||
"classpath:/config/", "file:./", "file:./config/" };
|
||||
|
||||
public void setFailOnError(boolean failOnError) {
|
||||
this.failOnError = failOnError;
|
||||
}
|
||||
|
||||
public boolean isFailOnError() {
|
||||
return failOnError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String config, String profile, String label) {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
ConfigurableEnvironment environment = getEnvironment(profile);
|
||||
builder.environment(environment);
|
||||
builder.web(false).showBanner(false);
|
||||
String[] args = getArgs(config, label);
|
||||
// Explicitly set the listeners (to exclude logging listener which would change log
|
||||
// levels in the caller)
|
||||
builder.application().setListeners(
|
||||
Collections.singletonList(new ConfigFileApplicationListener()));
|
||||
ConfigurableApplicationContext context = builder.run(args);
|
||||
environment.getPropertySources().remove("profiles");
|
||||
try {
|
||||
return new NativeEnvironmentRepository(environment).findOne(config, profile,
|
||||
label);
|
||||
}
|
||||
finally {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurableEnvironment getEnvironment(String profile) {
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
environment.getPropertySources()
|
||||
.addFirst(
|
||||
new MapPropertySource("profiles", Collections
|
||||
.<String, Object> singletonMap("spring.profiles.active",
|
||||
profile)));
|
||||
return environment;
|
||||
}
|
||||
|
||||
private String[] getArgs(String config, String label) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
if (!config.startsWith("application")) {
|
||||
config = "application," + config;
|
||||
}
|
||||
list.add("--spring.config.name=" + config);
|
||||
list.add("--spring.cloud.bootstrap.enabled=false");
|
||||
list.add("--encrypt.failOnError=" + failOnError);
|
||||
if (searchLocations != null) {
|
||||
list.add("--spring.config.location=" + getLocations(this.searchLocations, label));
|
||||
}
|
||||
else {
|
||||
list.add("--spring.config.location=" + getLocations(DEFAULT_LOCATIONS, label));
|
||||
}
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private String getLocations(String[] locations, String label) {
|
||||
List<String> output = new ArrayList<String>();
|
||||
for (String location : locations) {
|
||||
output.add(location);
|
||||
}
|
||||
for (String location : locations) {
|
||||
if (isDirectory(location) && StringUtils.hasText(label)) {
|
||||
output.add(location + label.trim() + "/");
|
||||
}
|
||||
}
|
||||
return StringUtils.collectionToCommaDelimitedString(output);
|
||||
}
|
||||
|
||||
public String[] getSearchLocations() {
|
||||
return searchLocations;
|
||||
}
|
||||
|
||||
public void setSearchLocations(String... locations) {
|
||||
this.searchLocations = locations;
|
||||
for (int i = 0; i < locations.length; i++) {
|
||||
String location = locations[i];
|
||||
if (isDirectory(location) && !location.endsWith("/")) {
|
||||
location = location + "/";
|
||||
}
|
||||
locations[i] = location;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDirectory(String location) {
|
||||
return !location.endsWith(".properties") && !location.endsWith(".yml")
|
||||
&& !location.endsWith(".yaml");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,7 +71,8 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
}
|
||||
|
||||
private Environment loadEnvironment(String application, String profile, String label) {
|
||||
final SpringApplicationEnvironmentRepository environmentRepository = new SpringApplicationEnvironmentRepository();
|
||||
final NativeEnvironmentRepository environmentRepository = new NativeEnvironmentRepository(
|
||||
getEnvironment());
|
||||
environmentRepository.setSearchLocations(getSearchLocations(getSvnPath(
|
||||
getWorkingDirectory(), label)));
|
||||
return environmentRepository.findOne(application, profile, label);
|
||||
@@ -116,7 +117,7 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
|
||||
@Override
|
||||
protected File getWorkingDirectory() {
|
||||
return this.basedir;
|
||||
return this.getBasedir();
|
||||
}
|
||||
|
||||
private File getSvnPath(File workingDirectory, String label) {
|
||||
|
||||
@@ -19,16 +19,17 @@ import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.SpringApplicationEnvironmentRepository;
|
||||
|
||||
import org.springframework.cloud.config.server.NativeEnvironmentRepository;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class SpringApplicationEnvironmentRepositoryTests {
|
||||
|
||||
private SpringApplicationEnvironmentRepository repository = new SpringApplicationEnvironmentRepository();
|
||||
public class NativeEnvironmentRepositoryTests {
|
||||
|
||||
private NativeEnvironmentRepository repository = new NativeEnvironmentRepository(
|
||||
new StandardEnvironment());
|
||||
|
||||
@Test
|
||||
public void vanilla() {
|
||||
@@ -47,23 +48,25 @@ public class SpringApplicationEnvironmentRepositoryTests {
|
||||
public void prefixed() {
|
||||
repository.setSearchLocations("classpath:/test");
|
||||
Environment environment = repository.findOne("foo", "development", "master");
|
||||
assertEquals(3, environment.getPropertySources().size());
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefixedWithFile() {
|
||||
repository.setSearchLocations("file:./src/test/resources/test");
|
||||
Environment environment = repository.findOne("foo", "development", "master");
|
||||
assertEquals(3, environment.getPropertySources().size());
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void labelled() {
|
||||
repository.setSearchLocations("classpath:/test");
|
||||
Environment environment = repository.findOne("foo", "development", "dev");
|
||||
assertEquals(4, environment.getPropertySources().size());
|
||||
// position 1 because it has higher precendence than anything except the foo-development.properties
|
||||
assertEquals("dev_bar", environment.getPropertySources().get(1).getSource().get("foo"));
|
||||
assertEquals(3, environment.getPropertySources().size());
|
||||
// position 1 because it has higher precendence than anything except the
|
||||
// foo-development.properties
|
||||
assertEquals("dev_bar",
|
||||
environment.getPropertySources().get(1).getSource().get("foo"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
bar: spam
|
||||
Reference in New Issue
Block a user