Limit when SystemEnvironment mapping is used

Update `SpringConfigurationPropertySource` so that the
`SystemEnvironmentPropertyMapper` is only used for the "actual" system
environment property source. This allows SystemEnvironmentProperySource
class to be used for other purposes (for example, Spring Cloud uses it
to as an override source providing decryption).

Only property sources named `systemEnvironment` or ending with
`-systemEnvironment` now have the `SystemEnvironmentPropertyMapper`
applied. The `TestPropertyValues` has been retrofitted to name the
source it adds appropriately.

Fixes gh-10840
This commit is contained in:
Phillip Webb 2017-11-06 13:12:25 -08:00
parent e9f31f9c34
commit 06b1b453a6
7 changed files with 86 additions and 13 deletions

View File

@ -57,7 +57,7 @@ public class EnvironmentInfoContributorTests {
@SuppressWarnings("unchecked")
public void propertiesFromEnvironmentShouldBindCorrectly() throws Exception {
TestPropertyValues.of("INFO_ENVIRONMENT_FOO=green").applyTo(this.environment,
Type.SYSTEM);
Type.SYSTEM_ENVIRONMENT);
Info actual = contributeFrom(this.environment);
assertThat(actual.get("environment", Map.class)).containsEntry("foo", "green");
}

View File

@ -34,6 +34,7 @@ import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.env.SystemEnvironmentPropertySource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -98,7 +99,7 @@ public final class TestPropertyValues {
* @param type the type of {@link PropertySource} to be added. See {@link Type}
*/
public void applyTo(ConfigurableEnvironment environment, Type type) {
applyTo(environment, type, "test");
applyTo(environment, type, type.applySuffix("test"));
}
/**
@ -212,23 +213,31 @@ public final class TestPropertyValues {
/**
* Used for {@link SystemEnvironmentPropertySource}.
*/
SYSTEM(SystemEnvironmentPropertySource.class),
SYSTEM_ENVIRONMENT(SystemEnvironmentPropertySource.class,
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME),
/**
* Used for {@link MapPropertySource}.
*/
MAP(MapPropertySource.class);
MAP(MapPropertySource.class, null);
private Class<? extends MapPropertySource> sourceClass;
private final Class<? extends MapPropertySource> sourceClass;
Type(Class<? extends MapPropertySource> sourceClass) {
private final String suffix;
Type(Class<? extends MapPropertySource> sourceClass, String suffix) {
this.sourceClass = sourceClass;
this.suffix = (suffix == null ? null : "-" + suffix);
}
public Class<? extends MapPropertySource> getSourceClass() {
return this.sourceClass;
}
protected String applySuffix(String name) {
return (this.suffix == null ? name : name + "-" + this.suffix);
}
}
/**

View File

@ -54,8 +54,10 @@ public class TestPropertyValuesTests {
@Test
public void applyToSystemPropertySource() throws Exception {
TestPropertyValues.of("FOO_BAR=BAZ").applyTo(this.environment, Type.SYSTEM);
TestPropertyValues.of("FOO_BAR=BAZ").applyTo(this.environment, Type.SYSTEM_ENVIRONMENT);
assertThat(this.environment.getProperty("foo.bar")).isEqualTo("BAZ");
assertThat(this.environment.getPropertySources().contains(
"test-" + StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME));
}
@Test
@ -70,7 +72,7 @@ public class TestPropertyValuesTests {
throws Exception {
TestPropertyValues.of("foo.bar=baz", "hello.world=hi").applyTo(this.environment,
Type.MAP, "other");
TestPropertyValues.of("FOO_BAR=BAZ").applyTo(this.environment, Type.SYSTEM,
TestPropertyValues.of("FOO_BAR=BAZ").applyTo(this.environment, Type.SYSTEM_ENVIRONMENT,
"other");
assertThat(this.environment.getPropertySources().get("other"))
.isInstanceOf(SystemEnvironmentPropertySource.class);

View File

@ -27,6 +27,7 @@ import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.PropertySourceOrigin;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.env.SystemEnvironmentPropertySource;
import org.springframework.util.Assert;
@ -150,12 +151,20 @@ class SpringConfigurationPropertySource implements ConfigurationPropertySource {
}
private static PropertyMapper getPropertyMapper(PropertySource<?> source) {
if (source instanceof SystemEnvironmentPropertySource) {
if (source instanceof SystemEnvironmentPropertySource
&& hasSystemEnvironmentName(source)) {
return SystemEnvironmentPropertyMapper.INSTANCE;
}
return DefaultPropertyMapper.INSTANCE;
}
private static boolean hasSystemEnvironmentName(PropertySource<?> source) {
String name = source.getName();
return StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME.equals(name)
|| name.endsWith("-"
+ StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
}
private static boolean isFullEnumerable(PropertySource<?> source) {
PropertySource<?> rootSource = getRootSource(source);
if (rootSource.getSource() instanceof Map) {

View File

@ -27,6 +27,7 @@ import org.springframework.boot.context.properties.bind.validation.BindValidatio
import org.springframework.boot.context.properties.bind.validation.ValidationErrors;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.env.SystemEnvironmentPropertySource;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.context.support.TestPropertySourceUtils;
@ -192,7 +193,8 @@ public class ConfigurationPropertiesBinderTests {
@Test
public void bindToMapWithSystemProperties() {
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(new SystemEnvironmentPropertySource("system",
propertySources.addLast(new SystemEnvironmentPropertySource(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
Collections.singletonMap("TEST_MAP_FOO_BAR", "baz")));
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
propertySources, null, null);

View File

@ -34,11 +34,10 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class BackCompatibiltyBinderIntegrationTests {
// gh-10873
@Test
public void bindWhenBindingCamelCaseToEnvironmentWithExtractUnderscore()
throws Exception {
// gh-10873
MockEnvironment environment = new MockEnvironment();
SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
@ -49,6 +48,17 @@ public class BackCompatibiltyBinderIntegrationTests {
assertThat(result.getZkNodes()).isEqualTo("foo");
}
@Test
public void bindWhenUsingSystemEnvronmentToOverride() {
MockEnvironment environment = new MockEnvironment();
SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource(
"override", Collections.singletonMap("foo.password", "test"));
environment.getPropertySources().addFirst(propertySource);
PasswordProperties result = Binder.get(environment)
.bind("foo", Bindable.of(PasswordProperties.class)).get();
assertThat(result.getPassword()).isEqualTo("test");
}
public static class ExampleCamelCaseBean {
private String zkNodes;
@ -63,4 +73,17 @@ public class BackCompatibiltyBinderIntegrationTests {
}
protected static class PasswordProperties {
private String password;
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
}

View File

@ -66,7 +66,8 @@ public class SpringConfigurationPropertySourcesTests {
@Test
public void shouldAdaptSystemEnvironmentPropertySource() throws Exception {
MutablePropertySources sources = new MutablePropertySources();
sources.addLast(new SystemEnvironmentPropertySource("system",
sources.addLast(new SystemEnvironmentPropertySource(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
Collections.singletonMap("SERVER_PORT", "1234")));
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
sources).iterator();
@ -76,6 +77,33 @@ public class SpringConfigurationPropertySourcesTests {
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void shouldExtendedAdaptSystemEnvironmentPropertySource() throws Exception {
MutablePropertySources sources = new MutablePropertySources();
sources.addLast(new SystemEnvironmentPropertySource(
"test-" + StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
Collections.singletonMap("SERVER_PORT", "1234")));
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
sources).iterator();
ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
assertThat(iterator.next().getConfigurationProperty(name).getValue())
.isEqualTo("1234");
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void shouldNotAdaptSystemEnvironmentPropertyOverrideSource() throws Exception {
MutablePropertySources sources = new MutablePropertySources();
sources.addLast(new SystemEnvironmentPropertySource("override",
Collections.singletonMap("server.port", "1234")));
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
sources).iterator();
ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
assertThat(iterator.next().getConfigurationProperty(name).getValue())
.isEqualTo("1234");
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void shouldAdaptMultiplePropertySources() throws Exception {
MutablePropertySources sources = new MutablePropertySources();