Add placeholder substitution to search paths within SCM repository
E.g. ...searchPaths={application}/ to search the directory with the
same name as the application (in addition to the root).
Fixes gh-328
This commit is contained in:
@@ -315,6 +315,28 @@ that should be applicable. HTTPS proxy settings can be set in
|
||||
`~/.git/config` or in the same way as for any other JVM process via
|
||||
system properties (`-Dhttps.proxyHost` and `-Dhttps.proxyPort`).
|
||||
|
||||
===== Placeholders in Git Search Paths
|
||||
|
||||
Spring Cloud Config Server also supports a search path with
|
||||
placeholders for the `{application}` and `{profile}` (and `{label}` if
|
||||
you need it). Example:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
git:
|
||||
uri: https://github.com/spring-cloud-samples/config-repo
|
||||
searchPaths: {application}
|
||||
----
|
||||
|
||||
searches the repository for files in the same name as the directory
|
||||
(as well as the top level). Wildcards are also valid in a search
|
||||
path with placeholders (any matching directory is included in the
|
||||
search).
|
||||
|
||||
==== File System Backend
|
||||
|
||||
There is also a "native" profile in the Config Server that doesn't use
|
||||
|
||||
@@ -124,7 +124,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
version = ref.getObjectId().getName();
|
||||
}
|
||||
return new Locations(application, profile, label, version,
|
||||
getSearchLocations(getWorkingDirectory()));
|
||||
getSearchLocations(getWorkingDirectory(), application, profile, label));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -146,8 +146,11 @@ public class NativeEnvironmentRepository
|
||||
}
|
||||
}
|
||||
for (String location : locations) {
|
||||
if (isDirectory(location) && StringUtils.hasText(label)) {
|
||||
output.add(location + label.trim() + "/");
|
||||
if (StringUtils.hasText(label)) {
|
||||
String labelled = location + label.trim() + "/";
|
||||
if (isDirectory(labelled)) {
|
||||
output.add(labelled);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Locations(application, profile, label, this.version,
|
||||
|
||||
@@ -54,7 +54,7 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
private String defaultLabel = DEFAULT_LABEL;
|
||||
|
||||
public String getDefaultLabel() {
|
||||
return this.defaultLabel ;
|
||||
return this.defaultLabel;
|
||||
}
|
||||
|
||||
public void setDefaultLabel(String defaultLabel) {
|
||||
@@ -62,8 +62,9 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Locations getLocations(String application, String profile, String label) {
|
||||
if (label==null) {
|
||||
public synchronized Locations getLocations(String application, String profile,
|
||||
String label) {
|
||||
if (label == null) {
|
||||
label = this.defaultLabel;
|
||||
}
|
||||
SvnOperationFactory svnOperationFactory = new SvnOperationFactory();
|
||||
@@ -80,7 +81,8 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
else {
|
||||
version = checkout(svnOperationFactory);
|
||||
}
|
||||
return new Locations(application, profile, label, version, getLocations(label));
|
||||
return new Locations(application, profile, label, version,
|
||||
getPaths(application, profile, label));
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new IllegalStateException("Cannot checkout repository", e);
|
||||
@@ -90,8 +92,8 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getLocations(String label) {
|
||||
String[] locations = getSearchLocations(getSvnPath(getWorkingDirectory(), label));
|
||||
private String[] getPaths(String application, String profile, String label) {
|
||||
String[] locations = getSearchLocations(getSvnPath(getWorkingDirectory(), label), application, profile, label);
|
||||
boolean exists = false;
|
||||
for (String location : locations) {
|
||||
location = location.startsWith("file:") ? location.substring("file:".length())
|
||||
|
||||
@@ -20,14 +20,20 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -36,7 +42,9 @@ import org.springframework.util.StringUtils;
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class AbstractScmAccessor {
|
||||
public class AbstractScmAccessor implements ResourceLoaderAware {
|
||||
|
||||
private static final String[] DEFAULT_LOCATIONS = new String[] {"/"};
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
/**
|
||||
@@ -59,13 +67,20 @@ public class AbstractScmAccessor {
|
||||
/**
|
||||
* Search paths to use within local working copy. By default searches only the root.
|
||||
*/
|
||||
private String[] searchPaths = new String[0];
|
||||
private String[] searchPaths = DEFAULT_LOCATIONS;
|
||||
|
||||
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
|
||||
public AbstractScmAccessor(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
this.basedir = createBaseDir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
protected File createBaseDir() {
|
||||
try {
|
||||
final File basedir = Files.createTempDirectory("config-repo-").toFile();
|
||||
@@ -76,7 +91,8 @@ public class AbstractScmAccessor {
|
||||
FileUtils.delete(basedir, FileUtils.RECURSIVE);
|
||||
}
|
||||
catch (IOException e) {
|
||||
AbstractScmAccessor.this.logger.warn("Failed to delete temporary directory on exit: " + e);
|
||||
AbstractScmAccessor.this.logger.warn(
|
||||
"Failed to delete temporary directory on exit: " + e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -100,7 +116,7 @@ public class AbstractScmAccessor {
|
||||
uri = uri.substring(0, uri.length() - 1);
|
||||
}
|
||||
int index = uri.indexOf("://");
|
||||
if (index>0 && !uri.substring(index+"://".length()).contains("/")) {
|
||||
if (index > 0 && !uri.substring(index + "://".length()).contains("/")) {
|
||||
// If there's no context path add one
|
||||
uri = uri + "/";
|
||||
}
|
||||
@@ -149,25 +165,63 @@ public class AbstractScmAccessor {
|
||||
return new UrlResource(StringUtils.cleanPath(this.uri)).getFile();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot convert uri to file: " + this.uri);
|
||||
throw new IllegalStateException(
|
||||
"Cannot convert uri to file: " + this.uri);
|
||||
}
|
||||
}
|
||||
return this.basedir;
|
||||
}
|
||||
|
||||
protected String[] getSearchLocations(File dir) {
|
||||
List<String> locations = new ArrayList<String>();
|
||||
locations.add(dir.toURI().toString());
|
||||
String[] list = dir.list();
|
||||
if (list!=null) {
|
||||
for (String path : list) {
|
||||
File file = new File(dir, path);
|
||||
if (file.isDirectory() && PatternMatchUtils.simpleMatch(this.searchPaths, path)) {
|
||||
locations.add(file.toURI().toString());
|
||||
protected String[] getSearchLocations(File dir, String application, String profile,
|
||||
String label) {
|
||||
String[] locations = this.searchPaths;
|
||||
if (locations == null || locations.length == 0) {
|
||||
locations = DEFAULT_LOCATIONS;
|
||||
} else {
|
||||
locations = StringUtils.concatenateStringArrays(DEFAULT_LOCATIONS, locations);
|
||||
}
|
||||
Collection<String> output = new LinkedHashSet<String>();
|
||||
for (String location : locations) {
|
||||
String[] profiles = new String[] { profile };
|
||||
if (profile != null) {
|
||||
profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
}
|
||||
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 + "/";
|
||||
}
|
||||
output.addAll(matchingDirectories(dir, value));
|
||||
}
|
||||
}
|
||||
return output.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private List<String> matchingDirectories(File dir, String value) {
|
||||
List<String> output = new ArrayList<String>();
|
||||
try {
|
||||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(
|
||||
this.resourceLoader);
|
||||
String path = new File(dir, value).toURI().toString();
|
||||
for (Resource resource : resolver.getResources(path)) {
|
||||
if (resource.getFile().isDirectory()) {
|
||||
output.add(resource.getURI().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return locations.toArray(new String[0]);
|
||||
catch (IOException e) {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -83,6 +83,19 @@ public class JGitEnvironmentRepositoryTests {
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeholderInSearchPath() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.repository.setUri(uri);
|
||||
this.repository.setSearchPaths(new String[] {"{application}"});
|
||||
this.repository.findOne("sub", "staging", "master");
|
||||
Environment environment = this.repository.findOne("sub", "staging", "master");
|
||||
assertEquals(1, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/sub/application.yml",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
private void assertVersion(Environment environment) {
|
||||
String version = environment.getVersion();
|
||||
assertNotNull("version was null", version);
|
||||
|
||||
Reference in New Issue
Block a user