Commit 378c4c95 authored by Madhura Bhave's avatar Madhura Bhave Committed by Phillip Webb

Stop included profiles overriding active profiles

Update `ConfigFileApplicationListener` so that `spring.profiles.include`
properties do not override higher priority active profiles.

This commit also changes when profiles get added to the environment.
Profiles are now added to the environment at the time of profile
processing so that they get logged in the order that they are processed.

Closes gh-13151
parent 60a4d67b
...@@ -328,6 +328,9 @@ public class ConfigFileApplicationListener ...@@ -328,6 +328,9 @@ public class ConfigFileApplicationListener
initializeProfiles(); initializeProfiles();
while (!this.profiles.isEmpty()) { while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll(); Profile profile = this.profiles.poll();
if (profile != null && !profile.isDefaultProfile()) {
addProfileToEnvironment(profile.getName());
}
load(profile, this::getPositiveProfileFilter, load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false)); addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile); this.processedProfiles.add(profile);
...@@ -347,15 +350,13 @@ public class ConfigFileApplicationListener ...@@ -347,15 +350,13 @@ public class ConfigFileApplicationListener
// first so that it is processed first and has lowest priority. // first so that it is processed first and has lowest priority.
this.profiles.add(null); this.profiles.add(null);
Set<Profile> activatedViaProperty = getProfilesActivatedViaProperty(); Set<Profile> activatedViaProperty = getProfilesActivatedViaProperty();
processOtherActiveProfiles(activatedViaProperty); this.profiles.addAll(getOtherActiveProfiles(activatedViaProperty));
// Any pre-existing active profiles set via property sources (e.g. // Any pre-existing active profiles set via property sources (e.g.
// System // System properties) take precedence over those added in config files.
// properties) take precedence over those added in config files.
addActiveProfiles(activatedViaProperty); addActiveProfiles(activatedViaProperty);
if (this.profiles.size() == 1) { // only has null profile if (this.profiles.size() == 1) { // only has null profile
for (String defaultProfileName : this.environment.getDefaultProfiles()) { for (String defaultProfileName : this.environment.getDefaultProfiles()) {
ConfigFileApplicationListener.Profile defaultProfile = new ConfigFileApplicationListener.Profile( Profile defaultProfile = new Profile(defaultProfileName, true);
defaultProfileName, true);
this.profiles.add(defaultProfile); this.profiles.add(defaultProfile);
} }
} }
...@@ -373,19 +374,22 @@ public class ConfigFileApplicationListener ...@@ -373,19 +374,22 @@ public class ConfigFileApplicationListener
return activeProfiles; return activeProfiles;
} }
private void processOtherActiveProfiles(Set<Profile> activatedViaProperty) { private List<Profile> getOtherActiveProfiles(Set<Profile> activatedViaProperty) {
List<Profile> otherActiveProfiles = Arrays return Arrays.stream(this.environment.getActiveProfiles()).map(Profile::new)
.stream(this.environment.getActiveProfiles()).map(Profile::new) .filter((profile) -> !activatedViaProperty.contains(profile))
.filter((o) -> !activatedViaProperty.contains(o))
.collect(Collectors.toList()); .collect(Collectors.toList());
this.profiles.addAll(otherActiveProfiles);
} }
void addActiveProfiles(Set<Profile> profiles) { void addActiveProfiles(Set<Profile> profiles) {
if (this.activatedProfiles || profiles.isEmpty()) { if (profiles.isEmpty()) {
return;
}
if (this.activatedProfiles) {
this.logger.debug("Profiles already activated, '" + profiles
+ "' will not be applied");
return; return;
} }
addProfiles(profiles); this.profiles.addAll(profiles);
if (this.logger.isDebugEnabled()) { if (this.logger.isDebugEnabled()) {
this.logger.debug("Activated activeProfiles " this.logger.debug("Activated activeProfiles "
+ StringUtils.collectionToCommaDelimitedString(profiles)); + StringUtils.collectionToCommaDelimitedString(profiles));
...@@ -394,13 +398,6 @@ public class ConfigFileApplicationListener ...@@ -394,13 +398,6 @@ public class ConfigFileApplicationListener
removeUnprocessedDefaultProfiles(); removeUnprocessedDefaultProfiles();
} }
void addProfiles(Set<Profile> profiles) {
for (Profile profile : profiles) {
this.profiles.add(profile);
addProfileToEnvironment(profile.getName());
}
}
private void removeUnprocessedDefaultProfiles() { private void removeUnprocessedDefaultProfiles() {
this.profiles.removeIf( this.profiles.removeIf(
(profile) -> (profile != null && profile.isDefaultProfile())); (profile) -> (profile != null && profile.isDefaultProfile()));
...@@ -526,7 +523,7 @@ public class ConfigFileApplicationListener ...@@ -526,7 +523,7 @@ public class ConfigFileApplicationListener
for (Document document : documents) { for (Document document : documents) {
if (filter.match(document)) { if (filter.match(document)) {
addActiveProfiles(document.getActiveProfiles()); addActiveProfiles(document.getActiveProfiles());
addProfiles(document.getIncludeProfiles()); addIncludedProfiles(document.getIncludeProfiles());
loaded.add(document); loaded.add(document);
} }
} }
...@@ -542,6 +539,13 @@ public class ConfigFileApplicationListener ...@@ -542,6 +539,13 @@ public class ConfigFileApplicationListener
} }
} }
private void addIncludedProfiles(Set<Profile> includeProfiles) {
LinkedList<Profile> existingProfiles = new LinkedList<>(this.profiles);
this.profiles.clear();
this.profiles.addAll(includeProfiles);
this.profiles.addAll(existingProfiles);
}
private List<Document> loadDocuments(PropertySourceLoader loader, String name, private List<Document> loadDocuments(PropertySourceLoader loader, String name,
Resource resource) throws IOException { Resource resource) throws IOException {
DocumentsCacheKey cacheKey = new DocumentsCacheKey(loader, resource); DocumentsCacheKey cacheKey = new DocumentsCacheKey(loader, resource);
......
...@@ -94,7 +94,7 @@ public class ConfigFileApplicationListenerYamlProfileNegationTests { ...@@ -94,7 +94,7 @@ public class ConfigFileApplicationListenerYamlProfileNegationTests {
application.setWebApplicationType(WebApplicationType.NONE); application.setWebApplicationType(WebApplicationType.NONE);
String configName = "--spring.config.name=cascadingprofiles"; String configName = "--spring.config.name=cascadingprofiles";
this.context = application.run(configName); this.context = application.run(configName);
assertVersionProperty(this.context, "E", "A", "B", "C", "E", "D"); assertVersionProperty(this.context, "D", "A", "C", "E", "B", "D");
assertThat(this.context.getEnvironment().getProperty("not-a")).isNull(); assertThat(this.context.getEnvironment().getProperty("not-a")).isNull();
assertThat(this.context.getEnvironment().getProperty("not-b")).isNull(); assertThat(this.context.getEnvironment().getProperty("not-b")).isNull();
assertThat(this.context.getEnvironment().getProperty("not-c")).isNull(); assertThat(this.context.getEnvironment().getProperty("not-c")).isNull();
......
...@@ -12,6 +12,7 @@ spring: ...@@ -12,6 +12,7 @@ spring:
include: include:
- C - C
- E - E
version: A
--- ---
spring.profiles: B spring.profiles: B
...@@ -21,6 +22,19 @@ spring: ...@@ -21,6 +22,19 @@ spring:
include: include:
- D - D
- E - E
version: B
---
spring.profiles: C
version: C
---
spring.profiles: D
version: D
--- ---
spring.profiles: E spring.profiles: E
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment