diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java index 5f05761c..a49835d6 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java @@ -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; } diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java index c77b9c09..0da8da47 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryIntegrationTests.java @@ -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"); diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/COMMIT_EDITMSG b/spring-cloud-config-server/src/test/resources/ordering-repo/git/COMMIT_EDITMSG new file mode 100644 index 00000000..80260766 --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/COMMIT_EDITMSG @@ -0,0 +1 @@ +initial commit diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/HEAD b/spring-cloud-config-server/src/test/resources/ordering-repo/git/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/config b/spring-cloud-config-server/src/test/resources/ordering-repo/git/config new file mode 100644 index 00000000..6c9406b7 --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/config @@ -0,0 +1,7 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = true diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/description b/spring-cloud-config-server/src/test/resources/ordering-repo/git/description new file mode 100644 index 00000000..498b267a --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/index b/spring-cloud-config-server/src/test/resources/ordering-repo/git/index new file mode 100644 index 00000000..9636a1b1 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/ordering-repo/git/index differ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/info/exclude b/spring-cloud-config-server/src/test/resources/ordering-repo/git/info/exclude new file mode 100644 index 00000000..a5196d1b --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/info/exclude @@ -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] +# *~ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/logs/HEAD b/spring-cloud-config-server/src/test/resources/ordering-repo/git/logs/HEAD new file mode 100644 index 00000000..6cc2571d --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 8265220d6be7d73011cbc98382b499e5d7169fe7 Ryan Baxter 1623269485 -0400 commit (initial): initial commit diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/logs/refs/heads/master b/spring-cloud-config-server/src/test/resources/ordering-repo/git/logs/refs/heads/master new file mode 100644 index 00000000..6cc2571d --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 8265220d6be7d73011cbc98382b499e5d7169fe7 Ryan Baxter 1623269485 -0400 commit (initial): initial commit diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/02/09d6d392d65f4ad734b9cb938889ddd40683f4 b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/02/09d6d392d65f4ad734b9cb938889ddd40683f4 new file mode 100644 index 00000000..23f4a161 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/02/09d6d392d65f4ad734b9cb938889ddd40683f4 differ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/1c/cddaee9468c2f249e75dc81e50877935955866 b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/1c/cddaee9468c2f249e75dc81e50877935955866 new file mode 100644 index 00000000..9a8041bf Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/1c/cddaee9468c2f249e75dc81e50877935955866 differ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/7a/68a4bbc80b44c287787e2306ff9fd7de35cc54 b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/7a/68a4bbc80b44c287787e2306ff9fd7de35cc54 new file mode 100644 index 00000000..cd40d0e0 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/7a/68a4bbc80b44c287787e2306ff9fd7de35cc54 differ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/82/65220d6be7d73011cbc98382b499e5d7169fe7 b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/82/65220d6be7d73011cbc98382b499e5d7169fe7 new file mode 100644 index 00000000..7c01b9a0 --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/82/65220d6be7d73011cbc98382b499e5d7169fe7 @@ -0,0 +1,2 @@ +xA +0E]seiD#xI@HEo/uYB7N8Z$ J'28('r1F!~6y tlpli{yVP ` c{&o_הh~C: \ No newline at end of file diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/ad/bec8abd5dd965a0d9a62fc5bd457ce0dec5727 b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/ad/bec8abd5dd965a0d9a62fc5bd457ce0dec5727 new file mode 100644 index 00000000..ba0830da Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/ad/bec8abd5dd965a0d9a62fc5bd457ce0dec5727 differ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/fc/4aeb82a374f50cae0654d8db79dda083eff3d7 b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/fc/4aeb82a374f50cae0654d8db79dda083eff3d7 new file mode 100644 index 00000000..2eb254b4 Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/ordering-repo/git/objects/fc/4aeb82a374f50cae0654d8db79dda083eff3d7 differ diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/git/refs/heads/master b/spring-cloud-config-server/src/test/resources/ordering-repo/git/refs/heads/master new file mode 100644 index 00000000..5bf99054 --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/git/refs/heads/master @@ -0,0 +1 @@ +8265220d6be7d73011cbc98382b499e5d7169fe7 diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/project/application.yml b/spring-cloud-config-server/src/test/resources/ordering-repo/project/application.yml new file mode 100644 index 00000000..7a68a4bb --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/project/application.yml @@ -0,0 +1,3 @@ +info: + foo: bar +raw: true diff --git a/spring-cloud-config-server/src/test/resources/ordering-repo/project/sub/application-test.yml b/spring-cloud-config-server/src/test/resources/ordering-repo/project/sub/application-test.yml new file mode 100644 index 00000000..adbec8ab --- /dev/null +++ b/spring-cloud-config-server/src/test/resources/ordering-repo/project/sub/application-test.yml @@ -0,0 +1,2 @@ +info: + foo: profile