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
pull/13388/head
Madhura Bhave 7 years ago committed by Phillip Webb
parent 60a4d67b13
commit 378c4c9535

@ -328,6 +328,9 @@ public class ConfigFileApplicationListener
initializeProfiles();
while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll();
if (profile != null && !profile.isDefaultProfile()) {
addProfileToEnvironment(profile.getName());
}
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
@ -347,15 +350,13 @@ public class ConfigFileApplicationListener
// first so that it is processed first and has lowest priority.
this.profiles.add(null);
Set<Profile> activatedViaProperty = getProfilesActivatedViaProperty();
processOtherActiveProfiles(activatedViaProperty);
this.profiles.addAll(getOtherActiveProfiles(activatedViaProperty));
// Any pre-existing active profiles set via property sources (e.g.
// System
// properties) take precedence over those added in config files.
// System properties) take precedence over those added in config files.
addActiveProfiles(activatedViaProperty);
if (this.profiles.size() == 1) { // only has null profile
for (String defaultProfileName : this.environment.getDefaultProfiles()) {
ConfigFileApplicationListener.Profile defaultProfile = new ConfigFileApplicationListener.Profile(
defaultProfileName, true);
Profile defaultProfile = new Profile(defaultProfileName, true);
this.profiles.add(defaultProfile);
}
}
@ -373,19 +374,22 @@ public class ConfigFileApplicationListener
return activeProfiles;
}
private void processOtherActiveProfiles(Set<Profile> activatedViaProperty) {
List<Profile> otherActiveProfiles = Arrays
.stream(this.environment.getActiveProfiles()).map(Profile::new)
.filter((o) -> !activatedViaProperty.contains(o))
private List<Profile> getOtherActiveProfiles(Set<Profile> activatedViaProperty) {
return Arrays.stream(this.environment.getActiveProfiles()).map(Profile::new)
.filter((profile) -> !activatedViaProperty.contains(profile))
.collect(Collectors.toList());
this.profiles.addAll(otherActiveProfiles);
}
void addActiveProfiles(Set<Profile> profiles) {
if (this.activatedProfiles || profiles.isEmpty()) {
if (profiles.isEmpty()) {
return;
}
addProfiles(profiles);
if (this.activatedProfiles) {
this.logger.debug("Profiles already activated, '" + profiles
+ "' will not be applied");
return;
}
this.profiles.addAll(profiles);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Activated activeProfiles "
+ StringUtils.collectionToCommaDelimitedString(profiles));
@ -394,13 +398,6 @@ public class ConfigFileApplicationListener
removeUnprocessedDefaultProfiles();
}
void addProfiles(Set<Profile> profiles) {
for (Profile profile : profiles) {
this.profiles.add(profile);
addProfileToEnvironment(profile.getName());
}
}
private void removeUnprocessedDefaultProfiles() {
this.profiles.removeIf(
(profile) -> (profile != null && profile.isDefaultProfile()));
@ -526,7 +523,7 @@ public class ConfigFileApplicationListener
for (Document document : documents) {
if (filter.match(document)) {
addActiveProfiles(document.getActiveProfiles());
addProfiles(document.getIncludeProfiles());
addIncludedProfiles(document.getIncludeProfiles());
loaded.add(document);
}
}
@ -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,
Resource resource) throws IOException {
DocumentsCacheKey cacheKey = new DocumentsCacheKey(loader, resource);

@ -94,7 +94,7 @@ public class ConfigFileApplicationListenerYamlProfileNegationTests {
application.setWebApplicationType(WebApplicationType.NONE);
String configName = "--spring.config.name=cascadingprofiles";
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-b")).isNull();
assertThat(this.context.getEnvironment().getProperty("not-c")).isNull();

@ -12,6 +12,7 @@ spring:
include:
- C
- E
version: A
---
spring.profiles: B
@ -21,6 +22,19 @@ spring:
include:
- D
- E
version: B
---
spring.profiles: C
version: C
---
spring.profiles: D
version: D
---
spring.profiles: E

Loading…
Cancel
Save