Filter properties with a particular prefix
This commit improves the configprops endpoint to allow filtering properties based on a particular prefix See gh-24718pull/25178/head
parent
0f9fb13141
commit
ad7c69a9cd
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.context.properties;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ContextConfigurationProperties;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Selector;
|
||||
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension;
|
||||
|
||||
/**
|
||||
* {@link EndpointWebExtension @EndpointWebExtension} for the
|
||||
* {@link ConfigurationPropertiesReportEndpoint}.
|
||||
*
|
||||
* @author Chris Bono
|
||||
* @since 2.4
|
||||
*/
|
||||
@EndpointWebExtension(endpoint = ConfigurationPropertiesReportEndpoint.class)
|
||||
public class ConfigurationPropertiesReportEndpointWebExtension {
|
||||
|
||||
private final ConfigurationPropertiesReportEndpoint delegate;
|
||||
|
||||
public ConfigurationPropertiesReportEndpointWebExtension(ConfigurationPropertiesReportEndpoint delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public WebEndpointResponse<ApplicationConfigurationProperties> configurationProperties(@Selector String prefix) {
|
||||
ApplicationConfigurationProperties configurationProperties = this.delegate.configurationProperties(prefix);
|
||||
boolean foundMatchingBeans = configurationProperties.getContexts().values().stream()
|
||||
.map(ContextConfigurationProperties::getBeans).anyMatch((beans) -> !beans.isEmpty());
|
||||
return (foundMatchingBeans) ? new WebEndpointResponse<>(configurationProperties, WebEndpointResponse.STATUS_OK)
|
||||
: new WebEndpointResponse<>(WebEndpointResponse.STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.context.properties;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
|
||||
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ContextConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationPropertiesReportEndpoint} when filtering by prefix.
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
class ConfigurationPropertiesReportEndpointFilteringTests {
|
||||
|
||||
@Test
|
||||
void filterByPrefixSingleMatch() {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner().withUserConfiguration(Config.class)
|
||||
.withPropertyValues("foo.primary.name:foo1", "foo.secondary.name:foo2", "only.bar.name:solo1");
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint.configurationProperties("only.bar");
|
||||
assertThat(applicationProperties.getContexts()).containsOnlyKeys(context.getId());
|
||||
ContextConfigurationProperties contextProperties = applicationProperties.getContexts().get(context.getId());
|
||||
assertThat(contextProperties.getBeans().values()).hasSize(1).first().hasFieldOrPropertyWithValue("prefix",
|
||||
"only.bar");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterByPrefixMultipleMatches() {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner().withUserConfiguration(Config.class)
|
||||
.withPropertyValues("foo.primary.name:foo1", "foo.secondary.name:foo2", "only.bar.name:solo1");
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint.configurationProperties("foo.");
|
||||
assertThat(applicationProperties.getContexts()).containsOnlyKeys(context.getId());
|
||||
ContextConfigurationProperties contextProperties = applicationProperties.getContexts().get(context.getId());
|
||||
assertThat(contextProperties.getBeans()).containsOnlyKeys("primaryFoo", "secondaryFoo");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterByPrefixNoMatches() {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner().withUserConfiguration(Config.class)
|
||||
.withPropertyValues("foo.primary.name:foo1", "foo.secondary.name:foo2", "only.bar.name:solo1");
|
||||
contextRunner.run((context) -> {
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ApplicationConfigurationProperties applicationProperties = endpoint.configurationProperties("foo.third");
|
||||
assertThat(applicationProperties.getContexts()).containsOnlyKeys(context.getId());
|
||||
ContextConfigurationProperties contextProperties = applicationProperties.getContexts().get(context.getId());
|
||||
assertThat(contextProperties.getBeans()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(Bar.class)
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
ConfigurationPropertiesReportEndpoint endpoint() {
|
||||
return new ConfigurationPropertiesReportEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "foo.primary")
|
||||
Foo primaryFoo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "foo.secondary")
|
||||
Foo secondaryFoo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String name = "5150";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "only.bar")
|
||||
public static class Bar {
|
||||
|
||||
private String name = "123456";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.context.properties;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ConfigurationPropertiesReportEndpoint} exposed by Jersey,
|
||||
* Spring MVC, and WebFlux.
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
class ConfigurationPropertiesReportEndpointWebIntegrationTests {
|
||||
|
||||
private WebTestClient client;
|
||||
|
||||
@BeforeEach
|
||||
void prepareEnvironment(ConfigurableApplicationContext context, WebTestClient client) {
|
||||
TestPropertyValues.of("com.foo.name=fooz", "com.bar.name=barz").applyTo(context);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@WebEndpointTest
|
||||
void noFilters() {
|
||||
this.client.get().uri("/actuator/configprops").exchange().expectStatus().isOk().expectBody()
|
||||
.jsonPath("$..beans[*]").value(hasSize(greaterThanOrEqualTo(2))).jsonPath("$..beans['fooDotCom']")
|
||||
.exists().jsonPath("$..beans['barDotCom']").exists();
|
||||
}
|
||||
|
||||
@WebEndpointTest
|
||||
void filterByExactPrefix() {
|
||||
this.client.get().uri("/actuator/configprops/com.foo").exchange().expectStatus().isOk().expectBody()
|
||||
.jsonPath("$..beans[*]").value(hasSize(1)).jsonPath("$..beans['fooDotCom']").exists();
|
||||
}
|
||||
|
||||
@WebEndpointTest
|
||||
void filterByGeneralPrefix() {
|
||||
this.client.get().uri("/actuator/configprops/com.").exchange().expectStatus().isOk().expectBody()
|
||||
.jsonPath("$..beans[*]").value(hasSize(2)).jsonPath("$..beans['fooDotCom']").exists()
|
||||
.jsonPath("$..beans['barDotCom']").exists();
|
||||
}
|
||||
|
||||
@WebEndpointTest
|
||||
void filterByNonExistentPrefix() {
|
||||
this.client.get().uri("/actuator/configprops/com.zoo").exchange().expectStatus().isNotFound();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
ConfigurationPropertiesReportEndpoint endpoint() {
|
||||
return new ConfigurationPropertiesReportEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ConfigurationPropertiesReportEndpointWebExtension endpointWebExtension(
|
||||
ConfigurationPropertiesReportEndpoint endpoint) {
|
||||
return new ConfigurationPropertiesReportEndpointWebExtension(endpoint);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "com.foo")
|
||||
Foo fooDotCom() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "com.bar")
|
||||
Bar barDotCom() {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String name = "5150";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Bar {
|
||||
|
||||
private String name = "6160";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue