From be708efc18b2d503f9f27b3d96cbc668f938aaaa Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 5 May 2021 14:12:06 -0400 Subject: [PATCH] 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 --- .../client/ConfigServerConfigDataLoader.java | 4 ++ .../config/environment/PropertySource.java | 16 +++++ .../NativeEnvironmentRepository.java | 64 ++++++++++++++++--- .../PassthruEnvironmentRepository.java | 3 +- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java index 3d69ab78..0c2e48dc 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java @@ -147,6 +147,10 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader 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 + ".")) { diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/environment/PropertySource.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/environment/PropertySource.java index dfd0680c..ea9012c6 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/environment/PropertySource.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/environment/PropertySource.java @@ -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 + "]"; diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java index 2ae00c7b..5f05761c 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java @@ -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, 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, 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; + } + + } + } diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/PassthruEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/PassthruEnvironmentRepository.java index 2ab63e5f..00ff3bcf 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/PassthruEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/PassthruEnvironmentRepository.java @@ -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 map = new LinkedHashMap<>(); Map input = (Map) source.getSource();