Improve output of `/application/env/{propertyName}`

This commit changes the output of a single property to mention the
actual value in the environment as well as the property source that
contributed to the value.

Closes gh-10178
pull/9737/head
Stephane Nicoll 7 years ago
parent 5d05347e61
commit c2c6f49cbc

@ -22,8 +22,8 @@ import org.junit.Test;
import org.springframework.boot.actuate.env.EnvironmentEndpoint;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor.PropertyValueDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.PropertySourceDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.PropertyValueDescriptor;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

@ -25,14 +25,15 @@ import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.boot.actuate.endpoint.Sanitizer;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor.PropertyValueDescriptor;
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.origin.OriginLookup;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@ -54,6 +55,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
* @author Phillip Webb
* @author Christian Dupuis
* @author Madhura Bhave
* @author Stephane Nicoll
* @since 2.0.0
*/
@Endpoint(id = "env")
@ -80,8 +82,8 @@ public class EnvironmentEndpoint {
}
@ReadOperation
public EnvironmentDescriptor environmentEntry(@Selector String toMatch) {
return getEnvironmentDescriptor(toMatch::equals);
public EnvironmentEntryDescriptor environmentEntry(@Selector String toMatch) {
return getEnvironmentEntryDescriptor(toMatch);
}
private EnvironmentDescriptor getEnvironmentDescriptor(
@ -99,6 +101,46 @@ public class EnvironmentEndpoint {
Arrays.asList(this.environment.getActiveProfiles()), propertySources);
}
private EnvironmentEntryDescriptor getEnvironmentEntryDescriptor(
String propertyName) {
Map<String, PropertyValueDescriptor> descriptors = getPropertySourceDescriptors(
propertyName);
PropertySummaryDescriptor summary = getPropertySummaryDescriptor(descriptors);
return new EnvironmentEntryDescriptor(summary,
Arrays.asList(this.environment.getActiveProfiles()),
toPropertySourceDescriptors(descriptors));
}
private List<PropertySourceEntryDescriptor> toPropertySourceDescriptors(
Map<String, PropertyValueDescriptor> descriptors) {
List<PropertySourceEntryDescriptor> result = new ArrayList<>();
for (Map.Entry<String, PropertyValueDescriptor> entry : descriptors.entrySet()) {
result.add(new PropertySourceEntryDescriptor(entry.getKey(), entry.getValue()));
}
return result;
}
private PropertySummaryDescriptor getPropertySummaryDescriptor(
Map<String, PropertyValueDescriptor> descriptors) {
for (Map.Entry<String, PropertyValueDescriptor> entry : descriptors.entrySet()) {
if (entry.getValue() != null) {
return new PropertySummaryDescriptor(entry.getKey(),
entry.getValue().getValue());
}
}
return null;
}
private Map<String, PropertyValueDescriptor> getPropertySourceDescriptors(
String propertyName) {
Map<String, PropertyValueDescriptor> propertySources = new LinkedHashMap<>();
PlaceholdersResolver resolver = getResolver();
getPropertySourcesAsMap().forEach((sourceName, source) ->
propertySources.put(sourceName, source.containsProperty(propertyName) ?
describeValueOf(propertyName, source, resolver) : null));
return propertySources;
}
private PropertySourceDescriptor describeSource(String sourceName,
EnumerablePropertySource<?> source, PlaceholdersResolver resolver,
Predicate<String> namePredicate) {
@ -109,7 +151,7 @@ public class EnvironmentEndpoint {
}
private PropertyValueDescriptor describeValueOf(String name,
EnumerablePropertySource<?> source, PlaceholdersResolver resolver) {
PropertySource<?> source, PlaceholdersResolver resolver) {
Object resolved = resolver.resolvePlaceholders(source.getProperty(name));
@SuppressWarnings("unchecked")
String origin = (source instanceof OriginLookup)
@ -125,7 +167,9 @@ public class EnvironmentEndpoint {
private Map<String, PropertySource<?>> getPropertySourcesAsMap() {
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
for (PropertySource<?> source : getPropertySources()) {
extract("", map, source);
if (!ConfigurationPropertySources.isMainConfigurationPropertySource(source)) {
extract("", map, source);
}
}
return map;
}
@ -208,54 +252,141 @@ public class EnvironmentEndpoint {
return this.propertySources;
}
/**
* A description of a {@link PropertySource}.
*/
public static final class PropertySourceDescriptor {
}
private final String name;
/**
* A description of an entry of the {@link Environment}.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class EnvironmentEntryDescriptor {
private final Map<String, PropertyValueDescriptor> properties;
private final PropertySummaryDescriptor property;
private PropertySourceDescriptor(String name,
Map<String, PropertyValueDescriptor> properties) {
this.name = name;
this.properties = properties;
}
private final List<String> activeProfiles;
public String getName() {
return this.name;
}
private final List<PropertySourceEntryDescriptor> propertySources;
public Map<String, PropertyValueDescriptor> getProperties() {
return this.properties;
}
private EnvironmentEntryDescriptor(PropertySummaryDescriptor property,
List<String> activeProfiles,
List<PropertySourceEntryDescriptor> propertySources) {
this.property = property;
this.activeProfiles = activeProfiles;
this.propertySources = propertySources;
}
/**
* A description of a property's value, including its origin if available.
*/
public static final class PropertyValueDescriptor {
public PropertySummaryDescriptor getProperty() {
return this.property;
}
private final Object value;
public List<String> getActiveProfiles() {
return this.activeProfiles;
}
private final String origin;
public List<PropertySourceEntryDescriptor> getPropertySources() {
return this.propertySources;
}
private PropertyValueDescriptor(Object value, String origin) {
this.value = value;
this.origin = origin;
}
}
public Object getValue() {
return this.value;
}
/**
* A summary of a particular entry of the {@link Environment}.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class PropertySummaryDescriptor {
public String getOrigin() {
return this.origin;
}
private final String source;
}
private final Object value;
public PropertySummaryDescriptor(String source, Object value) {
this.source = source;
this.value = value;
}
public String getSource() {
return this.source;
}
public Object getValue() {
return this.value;
}
}
/**
* A description of a particular entry of {@link PropertySource}.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class PropertySourceEntryDescriptor {
private final String name;
private final PropertyValueDescriptor property;
private PropertySourceEntryDescriptor(String name,
PropertyValueDescriptor property) {
this.name = name;
this.property = property;
}
public String getName() {
return this.name;
}
public PropertyValueDescriptor getProperty() {
return this.property;
}
}
/**
* A description of a {@link PropertySource}.
*/
public static final class PropertySourceDescriptor {
private final String name;
private final Map<String, PropertyValueDescriptor> properties;
private PropertySourceDescriptor(String name,
Map<String, PropertyValueDescriptor> properties) {
this.name = name;
this.properties = properties;
}
public String getName() {
return this.name;
}
public Map<String, PropertyValueDescriptor> getProperties() {
return this.properties;
}
}
/**
* A description of a property's value, including its origin if available.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public static final class PropertyValueDescriptor {
private final Object value;
private final String origin;
private PropertyValueDescriptor(Object value, String origin) {
this.value = value;
this.origin = origin;
}
public Object getValue() {
return this.value;
}
public String getOrigin() {
return this.origin;
}
}
/**

@ -17,23 +17,25 @@
package org.springframework.boot.actuate.env;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor.PropertyValueDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentEntryDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.PropertySourceDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.PropertySourceEntryDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.PropertyValueDescriptor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.StandardEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
@ -57,184 +59,243 @@ public class EnvironmentEndpointTests {
@Test
public void basicResponse() {
EnvironmentDescriptor env = new EnvironmentEndpoint(new StandardEnvironment())
ConfigurableEnvironment environment = emptyEnvironment();
environment.getPropertySources().addLast(
singleKeyPropertySource("one", "my.key", "first"));
environment.getPropertySources().addLast(
singleKeyPropertySource("two", "my.key", "second"));
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
assertThat(env.getActiveProfiles()).isEmpty();
assertThat(env.getPropertySources()).hasSize(2);
assertThat(descriptor.getActiveProfiles()).isEmpty();
Map<String, PropertySourceDescriptor> sources = propertySources(descriptor);
assertThat(sources.keySet()).containsExactly("one", "two");
assertThat(sources.get("one").getProperties()).containsOnlyKeys("my.key");
assertThat(sources.get("two").getProperties()).containsOnlyKeys("my.key");
}
@Test
public void compositeSourceIsHandledCorrectly() {
StandardEnvironment environment = new StandardEnvironment();
ConfigurableEnvironment environment = emptyEnvironment();
CompositePropertySource source = new CompositePropertySource("composite");
source.addPropertySource(
new MapPropertySource("one", Collections.singletonMap("foo", "bar")));
source.addPropertySource(
new MapPropertySource("two", Collections.singletonMap("foo", "spam")));
environment.getPropertySources().addFirst(source);
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
assertThat(getSource("composite:one", env).getProperties().get("foo").getValue())
Map<String, PropertySourceDescriptor> sources = propertySources(descriptor);
assertThat(sources.keySet()).containsExactly("composite:one", "composite:two");
assertThat(sources.get("composite:one").getProperties().get("foo").getValue())
.isEqualTo("bar");
assertThat(getSource("composite:two", env).getProperties().get("foo").getValue())
assertThat(sources.get("composite:two").getProperties().get("foo").getValue())
.isEqualTo("spam");
}
@Test
public void sensitiveKeysHaveTheirValuesSanitized() {
System.setProperty("dbPassword", "123456");
System.setProperty("apiKey", "123456");
System.setProperty("mySecret", "123456");
System.setProperty("myCredentials", "123456");
System.setProperty("VCAP_SERVICES", "123456");
EnvironmentDescriptor env = new EnvironmentEndpoint(new StandardEnvironment())
.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = getSource(
"systemProperties", env).getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo("******");
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo("******");
assertThat(systemProperties.get("mySecret").getValue()).isEqualTo("******");
assertThat(systemProperties.get("myCredentials").getValue()).isEqualTo("******");
assertThat(systemProperties.get("VCAP_SERVICES").getValue()).isEqualTo("******");
clearSystemProperties("dbPassword", "apiKey", "mySecret", "myCredentials",
"VCAP_SERVICES");
TestPropertyValues.of("dbPassword=123456", "apiKey=123456", "mySecret=123456",
"myCredentials=123456", "VCAP_SERVICES=123456"
).applyToSystemProperties(() -> {
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(
new StandardEnvironment()).environment(null);
Map<String, PropertyValueDescriptor> systemProperties = propertySources(
descriptor).get("systemProperties").getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo("******");
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo("******");
assertThat(systemProperties.get("mySecret").getValue()).isEqualTo("******");
assertThat(systemProperties.get("myCredentials").getValue()).isEqualTo("******");
assertThat(systemProperties.get("VCAP_SERVICES").getValue()).isEqualTo("******");
return null;
});
}
@Test
public void sensitiveKeysMatchingCredentialsPatternHaveTheirValuesSanitized() {
System.setProperty("my.services.amqp-free.credentials.uri", "123456");
System.setProperty("credentials.http_api_uri", "123456");
System.setProperty("my.services.cleardb-free.credentials", "123456");
System.setProperty("foo.mycredentials.uri", "123456");
EnvironmentDescriptor env = new EnvironmentEndpoint(new StandardEnvironment())
.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = getSource(
"systemProperties", env).getProperties();
assertThat(
systemProperties.get("my.services.amqp-free.credentials.uri").getValue())
.isEqualTo("******");
assertThat(systemProperties.get("credentials.http_api_uri").getValue())
.isEqualTo("******");
assertThat(
systemProperties.get("my.services.cleardb-free.credentials").getValue())
.isEqualTo("******");
assertThat(systemProperties.get("foo.mycredentials.uri").getValue())
.isEqualTo("******");
clearSystemProperties("my.services.amqp-free.credentials.uri",
"credentials.http_api_uri", "my.services.cleardb-free.credentials",
"foo.mycredentials.uri");
TestPropertyValues.of("my.services.amqp-free.credentials.uri=123456",
"credentials.http_api_uri=123456",
"my.services.cleardb-free.credentials=123456",
"foo.mycredentials.uri=123456").applyToSystemProperties(() -> {
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(
new StandardEnvironment()).environment(null);
Map<String, PropertyValueDescriptor> systemProperties = propertySources(
descriptor).get("systemProperties").getProperties();
assertThat(
systemProperties.get("my.services.amqp-free.credentials.uri").getValue())
.isEqualTo("******");
assertThat(systemProperties.get("credentials.http_api_uri").getValue())
.isEqualTo("******");
assertThat(
systemProperties.get("my.services.cleardb-free.credentials").getValue())
.isEqualTo("******");
assertThat(systemProperties.get("foo.mycredentials.uri").getValue())
.isEqualTo("******");
return null;
});
}
@Test
public void sensitiveKeysMatchingCustomNameHaveTheirValuesSanitized() {
System.setProperty("dbPassword", "123456");
System.setProperty("apiKey", "123456");
EnvironmentEndpoint endpoint = new EnvironmentEndpoint(new StandardEnvironment());
endpoint.setKeysToSanitize("key");
EnvironmentDescriptor env = endpoint.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = getSource(
"systemProperties", env).getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo("123456");
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo("******");
clearSystemProperties("dbPassword", "apiKey");
TestPropertyValues.of("dbPassword=123456",
"apiKey=123456").applyToSystemProperties(() -> {
EnvironmentEndpoint endpoint = new EnvironmentEndpoint(new StandardEnvironment());
endpoint.setKeysToSanitize("key");
EnvironmentDescriptor descriptor = endpoint.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = propertySources(
descriptor).get("systemProperties").getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo("123456");
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo("******");
return null;
});
}
@Test
public void sensitiveKeysMatchingCustomPatternHaveTheirValuesSanitized() {
System.setProperty("dbPassword", "123456");
System.setProperty("apiKey", "123456");
EnvironmentEndpoint endpoint = new EnvironmentEndpoint(new StandardEnvironment());
endpoint.setKeysToSanitize(".*pass.*");
EnvironmentDescriptor env = endpoint.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = getSource(
"systemProperties", env).getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo("******");
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo("123456");
clearSystemProperties("dbPassword", "apiKey");
TestPropertyValues.of("dbPassword=123456",
"apiKey=123456").applyToSystemProperties(() -> {
EnvironmentEndpoint endpoint = new EnvironmentEndpoint(new StandardEnvironment());
endpoint.setKeysToSanitize(".*pass.*");
EnvironmentDescriptor descriptor = endpoint.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = propertySources(
descriptor).get("systemProperties").getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo("******");
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo("123456");
return null;
});
}
@Test
public void propertyWithPlaceholderResolved() {
StandardEnvironment environment = new StandardEnvironment();
ConfigurableEnvironment environment = emptyEnvironment();
TestPropertyValues.of("my.foo: ${bar.blah}", "bar.blah: hello")
.applyTo(environment);
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
assertThat(getSource("test", env).getProperties().get("my.foo").getValue())
.isEqualTo("hello");
assertThat(propertySources(descriptor).get("test").getProperties().get("my.foo")
.getValue()).isEqualTo("hello");
}
@Test
public void propertyWithPlaceholderNotResolved() {
StandardEnvironment environment = new StandardEnvironment();
ConfigurableEnvironment environment = emptyEnvironment();
TestPropertyValues.of("my.foo: ${bar.blah}").applyTo(environment);
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
assertThat(getSource("test", env).getProperties().get("my.foo").getValue())
.isEqualTo("${bar.blah}");
assertThat(propertySources(descriptor).get("test").getProperties().get("my.foo")
.getValue()).isEqualTo("${bar.blah}");
}
@Test
public void propertyWithSensitivePlaceholderResolved() {
StandardEnvironment environment = new StandardEnvironment();
ConfigurableEnvironment environment = emptyEnvironment();
TestPropertyValues
.of("my.foo: http://${bar.password}://hello", "bar.password: hello")
.applyTo(environment);
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
assertThat(getSource("test", env).getProperties().get("my.foo").getValue())
.isEqualTo("http://******://hello");
assertThat(propertySources(descriptor).get("test").getProperties().get("my.foo")
.getValue()).isEqualTo("http://******://hello");
}
@Test
public void propertyWithSensitivePlaceholderNotResolved() {
StandardEnvironment environment = new StandardEnvironment();
ConfigurableEnvironment environment = emptyEnvironment();
TestPropertyValues.of("my.foo: http://${bar.password}://hello")
.applyTo(environment);
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
assertThat(getSource("test", env).getProperties().get("my.foo").getValue())
.isEqualTo("http://${bar.password}://hello");
assertThat(propertySources(descriptor).get("test").getProperties().get("my.foo")
.getValue()).isEqualTo("http://${bar.password}://hello");
}
@Test
@SuppressWarnings("unchecked")
public void propertyWithTypeOtherThanStringShouldNotFail() {
StandardEnvironment environment = new StandardEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
Map<String, Object> source = new HashMap<>();
source.put("foo", Collections.singletonMap("bar", "baz"));
propertySources.addFirst(new MapPropertySource("test", source));
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
ConfigurableEnvironment environment = emptyEnvironment();
environment.getPropertySources().addFirst(singleKeyPropertySource("test", "foo",
Collections.singletonMap("bar", "baz")));
EnvironmentDescriptor descriptor = new EnvironmentEndpoint(environment)
.environment(null);
Map<String, PropertyValueDescriptor> testProperties = getSource("test", env)
.getProperties();
Map<String, String> foo = (Map<String, String>) testProperties.get("foo")
.getValue();
Map<String, String> foo = (Map<String, String>) propertySources(descriptor)
.get("test").getProperties().get("foo").getValue();
assertThat(foo.get("bar")).isEqualTo("baz");
}
@Test
public void propertyEntry() {
TestPropertyValues.of("my.foo=another").applyToSystemProperties(() -> {
StandardEnvironment environment = new StandardEnvironment();
TestPropertyValues.of("my.foo=bar", "my.foo2=bar2").applyTo(environment,
TestPropertyValues.Type.MAP, "test");
EnvironmentEntryDescriptor descriptor = new EnvironmentEndpoint(environment)
.environmentEntry("my.foo");
assertThat(descriptor).isNotNull();
assertThat(descriptor.getProperty()).isNotNull();
assertThat(descriptor.getProperty().getSource()).isEqualTo("test");
assertThat(descriptor.getProperty().getValue()).isEqualTo("bar");
Map<String, PropertySourceEntryDescriptor> sources = propertySources(descriptor);
assertThat(sources.keySet()).containsExactly(
"test", "systemProperties", "systemEnvironment");
assertPropertySourceEntryDescriptor(sources.get("test"), "bar", null);
assertPropertySourceEntryDescriptor(sources.get("systemProperties"), "another", null);
assertPropertySourceEntryDescriptor(sources.get("systemEnvironment"), null, null);
return null;
});
}
@Test
public void propertyEntryNotFound() {
ConfigurableEnvironment environment = emptyEnvironment();
environment.getPropertySources().addFirst(
singleKeyPropertySource("test", "foo", "bar"));
EnvironmentEntryDescriptor descriptor = new EnvironmentEndpoint(environment)
.environmentEntry("does.not.exist");
assertThat(descriptor).isNotNull();
assertThat(descriptor.getProperty()).isNull();
Map<String, PropertySourceEntryDescriptor> sources = propertySources(descriptor);
assertThat(sources.keySet()).containsExactly(
"test");
assertPropertySourceEntryDescriptor(sources.get("test"), null, null);
}
private static ConfigurableEnvironment emptyEnvironment() {
StandardEnvironment environment = new StandardEnvironment();
TestPropertyValues.of("my.foo=bar", "my.foo2=bar2").applyTo(environment);
EnvironmentDescriptor env = new EnvironmentEndpoint(environment)
.environmentEntry("my.foo");
assertThat(env).isNotNull();
assertThat(getSource("test", env).getProperties().get("my.foo").getValue())
.isEqualTo("bar");
environment.getPropertySources().remove(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
environment.getPropertySources().remove(
StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
return environment;
}
private void clearSystemProperties(String... properties) {
for (String property : properties) {
System.clearProperty(property);
}
private MapPropertySource singleKeyPropertySource(String name, String key, Object value) {
return new MapPropertySource(name, Collections.singletonMap(key, value));
}
private PropertySourceDescriptor getSource(String name,
private Map<String, PropertySourceDescriptor> propertySources(
EnvironmentDescriptor descriptor) {
return descriptor.getPropertySources().stream()
.filter((source) -> name.equals(source.getName())).findFirst().get();
Map<String, PropertySourceDescriptor> sources = new LinkedHashMap<>();
descriptor.getPropertySources().forEach(d -> sources.put(d.getName(), d));
return sources;
}
private Map<String, PropertySourceEntryDescriptor> propertySources(
EnvironmentEntryDescriptor descriptor) {
Map<String, PropertySourceEntryDescriptor> sources = new LinkedHashMap<>();
descriptor.getPropertySources().forEach(d -> sources.put(d.getName(), d));
return sources;
}
private void assertPropertySourceEntryDescriptor(PropertySourceEntryDescriptor actual,
Object value, String origin) {
assertThat(actual).isNotNull();
if (value != null) {
assertThat(actual.getProperty().getValue()).isEqualTo(value);
assertThat(actual.getProperty().getOrigin()).isEqualTo(origin);
}
else {
assertThat(actual.getProperty()).isNull();
}
}
@Configuration

@ -53,7 +53,9 @@ public class EnvironmentEndpointWebIntegrationTests {
@Test
public void sub() throws Exception {
client.get().uri("/application/env/foo").exchange().expectStatus().isOk()
.expectBody().jsonPath(forProperty("test", "foo")).isEqualTo("bar");
.expectBody()
.jsonPath("property.source").isEqualTo("test")
.jsonPath("property.value").isEqualTo("bar");
}
@Test
@ -75,8 +77,10 @@ public class EnvironmentEndpointWebIntegrationTests {
context.getEnvironment().getPropertySources()
.addFirst(new MapPropertySource("unresolved-placeholder", map));
client.get().uri("/application/env/my.foo").exchange().expectStatus().isOk()
.expectBody().jsonPath(forProperty("unresolved-placeholder", "my.foo"))
.isEqualTo("${my.bar}");
.expectBody()
.jsonPath("property.value").isEqualTo("${my.bar}")
.jsonPath(forPropertyEntry(
"unresolved-placeholder")).isEqualTo("${my.bar}");
}
@Test
@ -87,8 +91,9 @@ public class EnvironmentEndpointWebIntegrationTests {
context.getEnvironment().getPropertySources()
.addFirst(new MapPropertySource("placeholder", map));
client.get().uri("/application/env/my.foo").exchange().expectStatus().isOk()
.expectBody().jsonPath(forProperty("placeholder", "my.foo"))
.isEqualTo("******");
.expectBody()
.jsonPath("property.value").isEqualTo("******")
.jsonPath(forPropertyEntry("placeholder")).isEqualTo("******");
}
@Test
@ -123,6 +128,10 @@ public class EnvironmentEndpointWebIntegrationTests {
+ "'].value";
}
private String forPropertyEntry(String source) {
return "propertySources[?(@.name=='" + source + "')].property.value";
}
@Configuration
static class TestConfiguration {

@ -45,6 +45,18 @@ public final class ConfigurationPropertySources {
private ConfigurationPropertySources() {
}
/**
* Determines if the specific {@link PropertySource} is the
* {@link ConfigurationPropertySource} that was {@link #attach(Environment) attached}
* to the {@link Environment}.
* @param propertySource the property source to test
* @return {@code true} if this is the attached {@link ConfigurationPropertySource}
*/
public static boolean isMainConfigurationPropertySource(
PropertySource<?> propertySource) {
return ATTACHED_PROPERTY_SOURCE_NAME.equals(propertySource.getName());
}
/**
* Attach a {@link ConfigurationPropertySource} support to the specified
* {@link Environment}. Adapts each {@link PropertySource} managed by the environment

Loading…
Cancel
Save