Support new delimiters in spring.config.location (#1904)

This commit is contained in:
Ryan Baxter
2021-06-10 13:50:44 -04:00
committed by GitHub
parent b1e795d8d1
commit c6a07ed234
19 changed files with 93 additions and 37 deletions

View File

@@ -17,6 +17,7 @@
package org.springframework.cloud.config.server.environment;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -224,7 +225,7 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
map.put("spring.config.name", config);
// map.put("encrypt.failOnError=" + this.failOnError);
map.put("spring.config.location",
StringUtils.arrayToCommaDelimitedString(getLocations(application, profile, label).getLocations()));
StringUtils.arrayToDelimitedString(getLocations(application, profile, label).getLocations(), ";"));
// globally ignore config files that are not found
map.put("spring.config.on-not-found", "IGNORE");
environment.getPropertySources().addFirst(new MapPropertySource("config-data-setup", map));
@@ -245,7 +246,7 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
if (this.environment.getPropertySources().contains(name)) {
continue;
}
String location = null;
String[] locations = null;
PropertySourceConfigData configData = propertySourceToConfigData.get(source.getOriginalPropertySource());
// try and get information directly from ConfigData
@@ -253,17 +254,16 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
StandardConfigDataResource configDataResource = (StandardConfigDataResource) configData.resource;
// use StandardConfigDataResource as that format is expected still
name = configDataResource.toString();
location = configData.location.toString();
locations = configDataLocations(configData.location.split());
}
else {
// if not, try and parse
Matcher matcher = RESOURCE_PATTERN.matcher(name);
if (matcher.find()) {
name = matcher.group(1);
location = matcher.group(2);
locations = new String[] { matcher.group(2) };
}
}
// TODO: needed anymore?
name = name.replace("applicationConfig: [", "");
name = name.replace("file [", "file:");
if (name.indexOf('[') < 0) {
@@ -271,38 +271,7 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
name = name.replace("]", "");
}
if (this.searchLocations != null) {
boolean matches = false;
String normal = name;
if (normal.startsWith("file:")) {
normal = StringUtils.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()) {
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 (location != null && location.startsWith("file:")) {
location = StringUtils
.cleanPath(new File(location.substring("file:".length())).getAbsolutePath()) + "/";
}
if (location != null && location.startsWith(pattern)
&& !location.substring(pattern.length()).contains("/")) {
matches = true;
break;
}
}
boolean matches = matchesLocation(locations, name, result);
if (!matches) {
// Don't include this one: it wasn't matched by our search locations
if (logger.isDebugEnabled()) {
@@ -324,6 +293,53 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
return result;
}
private String[] configDataLocations(ConfigDataLocation[] locations) {
String[] stringLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
stringLocations[i] = locations[i].toString();
}
return stringLocations;
}
private boolean matchesLocation(String[] locations, String name, Environment result) {
boolean matches = false;
String normal = name;
if (normal.startsWith("file:")) {
normal = StringUtils.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()) {
if (!pattern.contains(":")) {
pattern = "file:" + pattern;
}
if (pattern.startsWith("file:")) {
pattern = StringUtils.cleanPath(new File(pattern.substring("file:".length())).getAbsolutePath()) + "/";
}
final String finalPattern = pattern;
if (logger.isTraceEnabled()) {
logger.trace("Testing pattern: " + finalPattern + " with property source: " + name);
}
if (normal.startsWith(finalPattern) && !normal.substring(finalPattern.length()).contains("/")) {
matches = true;
break;
}
if (locations != null) {
return !Arrays.stream(locations).map(this::cleanFileLocation)
.noneMatch(location -> location.startsWith(finalPattern)
&& !location.substring(finalPattern.length()).contains("/"));
}
}
return matches;
}
private String cleanFileLocation(String location) {
if (location.startsWith("file:")) {
return StringUtils.cleanPath(new File(location.substring("file:".length())).getAbsolutePath()) + "/";
}
return location;
}
public String[] getSearchLocations() {
return this.searchLocations;
}

View File

@@ -219,6 +219,20 @@ public class JGitEnvironmentRepositoryIntegrationTests {
assertThat(environment.getPropertySources().size()).isEqualTo(3);
}
@Test
public void verifyPropertySourceOrdering() throws IOException {
String uri = ConfigServerTestUtils.prepareLocalRepo("ordering-repo");
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
.run("--spring.cloud.config.server.git.uri=" + uri, "--spring.cloud.config.server.git.searchPaths=**");
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
Environment environment = repository.findOne("application", "test", "master");
assertThat(environment.getPropertySources().size()).isEqualTo(2);
assertThat(environment.getPropertySources().get(0).getName())
.isEqualTo("file:././target/repos/ordering-repo//project/sub/application-test.yml");
assertThat(environment.getPropertySources().get(1).getName())
.isEqualTo("file:././target/repos/ordering-repo//project/application.yml");
}
@Test
public void nestedWithProfilePlaceholders() throws IOException {
String uri = ConfigServerTestUtils.prepareLocalRepo("nested-repo");

View File

@@ -0,0 +1 @@
initial commit

View File

@@ -0,0 +1 @@
ref: refs/heads/master

View File

@@ -0,0 +1,7 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true

View File

@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@@ -0,0 +1 @@
0000000000000000000000000000000000000000 8265220d6be7d73011cbc98382b499e5d7169fe7 Ryan Baxter <rbaxter@pivotal.io> 1623269485 -0400 commit (initial): initial commit

View File

@@ -0,0 +1 @@
0000000000000000000000000000000000000000 8265220d6be7d73011cbc98382b499e5d7169fe7 Ryan Baxter <rbaxter@pivotal.io> 1623269485 -0400 commit (initial): initial commit

View File

@@ -0,0 +1,2 @@
x<01><>A
<EFBFBD>0E]<5D>se<><65>iD<>#x<>I<EFBFBD><49>@<40>HEo/<2F><13><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>uY<75>B7<42>N<EFBFBD>8Z$ <09><>J<EFBFBD>'<27>28<32>('r1F<11>!<21><>~<7E><>6<EFBFBD><36>y<EFBFBD> <0B>tlpli<1B>{yV<79><56>P<EFBFBD> <09>`<60>

View File

@@ -0,0 +1 @@
8265220d6be7d73011cbc98382b499e5d7169fe7

View File

@@ -0,0 +1,3 @@
info:
foo: bar
raw: true

View File

@@ -0,0 +1,2 @@
info:
foo: profile