diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CachesEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CachesEndpointAutoConfiguration.java index e78a66e14f..c216ee44db 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CachesEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cache/CachesEndpointAutoConfiguration.java @@ -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); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java index 44536ab5ab..7fb384d6a8 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java @@ -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); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnAvailableEndpointCondition.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnAvailableEndpointCondition.java index 1b185fdb4d..ac5ad1b2e6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnAvailableEndpointCondition.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnAvailableEndpointCondition.java @@ -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 exposuresToCheck = getExposuresToCheck(conditionAnnotation); Set 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() { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/expose/EndpointExposure.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/expose/EndpointExposure.java index a678eb7456..a8abe8fdf3 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/expose/EndpointExposure.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/expose/EndpointExposure.java @@ -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; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java index 1dd998dd32..2a2d28d13d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java @@ -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); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java index 6fd895cade..ec16083331 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.java @@ -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 diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java index 7fdc2bd091..57bde64f6d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.java @@ -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 diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/quartz/QuartzEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/quartz/QuartzEndpointAutoConfiguration.java index d4a1e9e501..0221fd0374 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/quartz/QuartzEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/quartz/QuartzEndpointAutoConfiguration.java @@ -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); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpointTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpointTests.java index 530e27f061..31b1bd49d4 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpointTests.java @@ -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"; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/AbstractHealthEndpointAdditionalPathIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/AbstractHealthEndpointAdditionalPathIntegrationTests.java index dddc5eaf07..11e1d3b463 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/AbstractHealthEndpointAdditionalPathIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/AbstractHealthEndpointAdditionalPathIntegrationTests.java @@ -91,6 +91,30 @@ abstract class AbstractHealthEndpointAdditionalPathIntegrationTests 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();