Expose all endpoints under /cloudfoundryapplication

Regardless of whether the web endpoints have been enabled or not,
all endpoints for which beans are created need to be exposed in a
CF environment under /cloudfoundryapplication.

Closes gh-10673
This commit is contained in:
Madhura Bhave 2017-10-19 11:22:50 -07:00
parent c2f649df54
commit df30d2fc10
2 changed files with 53 additions and 4 deletions

View File

@ -18,10 +18,11 @@ package org.springframework.boot.actuate.autoconfigure.cloudfoundry;
import java.util.Arrays; import java.util.Arrays;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.DefaultCachingConfigurationFactory;
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
import org.springframework.boot.actuate.endpoint.OperationParameterMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.WebEndpointOperation; import org.springframework.boot.actuate.endpoint.web.annotation.WebAnnotationEndpointDiscoverer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@ -33,6 +34,7 @@ import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.endpoint.web.EndpointMapping; import org.springframework.boot.endpoint.web.EndpointMapping;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
@ -66,14 +68,24 @@ public class CloudFoundryActuatorAutoConfiguration {
@ConditionalOnBean(DispatcherServlet.class) @ConditionalOnBean(DispatcherServlet.class)
static class MvcWebEndpointConfiguration { static class MvcWebEndpointConfiguration {
private final ApplicationContext applicationContext;
MvcWebEndpointConfiguration(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean @Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping( public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
EndpointProvider<WebEndpointOperation> provider, OperationParameterMapper parameterMapper,
DefaultCachingConfigurationFactory cachingConfigurationFactory,
EndpointMediaTypes endpointMediaTypes, Environment environment, EndpointMediaTypes endpointMediaTypes, Environment environment,
RestTemplateBuilder builder) { RestTemplateBuilder builder) {
WebAnnotationEndpointDiscoverer endpointDiscoverer = new WebAnnotationEndpointDiscoverer(
this.applicationContext, parameterMapper, cachingConfigurationFactory,
endpointMediaTypes);
return new CloudFoundryWebEndpointServletHandlerMapping( return new CloudFoundryWebEndpointServletHandlerMapping(
new EndpointMapping("/cloudfoundryapplication"), new EndpointMapping("/cloudfoundryapplication"),
provider.getEndpoints(), endpointMediaTypes, getCorsConfiguration(), endpointDiscoverer.discoverEndpoints(), endpointMediaTypes, getCorsConfiguration(),
getSecurityInterceptor(builder, environment)); getSecurityInterceptor(builder, environment));
} }

View File

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.autoconfigure.cloudfoundry; package org.springframework.boot.actuate.autoconfigure.cloudfoundry;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -25,7 +26,11 @@ import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
import org.springframework.boot.actuate.endpoint.EndpointInfo;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType; import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.boot.actuate.endpoint.web.WebEndpointOperation;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
@ -35,6 +40,8 @@ import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoC
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext; import org.springframework.mock.web.MockServletContext;
@ -200,6 +207,16 @@ public class CloudFoundryActuatorAutoConfigurationTests {
.isFalse(); .isFalse();
} }
@Test
public void allEndpointsAvailableUnderCloudFoundryWithoutEnablingWeb() throws Exception {
this.context.register(TestConfiguration.class);
this.context.refresh();
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping();
List<EndpointInfo<WebEndpointOperation>> endpoints = (List<EndpointInfo<WebEndpointOperation>>) handlerMapping.getEndpoints();
assertThat(endpoints.size()).isEqualTo(1);
assertThat(endpoints.get(0).getId()).isEqualTo("test");
}
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping() { private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping() {
TestPropertyValues TestPropertyValues
.of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", .of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
@ -210,4 +227,24 @@ public class CloudFoundryActuatorAutoConfigurationTests {
CloudFoundryWebEndpointServletHandlerMapping.class); CloudFoundryWebEndpointServletHandlerMapping.class);
} }
@Configuration
static class TestConfiguration {
@Bean
public TestEndpoint testEndpoint() {
return new TestEndpoint();
}
}
@Endpoint(id = "test")
static class TestEndpoint {
@ReadOperation
public String hello() {
return "hello world";
}
}
} }