Skip to content

Commit 8f42007

Browse files
committed
Improve the structure of the response from the env endpoint
Closes gh-9864
1 parent 28b7ec3 commit 8f42007

File tree

2 files changed

+203
-119
lines changed

2 files changed

+203
-119
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpoint.java

Lines changed: 106 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,17 @@
1616

1717
package org.springframework.boot.actuate.endpoint;
1818

19+
import java.util.ArrayList;
20+
import java.util.Arrays;
1921
import java.util.LinkedHashMap;
22+
import java.util.List;
2023
import java.util.Map;
21-
import java.util.Map.Entry;
2224

25+
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint.EnvironmentDescriptor;
26+
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor;
27+
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor.PropertyValueDescriptor;
2328
import org.springframework.boot.context.properties.ConfigurationProperties;
29+
import org.springframework.boot.origin.OriginLookup;
2430
import org.springframework.core.env.CompositePropertySource;
2531
import org.springframework.core.env.ConfigurableEnvironment;
2632
import org.springframework.core.env.EnumerablePropertySource;
@@ -41,7 +47,7 @@
4147
* @author Madhura Bhave
4248
*/
4349
@ConfigurationProperties(prefix = "endpoints.env")
44-
public class EnvironmentEndpoint extends AbstractEndpoint<Map<String, Object>> {
50+
public class EnvironmentEndpoint extends AbstractEndpoint<EnvironmentDescriptor> {
4551

4652
private final Sanitizer sanitizer = new Sanitizer();
4753

@@ -57,28 +63,35 @@ public void setKeysToSanitize(String... keysToSanitize) {
5763
}
5864

5965
@Override
60-
public Map<String, Object> invoke() {
61-
Map<String, Object> result = new LinkedHashMap<>();
62-
result.put("profiles", getEnvironment().getActiveProfiles());
66+
public EnvironmentDescriptor invoke() {
6367
PropertyResolver resolver = getResolver();
64-
for (Entry<String, PropertySource<?>> entry : getPropertySourcesAsMap()
65-
.entrySet()) {
66-
PropertySource<?> source = entry.getValue();
67-
String sourceName = entry.getKey();
68+
List<PropertySourceDescriptor> propertySources = new ArrayList<PropertySourceDescriptor>();
69+
getPropertySourcesAsMap().forEach((sourceName, source) -> {
6870
if (source instanceof EnumerablePropertySource) {
69-
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
70-
Map<String, Object> properties = new LinkedHashMap<>();
71-
for (String name : enumerable.getPropertyNames()) {
72-
Object resolved = resolver.getProperty(name, Object.class);
73-
properties.put(name, sanitize(name, resolved));
74-
}
75-
properties = postProcessSourceProperties(sourceName, properties);
76-
if (properties != null) {
77-
result.put(sourceName, properties);
78-
}
71+
propertySources.add(describeSource(sourceName,
72+
(EnumerablePropertySource<?>) source, resolver));
7973
}
74+
});
75+
return new EnvironmentDescriptor(
76+
Arrays.asList(getEnvironment().getActiveProfiles()), propertySources);
77+
}
78+
79+
private PropertySourceDescriptor describeSource(String sourceName,
80+
EnumerablePropertySource<?> source, PropertyResolver resolver) {
81+
Map<String, PropertyValueDescriptor> properties = new LinkedHashMap<>();
82+
for (String name : source.getPropertyNames()) {
83+
properties.put(name, describeValueOf(name, source, resolver));
8084
}
81-
return result;
85+
return new PropertySourceDescriptor(sourceName, properties);
86+
}
87+
88+
private PropertyValueDescriptor describeValueOf(String name,
89+
EnumerablePropertySource<?> source, PropertyResolver resolver) {
90+
Object resolved = resolver.getProperty(name, Object.class);
91+
@SuppressWarnings("unchecked")
92+
String origin = (source instanceof OriginLookup)
93+
? ((OriginLookup<Object>) source).getOrigin(name).toString() : null;
94+
return new PropertyValueDescriptor(sanitize(name, resolved), origin);
8295
}
8396

8497
public PropertyResolver getResolver() {
@@ -125,19 +138,6 @@ public Object sanitize(String name, Object object) {
125138
return this.sanitizer.sanitize(name, object);
126139
}
127140

128-
/**
129-
* Apply any post processing to source data before it is added.
130-
* @param sourceName the source name
131-
* @param properties the properties
132-
* @return the post-processed properties or {@code null} if the source should not be
133-
* added
134-
* @since 1.4.0
135-
*/
136-
protected Map<String, Object> postProcessSourceProperties(String sourceName,
137-
Map<String, Object> properties) {
138-
return properties;
139-
}
140-
141141
/**
142142
* {@link PropertySourcesPropertyResolver} that sanitizes sensitive placeholders if
143143
* present.
@@ -166,4 +166,77 @@ protected String getPropertyAsRawString(String key) {
166166

167167
}
168168

169+
/**
170+
* A description of an {@link Environment}.
171+
*/
172+
static final class EnvironmentDescriptor {
173+
174+
private final List<String> activeProfiles;
175+
176+
private final List<PropertySourceDescriptor> propertySources;
177+
178+
private EnvironmentDescriptor(List<String> activeProfiles,
179+
List<PropertySourceDescriptor> propertySources) {
180+
this.activeProfiles = activeProfiles;
181+
this.propertySources = propertySources;
182+
}
183+
184+
public List<String> getActiveProfiles() {
185+
return this.activeProfiles;
186+
}
187+
188+
public List<PropertySourceDescriptor> getPropertySources() {
189+
return this.propertySources;
190+
}
191+
192+
/**
193+
* A description of a {@link PropertySource}.
194+
*/
195+
static final class PropertySourceDescriptor {
196+
197+
private final String name;
198+
199+
private final Map<String, PropertyValueDescriptor> properties;
200+
201+
private PropertySourceDescriptor(String name,
202+
Map<String, PropertyValueDescriptor> properties) {
203+
this.name = name;
204+
this.properties = properties;
205+
}
206+
207+
public String getName() {
208+
return this.name;
209+
}
210+
211+
public Map<String, PropertyValueDescriptor> getProperties() {
212+
return this.properties;
213+
}
214+
215+
/**
216+
* A description of a property's value, including its origin if available.
217+
*/
218+
static final class PropertyValueDescriptor {
219+
220+
private final Object value;
221+
222+
private final String origin;
223+
224+
private PropertyValueDescriptor(Object value, String origin) {
225+
this.value = value;
226+
this.origin = origin;
227+
}
228+
229+
public Object getValue() {
230+
return this.value;
231+
}
232+
233+
public String getOrigin() {
234+
return this.origin;
235+
}
236+
237+
}
238+
239+
}
240+
}
241+
169242
}

0 commit comments

Comments
 (0)