Use boot config data api to determine resource and location.

Previously the resource name and location needed to be parsed. This change updates NativeEnvironmentRepository to pass a ConfigDataEnvironmentUpdateListener to ConfigDataEnvironmentPostProcessor.applyTo() and match PropertySources to location and resource. PassthruEnvironmentRepository is updated to attach the original PropertySource to use later in the clean() method to retrieve the location and resource avoiding parsing.

Fixes gh-1875
This commit is contained in:
spencergibb
2021-05-05 14:12:06 -04:00
parent 9c695648be
commit be708efc18
4 changed files with 76 additions and 11 deletions

View File

@@ -147,6 +147,10 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
List<Option> options = new ArrayList<>();
options.add(Option.IGNORE_IMPORTS);
options.add(Option.IGNORE_PROFILES);
// TODO: the profile is now available on the backend
// in a future minor, add the profile associated with a
// PropertySource see
// https://github.com/spring-cloud/spring-cloud-config/issues/1874
for (String profile : resource.getAcceptedProfiles()) {
// TODO: switch to match
if (propertySourceName.contains("-" + profile + ".")) {

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.config.environment;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
@@ -34,12 +35,22 @@ public class PropertySource {
private Map<?, ?> source;
private org.springframework.core.env.PropertySource<?> originalPropertySource;
@JsonCreator
public PropertySource(@JsonProperty("name") String name, @JsonProperty("source") Map<?, ?> source) {
this.name = name;
this.source = source;
}
@JsonIgnore
public PropertySource(String name, Map<?, ?> source,
org.springframework.core.env.PropertySource<?> originalPropertySource) {
this.name = name;
this.source = source;
this.originalPropertySource = originalPropertySource;
}
public String getName() {
return this.name;
}
@@ -48,6 +59,11 @@ public class PropertySource {
return this.source;
}
@JsonIgnore
public org.springframework.core.env.PropertySource<?> getOriginalPropertySource() {
return this.originalPropertySource;
}
@Override
public String toString() {
return "PropertySource [name=" + this.name + "]";

View File

@@ -18,6 +18,7 @@ package org.springframework.cloud.config.server.environment;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -28,6 +29,10 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
import org.springframework.boot.context.config.ConfigDataEnvironmentUpdateListener;
import org.springframework.boot.context.config.ConfigDataLocation;
import org.springframework.boot.context.config.ConfigDataResource;
import org.springframework.boot.context.config.StandardConfigDataResource;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.core.NestedExceptionUtils;
@@ -130,11 +135,20 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
try {
ConfigurableEnvironment environment = getEnvironment(config, profile, label);
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Map<org.springframework.core.env.PropertySource<?>, PropertySourceConfigData> propertySourceToConfigData = new HashMap<>();
ConfigDataEnvironmentPostProcessor.applyTo(environment, resourceLoader, null,
StringUtils.commaDelimitedListToStringArray(profile));
StringUtils.commaDelimitedListToSet(profile), new ConfigDataEnvironmentUpdateListener() {
@Override
public void onPropertySourceAdded(org.springframework.core.env.PropertySource<?> propertySource,
ConfigDataLocation location, ConfigDataResource resource) {
propertySourceToConfigData.put(propertySource,
new PropertySourceConfigData(location, resource));
}
});
environment.getPropertySources().remove("config-data-setup");
return clean(new PassthruEnvironmentRepository(environment).findOne(config, profile, label, includeOrigin));
return clean(new PassthruEnvironmentRepository(environment).findOne(config, profile, label, includeOrigin),
propertySourceToConfigData);
}
catch (Exception e) {
String msg = String.format("Could not construct context for config=%s profile=%s label=%s includeOrigin=%b",
@@ -217,20 +231,37 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
return environment;
}
protected Environment clean(Environment value) {
Environment result = new Environment(value.getName(), value.getProfiles(), value.getLabel(), this.version,
value.getState());
for (PropertySource source : value.getPropertySources()) {
protected Environment clean(Environment env) {
return clean(env, Collections.emptyMap());
}
protected Environment clean(Environment env,
Map<org.springframework.core.env.PropertySource<?>, PropertySourceConfigData> propertySourceToConfigData) {
Environment result = new Environment(env.getName(), env.getProfiles(), env.getLabel(), this.version,
env.getState());
for (PropertySource source : env.getPropertySources()) {
String originalName = source.getName();
String name = originalName;
if (this.environment.getPropertySources().contains(name)) {
continue;
}
Matcher matcher = RESOURCE_PATTERN.matcher(name);
String location = null;
if (matcher.find()) {
name = matcher.group(1);
location = matcher.group(2);
PropertySourceConfigData configData = propertySourceToConfigData.get(source.getOriginalPropertySource());
// try and get information directly from ConfigData
if (configData != null && configData.resource instanceof StandardConfigDataResource) {
StandardConfigDataResource configDataResource = (StandardConfigDataResource) configData.resource;
// use StandardConfigDataResource as that format is expected still
name = configDataResource.toString();
location = configData.location.toString();
}
else {
// if not, try and parse
Matcher matcher = RESOURCE_PATTERN.matcher(name);
if (matcher.find()) {
name = matcher.group(1);
location = matcher.group(2);
}
}
// TODO: needed anymore?
name = name.replace("applicationConfig: [", "");
@@ -332,4 +363,17 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
this.order = order;
}
private final class PropertySourceConfigData {
private final ConfigDataLocation location;
private final ConfigDataResource resource;
private PropertySourceConfigData(ConfigDataLocation location, ConfigDataResource resource) {
this.location = location;
this.resource = resource;
}
}
}

View File

@@ -74,13 +74,14 @@ public class PassthruEnvironmentRepository implements EnvironmentRepository {
for (org.springframework.core.env.PropertySource<?> source : this.environment.getPropertySources()) {
String name = source.getName();
if (!this.standardSources.contains(name) && source instanceof MapPropertySource) {
result.add(new PropertySource(name, getMap(source, includeOrigin)));
result.add(new PropertySource(name, getMap(source, includeOrigin), source));
}
}
return result;
}
@SuppressWarnings("unchecked")
private Map<?, ?> getMap(org.springframework.core.env.PropertySource<?> source, boolean includeOrigin) {
Map<Object, Object> map = new LinkedHashMap<>();
Map<?, ?> input = (Map<?, ?>) source.getSource();