Update Actuator endpoints to use custom media type

Previously, the actuator's endpoints produced application/json and,
where appropriate, also consumed application/json. Without a custom,
versioned media type, it's impossible for us to make changes to the
endpoints without breaking clients.

This commit introduces a new media type,
application/spring-boot.actuator.v1+json, that is now produced by
default with application/json also being produced if requested.
Endpoints that consume JSON will now also accept content the uses
the new media type in addition to application/json.

Closes gh-7967
This commit is contained in:
Andy Wilkinson
2017-01-19 15:25:48 +00:00
parent bed545df64
commit b900a3efc8
23 changed files with 478 additions and 80 deletions

View File

@@ -37,6 +37,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.mvc.ActuatorMediaTypes;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
@@ -76,9 +77,9 @@ public class EndpointDocumentation {
static final File LOG_FILE = new File("target/logs/spring.log");
private static final Set<String> SKIPPED = Collections.<String>unmodifiableSet(
new HashSet<String>(Arrays.asList("/docs", "/logfile", "/heapdump",
"/auditevents")));
private static final Set<String> SKIPPED = Collections
.<String>unmodifiableSet(new HashSet<String>(
Arrays.asList("/docs", "/logfile", "/heapdump", "/auditevents")));
@Autowired
private MvcEndpoints mvcEndpoints;
@@ -123,34 +124,36 @@ public class EndpointDocumentation {
public void setLogger() throws Exception {
this.mockMvc
.perform(post("/loggers/org.springframework.boot")
.contentType(MediaType.APPLICATION_JSON)
.contentType(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON)
.content("{\"configuredLevel\": \"DEBUG\"}"))
.andExpect(status().isOk()).andDo(document("set-logger"));
}
@Test
public void auditEvents() throws Exception {
this.mockMvc.perform(get("/auditevents")
.param("after", "2016-11-01T10:00:00+0000")
.accept(MediaType.APPLICATION_JSON))
this.mockMvc
.perform(get("/auditevents").param("after", "2016-11-01T10:00:00+0000")
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk()).andDo(document("auditevents"));
}
@Test
public void auditEventsByPrincipal() throws Exception {
this.mockMvc.perform(get("/auditevents").param("principal", "admin")
this.mockMvc
.perform(get("/auditevents").param("principal", "admin")
.param("after", "2016-11-01T10:00:00+0000")
.accept(MediaType.APPLICATION_JSON))
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk())
.andDo(document("auditevents/filter-by-principal"));
}
@Test
public void auditEventsByPrincipalAndType() throws Exception {
this.mockMvc.perform(get("/auditevents").param("principal", "admin")
this.mockMvc
.perform(get("/auditevents").param("principal", "admin")
.param("after", "2016-11-01T10:00:00+0000")
.param("type", "AUTHENTICATION_SUCCESS")
.accept(MediaType.APPLICATION_JSON))
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk())
.andDo(document("auditevents/filter-by-principal-and-type"));
}
@@ -167,7 +170,9 @@ public class EndpointDocumentation {
if (!SKIPPED.contains(endpointPath)) {
String output = endpointPath.substring(1);
output = output.length() > 0 ? output : "./";
this.mockMvc.perform(get(endpointPath).accept(MediaType.APPLICATION_JSON))
this.mockMvc
.perform(get(endpointPath)
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk()).andDo(document(output))
.andDo(new ResultHandler() {

View File

@@ -20,10 +20,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.mvc.ActuatorMediaTypes;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
@@ -50,7 +50,9 @@ public class HealthEndpointDocumentation {
@Test
public void health() throws Exception {
this.mockMvc.perform(get("/health").accept(MediaType.APPLICATION_JSON))
this.mockMvc
.perform(get("/health")
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk()).andDo(document("health/insensitive"));
}

View File

@@ -20,10 +20,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.mvc.ActuatorMediaTypes;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
@@ -51,13 +51,17 @@ public class HypermediaEndpointDocumentation {
@Test
public void beans() throws Exception {
this.mockMvc.perform(get("/beans").accept(MediaType.APPLICATION_JSON))
this.mockMvc
.perform(get("/beans")
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk()).andDo(document("beans/hypermedia"));
}
@Test
public void metrics() throws Exception {
this.mockMvc.perform(get("/metrics").accept(MediaType.APPLICATION_JSON))
this.mockMvc
.perform(get("/metrics")
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$._links.self.href")
.value("http://localhost:8080/metrics"))
@@ -66,7 +70,9 @@ public class HypermediaEndpointDocumentation {
@Test
public void home() throws Exception {
this.mockMvc.perform(get("/actuator").accept(MediaType.APPLICATION_JSON))
this.mockMvc
.perform(get("/actuator")
.accept(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON))
.andExpect(status().isOk()).andDo(document("admin"));
}