Provide links for actuators at / when using a separate management port
See gh-17418
This commit is contained in:
parent
edea223841
commit
c108629311
|
|
@ -26,6 +26,7 @@ import org.glassfish.jersey.server.ResourceConfig;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||||
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
|
||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||||
|
|
@ -42,6 +43,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||||
import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer;
|
import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ManagementContextConfiguration @ManagementContextConfiguration} for Jersey
|
* {@link ManagementContextConfiguration @ManagementContextConfiguration} for Jersey
|
||||||
|
|
@ -62,14 +64,16 @@ class JerseyWebEndpointManagementContextConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
ResourceConfigCustomizer webEndpointRegistrar(WebEndpointsSupplier webEndpointsSupplier,
|
ResourceConfigCustomizer webEndpointRegistrar(WebEndpointsSupplier webEndpointsSupplier,
|
||||||
ServletEndpointsSupplier servletEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
|
ServletEndpointsSupplier servletEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
|
||||||
WebEndpointProperties webEndpointProperties) {
|
WebEndpointProperties webEndpointProperties, Environment environment) {
|
||||||
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
||||||
allEndpoints.addAll(webEndpointsSupplier.getEndpoints());
|
allEndpoints.addAll(webEndpointsSupplier.getEndpoints());
|
||||||
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
|
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
|
||||||
return (resourceConfig) -> {
|
return (resourceConfig) -> {
|
||||||
JerseyEndpointResourceFactory resourceFactory = new JerseyEndpointResourceFactory();
|
JerseyEndpointResourceFactory resourceFactory = new JerseyEndpointResourceFactory();
|
||||||
String basePath = webEndpointProperties.getBasePath();
|
String basePath = webEndpointProperties.getBasePath();
|
||||||
EndpointMapping endpointMapping = new EndpointMapping(basePath);
|
ManagementPortType type = ManagementPortType.get(environment);
|
||||||
|
Boolean samePort = type == ManagementPortType.SAME;
|
||||||
|
EndpointMapping endpointMapping = new EndpointMapping(basePath, samePort);
|
||||||
Collection<ExposableWebEndpoint> webEndpoints = Collections
|
Collection<ExposableWebEndpoint> webEndpoints = Collections
|
||||||
.unmodifiableCollection(webEndpointsSupplier.getEndpoints());
|
.unmodifiableCollection(webEndpointsSupplier.getEndpoints());
|
||||||
resourceConfig.registerResources(new HashSet<>(resourceFactory.createEndpointResources(endpointMapping,
|
resourceConfig.registerResources(new HashSet<>(resourceFactory.createEndpointResources(endpointMapping,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||||
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
|
||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||||
|
|
@ -40,6 +41,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.http.server.reactive.HttpHandler;
|
import org.springframework.http.server.reactive.HttpHandler;
|
||||||
import org.springframework.web.reactive.DispatcherHandler;
|
import org.springframework.web.reactive.DispatcherHandler;
|
||||||
|
|
||||||
|
|
@ -62,8 +64,11 @@ public class WebFluxEndpointManagementContextConfiguration {
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public WebFluxEndpointHandlerMapping webEndpointReactiveHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
|
public WebFluxEndpointHandlerMapping webEndpointReactiveHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
|
||||||
ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
|
ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes,
|
||||||
CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties) {
|
CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties,
|
||||||
EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
|
Environment environment) {
|
||||||
|
ManagementPortType type = ManagementPortType.get(environment);
|
||||||
|
Boolean samePort = type == ManagementPortType.SAME;
|
||||||
|
EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath(), samePort);
|
||||||
Collection<ExposableWebEndpoint> endpoints = webEndpointsSupplier.getEndpoints();
|
Collection<ExposableWebEndpoint> endpoints = webEndpointsSupplier.getEndpoints();
|
||||||
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
||||||
allEndpoints.addAll(endpoints);
|
allEndpoints.addAll(endpoints);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||||
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
|
||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||||
|
|
@ -41,6 +42,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -63,13 +65,15 @@ public class WebMvcEndpointManagementContextConfiguration {
|
||||||
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
|
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
|
||||||
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
|
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
|
||||||
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
|
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
|
||||||
WebEndpointProperties webEndpointProperties) {
|
WebEndpointProperties webEndpointProperties, Environment environment) {
|
||||||
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
||||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
||||||
allEndpoints.addAll(webEndpoints);
|
allEndpoints.addAll(webEndpoints);
|
||||||
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
|
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
|
||||||
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
||||||
EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
|
ManagementPortType type = ManagementPortType.get(environment);
|
||||||
|
Boolean samePort = type == ManagementPortType.SAME;
|
||||||
|
EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath(), samePort);
|
||||||
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
|
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
|
||||||
corsProperties.toCorsConfiguration(),
|
corsProperties.toCorsConfiguration(),
|
||||||
new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()));
|
new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()));
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,20 @@ public class EndpointMapping {
|
||||||
|
|
||||||
private final String path;
|
private final String path;
|
||||||
|
|
||||||
|
private final Boolean samePort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code EndpointMapping} using the given {@code path}.
|
* Creates a new {@code EndpointMapping} using the given {@code path}.
|
||||||
* @param path the path
|
* @param path the path
|
||||||
|
* @param samePort states true or false for same port as server
|
||||||
*/
|
*/
|
||||||
public EndpointMapping(String path) {
|
public EndpointMapping(String path, Boolean samePort) {
|
||||||
this.path = normalizePath(path);
|
this.path = normalizePath(path);
|
||||||
|
this.samePort = samePort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndpointMapping(String path) {
|
||||||
|
this(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -44,6 +52,10 @@ public class EndpointMapping {
|
||||||
return this.path;
|
return this.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSamePort() {
|
||||||
|
return this.samePort;
|
||||||
|
}
|
||||||
|
|
||||||
public String createSubPath(String path) {
|
public String createSubPath(String path) {
|
||||||
return this.path + normalizePath(path);
|
return this.path + normalizePath(path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ public class JerseyEndpointResourceFactory {
|
||||||
List<Resource> resources = new ArrayList<>();
|
List<Resource> resources = new ArrayList<>();
|
||||||
endpoints.stream().flatMap((endpoint) -> endpoint.getOperations().stream())
|
endpoints.stream().flatMap((endpoint) -> endpoint.getOperations().stream())
|
||||||
.map((operation) -> createResource(endpointMapping, operation)).forEach(resources::add);
|
.map((operation) -> createResource(endpointMapping, operation)).forEach(resources::add);
|
||||||
if (StringUtils.hasText(endpointMapping.getPath())) {
|
if (StringUtils.hasText(endpointMapping.getPath()) || !endpointMapping.isSamePort()) {
|
||||||
Resource resource = createEndpointLinksResource(endpointMapping.getPath(), endpointMediaTypes,
|
Resource resource = createEndpointLinksResource(endpointMapping.getPath(), endpointMediaTypes,
|
||||||
linksResolver);
|
linksResolver);
|
||||||
resources.add(resource);
|
resources.add(resource);
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappi
|
||||||
registerMappingForOperation(endpoint, operation);
|
registerMappingForOperation(endpoint, operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.hasText(this.endpointMapping.getPath())) {
|
if (StringUtils.hasText(this.endpointMapping.getPath()) || !this.endpointMapping.isSamePort()) {
|
||||||
registerLinksMapping();
|
registerLinksMapping();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ public abstract class AbstractWebMvcEndpointHandlerMapping extends RequestMappin
|
||||||
registerMappingForOperation(endpoint, operation);
|
registerMappingForOperation(endpoint, operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.hasText(this.endpointMapping.getPath())) {
|
if (StringUtils.hasText(this.endpointMapping.getPath()) || !this.endpointMapping.isSamePort()) {
|
||||||
registerLinksMapping();
|
registerLinksMapping();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,4 +77,9 @@ class EndpointMappingTests {
|
||||||
assertThat(new EndpointMapping("/test").createSubPath("one/")).isEqualTo("/test/one");
|
assertThat(new EndpointMapping("/test").createSubPath("one/")).isEqualTo("/test/one");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setDifferentPort() {
|
||||||
|
assertThat(new EndpointMapping("/test", false).isSamePort()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package smoketest.actuator;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.web.server.LocalManagementPort;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||||
|
properties = { "management.endpoints.web.base-path=/","management.server.port=0"})
|
||||||
|
public class ManagementDifferentPortSampleActuatorApplicationTests {
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
@LocalManagementPort
|
||||||
|
private int managementPort;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDifferentServerPort(){
|
||||||
|
if(this.managementPort != this.port) {
|
||||||
|
ResponseEntity<String> entity = new TestRestTemplate("user", getPassword())
|
||||||
|
.getForEntity("http://localhost:" + this.managementPort + "/", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
assertThat(entity.getBody()).contains("\"_links\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPassword(){
|
||||||
|
return "password";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package smoketest.jersey;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.web.server.LocalManagementPort;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"management.server.port=0","management.endpoints.web.base-path=/"})
|
||||||
|
public class JerseyDifferentPortSampleActuatorApplicationTests {
|
||||||
|
|
||||||
|
@LocalManagementPort
|
||||||
|
private int managementPort;
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDifferentServerPort(){
|
||||||
|
if(this.managementPort != this.port) {
|
||||||
|
ResponseEntity<String> entity = new TestRestTemplate("user", getPassword())
|
||||||
|
.getForEntity("http://localhost:" + this.managementPort + "/", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
assertThat(entity.getBody()).contains("\"_links\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPassword(){
|
||||||
|
return "password";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package smoketest.webflux;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.web.server.LocalManagementPort;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"management.server.port=0","management.endpoints.web.base-path=/"})
|
||||||
|
public class WebFluxDifferentPortSampleActuatorApplicationTests {
|
||||||
|
|
||||||
|
@LocalManagementPort
|
||||||
|
private int managementPort;
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDifferentServerPort(){
|
||||||
|
if(this.managementPort != this.port) {
|
||||||
|
ResponseEntity<String> entity = new TestRestTemplate("user", getPassword())
|
||||||
|
.getForEntity("http://localhost:" + this.managementPort + "/", String.class);
|
||||||
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
assertThat(entity.getBody()).contains("\"_links\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPassword(){
|
||||||
|
return "password";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue