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
This commit is contained in:
Madhura Bhave
2018-05-15 17:44:40 -07:00
committed by Phillip Webb
parent 60a4d67b13
commit 378c4c9535
3 changed files with 39 additions and 21 deletions

View File

@@ -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);

View File

@@ -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();

View File

@@ -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