Configure health on additional path only when health exposed
Prior to this commit, limiting the exposure to a specific technology in `ConditionalOnAvailableEndpoint` would not have any effect because all endpoints would be considered to be available if the app was running on Cloud Foundry. This caused issues in cases where beans were meant to be exposed only if the endpoint was actually exposed. This commit adds CLOUD_FOUNDRY to the `EndpointExposure` enum. This allows `ConditionalOnAvailableEndpoint` to limit by exposure even when the Cloud Foundry platform is active. Fixes gh-29532
This commit is contained in:
parent
8c5a5f81ff
commit
0597c6831e
|
|
@ -54,7 +54,7 @@ public class CachesEndpointAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(CachesEndpoint.class)
|
||||
@ConditionalOnAvailableEndpoint(exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
public CachesEndpointWebExtension cachesEndpointWebExtension(CachesEndpoint cachesEndpoint) {
|
||||
return new CachesEndpointWebExtension(cachesEndpoint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class ConfigurationPropertiesReportEndpointAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(ConfigurationPropertiesReportEndpoint.class)
|
||||
@ConditionalOnAvailableEndpoint(exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
public ConfigurationPropertiesReportEndpointWebExtension configurationPropertiesReportEndpointWebExtension(
|
||||
ConfigurationPropertiesReportEndpoint configurationPropertiesReportEndpoint) {
|
||||
return new ConfigurationPropertiesReportEndpointWebExtension(configurationPropertiesReportEndpoint);
|
||||
|
|
|
|||
|
|
@ -113,9 +113,6 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
|
|||
if (!enablementOutcome.isMatch()) {
|
||||
return enablementOutcome;
|
||||
}
|
||||
if (CloudPlatform.CLOUD_FOUNDRY.isActive(environment)) {
|
||||
return ConditionOutcome.match(message.because("application is running on Cloud Foundry"));
|
||||
}
|
||||
Set<EndpointExposure> exposuresToCheck = getExposuresToCheck(conditionAnnotation);
|
||||
Set<ExposureFilter> exposureFilters = getExposureFilters(environment);
|
||||
for (ExposureFilter exposureFilter : exposureFilters) {
|
||||
|
|
@ -168,6 +165,9 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
|
|||
if (environment.getProperty(JMX_ENABLED_KEY, Boolean.class, false)) {
|
||||
exposureFilters.add(new ExposureFilter(environment, EndpointExposure.JMX));
|
||||
}
|
||||
if (CloudPlatform.CLOUD_FOUNDRY.isActive(environment)) {
|
||||
exposureFilters.add(new ExposureFilter(environment, EndpointExposure.CLOUD_FOUNDRY));
|
||||
}
|
||||
exposureFilters.add(new ExposureFilter(environment, EndpointExposure.WEB));
|
||||
exposureFiltersCache.put(environment, exposureFilters);
|
||||
}
|
||||
|
|
@ -181,9 +181,16 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
|
|||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private ExposureFilter(Environment environment, EndpointExposure exposure) {
|
||||
super((Class) ExposableEndpoint.class, environment,
|
||||
"management.endpoints." + exposure.name().toLowerCase() + ".exposure",
|
||||
exposure.getDefaultIncludes());
|
||||
"management.endpoints." + getCanonicalName(exposure) + ".exposure", exposure.getDefaultIncludes());
|
||||
this.exposure = exposure;
|
||||
|
||||
}
|
||||
|
||||
private static String getCanonicalName(EndpointExposure exposure) {
|
||||
if (EndpointExposure.CLOUD_FOUNDRY.equals(exposure)) {
|
||||
return "cloud-foundry";
|
||||
}
|
||||
return exposure.name().toLowerCase();
|
||||
}
|
||||
|
||||
EndpointExposure getExposure() {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,13 @@ public enum EndpointExposure {
|
|||
/**
|
||||
* Exposed via a web endpoint.
|
||||
*/
|
||||
WEB("health");
|
||||
WEB("health"),
|
||||
|
||||
/**
|
||||
* Exposed on Cloud Foundry via `/cloudfoundryapplication`.
|
||||
* @since 2.6.4
|
||||
*/
|
||||
CLOUD_FOUNDRY("*");
|
||||
|
||||
private final String[] defaultIncludes;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class EnvironmentEndpointAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(EnvironmentEndpoint.class)
|
||||
@ConditionalOnAvailableEndpoint(exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
public EnvironmentEndpointWebExtension environmentEndpointWebExtension(EnvironmentEndpoint environmentEndpoint) {
|
||||
return new EnvironmentEndpointWebExtension(environmentEndpoint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ import org.springframework.context.annotation.Configuration;
|
|||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class,
|
||||
exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
class HealthEndpointReactiveWebExtensionConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
@ -57,6 +58,7 @@ class HealthEndpointReactiveWebExtensionConfiguration {
|
|||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB)
|
||||
static class WebFluxAdditionalHealthEndpointPathsConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ import org.springframework.web.servlet.DispatcherServlet;
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnBean(HealthEndpoint.class)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class,
|
||||
exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
class HealthEndpointWebExtensionConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
@ -82,6 +83,7 @@ class HealthEndpointWebExtensionConfiguration {
|
|||
}
|
||||
|
||||
@ConditionalOnBean(DispatcherServlet.class)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB)
|
||||
static class MvcAdditionalHealthEndpointPathsConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
@ -97,6 +99,7 @@ class HealthEndpointWebExtensionConfiguration {
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(ResourceConfig.class)
|
||||
@ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet")
|
||||
@ConditionalOnAvailableEndpoint(endpoint = HealthEndpoint.class, exposure = EndpointExposure.WEB)
|
||||
static class JerseyAdditionalHealthEndpointPathsConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class QuartzEndpointAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnBean(QuartzEndpoint.class)
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnAvailableEndpoint(exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
public QuartzEndpointWebExtension quartzEndpointWebExtension(QuartzEndpoint endpoint) {
|
||||
return new QuartzEndpointWebExtension(endpoint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -327,7 +327,8 @@ class ConditionalOnAvailableEndpointTests {
|
|||
static class ExposureEndpointConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnAvailableEndpoint(endpoint = TestEndpoint.class, exposure = EndpointExposure.WEB)
|
||||
@ConditionalOnAvailableEndpoint(endpoint = TestEndpoint.class,
|
||||
exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
|
||||
String unexposed() {
|
||||
return "unexposed";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,30 @@ abstract class AbstractHealthEndpointAdditionalPathIntegrationTests<T extends Ab
|
|||
.exchange().expectStatus().isNotFound(), "local.server.port"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void groupsAreNotConfiguredWhenHealthEndpointIsNotExposedAndCloudFoundryPlatform() {
|
||||
this.runner.withPropertyValues("spring.jmx.enabled=true", "management.endpoints.web.exposure.exclude=health",
|
||||
"spring.main.cloud-platform=cloud_foundry", "management.endpoint.health.group.live.include=diskSpace",
|
||||
"management.endpoint.health.group.live.additional-path=server:healthz",
|
||||
"management.endpoint.health.group.live.show-components=always")
|
||||
.withInitializer(new ConditionEvaluationReportLoggingListener())
|
||||
.run(withWebTestClient((client) -> client.get().uri("/healthz").accept(MediaType.APPLICATION_JSON)
|
||||
.exchange().expectStatus().isNotFound(), "local.server.port"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void groupsAreNotConfiguredWhenHealthEndpointIsNotExposedWithDifferentManagementPortAndCloudFoundryPlatform() {
|
||||
this.runner
|
||||
.withPropertyValues("spring.jmx.enabled=true", "management.endpoints.web.exposure.exclude=health",
|
||||
"spring.main.cloud-platform=cloud_foundry", "management.server.port=0",
|
||||
"management.endpoint.health.group.live.include=diskSpace",
|
||||
"management.endpoint.health.group.live.additional-path=server:healthz",
|
||||
"management.endpoint.health.group.live.show-components=always")
|
||||
.withInitializer(new ConditionEvaluationReportLoggingListener())
|
||||
.run(withWebTestClient((client) -> client.get().uri("/healthz").accept(MediaType.APPLICATION_JSON)
|
||||
.exchange().expectStatus().isNotFound(), "local.server.port"));
|
||||
}
|
||||
|
||||
private void testResponse(WebTestClient client) {
|
||||
client.get().uri("/healthz").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody()
|
||||
.jsonPath("status").isEqualTo("UP").jsonPath("components.diskSpace").exists();
|
||||
|
|
|
|||
Loading…
Reference in New Issue