Fixes profile ordering of remote vs local.
Previously a local profiles specific file would have more priority than a remote profile specific file. Using a new ConfigData Option, this is now fixed. Fixes gh-1795
This commit is contained in:
@@ -19,6 +19,7 @@ package org.springframework.cloud.config.client;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -28,6 +29,7 @@ import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.context.config.ConfigData;
|
||||
import org.springframework.boot.context.config.ConfigData.Option;
|
||||
import org.springframework.boot.context.config.ConfigData.Options;
|
||||
import org.springframework.boot.context.config.ConfigDataLoader;
|
||||
import org.springframework.boot.context.config.ConfigDataLoaderContext;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
@@ -62,6 +64,8 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
|
||||
*/
|
||||
public static final String CONFIG_CLIENT_PROPERTYSOURCE_NAME = "configClient";
|
||||
|
||||
private static final EnumSet<Option> ALL_OPTIONS = EnumSet.allOf(Option.class);
|
||||
|
||||
protected final Log logger;
|
||||
|
||||
public ConfigServerConfigDataLoader(Log logger) {
|
||||
@@ -91,7 +95,7 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
|
||||
|
||||
public ConfigData doLoad(ConfigDataLoaderContext context, ConfigServerConfigDataResource resource) {
|
||||
ConfigClientProperties properties = resource.getProperties();
|
||||
List<PropertySource<?>> composite = new ArrayList<>();
|
||||
List<PropertySource<?>> propertySources = new ArrayList<>();
|
||||
Exception error = null;
|
||||
String errorBody = null;
|
||||
try {
|
||||
@@ -113,7 +117,7 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = translateOrigins(source.getName(),
|
||||
(Map<String, Object>) source.getSource());
|
||||
composite.add(0,
|
||||
propertySources.add(0,
|
||||
new OriginTrackedMapPropertySource("configserver:" + source.getName(), map));
|
||||
}
|
||||
}
|
||||
@@ -127,17 +131,31 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
|
||||
}
|
||||
// the existence of this property source confirms a successful
|
||||
// response from config server
|
||||
composite.add(0, new MapPropertySource(CONFIG_CLIENT_PROPERTYSOURCE_NAME, map));
|
||||
try {
|
||||
return new ConfigData(composite, Option.IGNORE_IMPORTS, Option.IGNORE_PROFILES);
|
||||
propertySources.add(0, new MapPropertySource(CONFIG_CLIENT_PROPERTYSOURCE_NAME, map));
|
||||
if (ALL_OPTIONS.size() == 1) {
|
||||
// boot 2.4.2 and prior
|
||||
return new ConfigData(propertySources);
|
||||
}
|
||||
catch (NoSuchFieldError e) {
|
||||
// IGNORE_PROFILES was added in boot 2.4.3, for backwards
|
||||
// compatibility
|
||||
// IGNORE_IMPORTS alone causes NPE prior to 2.4.3
|
||||
// this will still throw an error if spring.profiles.include in
|
||||
// remote config
|
||||
return new ConfigData(composite);
|
||||
else if (ALL_OPTIONS.size() == 2) {
|
||||
// boot 2.4.3 and 2.4.4
|
||||
return new ConfigData(propertySources, Option.IGNORE_IMPORTS, Option.IGNORE_PROFILES);
|
||||
}
|
||||
else if (ALL_OPTIONS.size() > 2) {
|
||||
// boot 2.4.5+
|
||||
return new ConfigData(propertySources, propertySource -> {
|
||||
String propertySourceName = propertySource.getName();
|
||||
List<Option> options = new ArrayList<>();
|
||||
options.add(Option.IGNORE_IMPORTS);
|
||||
options.add(Option.IGNORE_PROFILES);
|
||||
for (String profile : resource.getAcceptedProfiles()) {
|
||||
// TODO: switch to match
|
||||
if (propertySourceName.contains("-" + profile + ".")) {
|
||||
// TODO: switch to Options.with() when implemented
|
||||
options.add(Option.PROFILE_SPECIFIC);
|
||||
}
|
||||
}
|
||||
return Options.of(options.toArray(new Option[0]));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,12 +47,15 @@ public class ConfigServerConfigDataResource extends ConfigDataResource {
|
||||
}
|
||||
|
||||
public String getProfiles() {
|
||||
List<String> accepted = profiles.getAccepted();
|
||||
if (StringUtils.hasText(properties.getProfile())
|
||||
&& !properties.getProfile().equals(ConfigClientProperties.DEFAULT_PROFILE)) {
|
||||
return properties.getProfile();
|
||||
}
|
||||
return StringUtils.collectionToCommaDelimitedString(accepted);
|
||||
return StringUtils.collectionToCommaDelimitedString(getAcceptedProfiles());
|
||||
}
|
||||
|
||||
List<String> getAcceptedProfiles() {
|
||||
return this.profiles.getAccepted();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.config.ConfigData;
|
||||
import org.springframework.boot.context.config.ConfigData.Option;
|
||||
import org.springframework.boot.context.config.ConfigData.Options;
|
||||
import org.springframework.boot.context.properties.bind.BindContext;
|
||||
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
@@ -37,6 +38,7 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyN
|
||||
import org.springframework.cloud.config.client.ConfigServerBootstrapper.LoaderInterceptor;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -110,9 +112,14 @@ public class ConfigServerConfigDataCustomizationIntegrationTests {
|
||||
hasBinder = context.getBinder() != null;
|
||||
ConfigData configData = context.getInvocation().apply(context.getLoaderContext(), context.getResource());
|
||||
assertThat(configData).as("ConfigData was null for location %s", context.getResource()).isNotNull();
|
||||
assertThat(configData.getOptions()).as("ConfigData.options was null for location %s", context.getResource())
|
||||
.isNotNull();
|
||||
assertThat(configData.getOptions()).contains(Option.IGNORE_IMPORTS, Option.IGNORE_PROFILES);
|
||||
assertThat(configData.getPropertySources()).hasSize(1);
|
||||
PropertySource<?> propertySource = configData.getPropertySources().iterator().next();
|
||||
Options options = configData.getOptions(propertySource);
|
||||
assertThat(options).as("ConfigData.options was null for location %s property source %s",
|
||||
context.getResource(), propertySource.getName()).isNotNull();
|
||||
assertThat(options.contains(Option.IGNORE_IMPORTS)).isTrue();
|
||||
assertThat(options.contains(Option.IGNORE_PROFILES)).isTrue();
|
||||
assertThat(options.contains(Option.PROFILE_SPECIFIC)).isFalse();
|
||||
return configData;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user