Commit 6cb1208c by Johannes Edmeier

Add legacy trace conversion, update to current snapshot

parent 668d19c1
......@@ -13,8 +13,11 @@
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
......@@ -24,10 +27,10 @@
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server</artifactId>
</dependency>
<!-- dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
</dependency -->
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
......
......@@ -7,12 +7,23 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableAutoConfiguration
@EnableAdminServer
public class SpringBootAdminApplication extends SpringBootServletInitializer {
@Configuration
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()//
.and().csrf().disable();
}
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application;
......
info:
stage: test
spring:
application:
name: spring-boot-admin-sample-war
boot:
admin:
client:
url: http://localhost:8080
cloud:
config:
enabled: false
endpoints:
health:
sensitive: false
management:
endpoints:
web:
expose: "*"
......@@ -43,6 +43,10 @@
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
......
......@@ -2,7 +2,6 @@
info:
scm-url: "@scm.url@"
build-url: "http://travis-ci.org/@env.TRAVIS_REPO_SLUG@/builds/@env.TRAVIS_BUILD_ID@"
stage: test
logging:
file: "target/boot-admin-sample.log"
......@@ -10,14 +9,11 @@ logging:
management:
endpoints:
web:
base-path: "/actuator"
expose: "*"
jolokia:
enabled: true
spring:
application:
name: "@pom.artifactId@"
name: spring-boot-admin-sample
boot:
admin:
client:
......
......@@ -36,6 +36,15 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
......
......@@ -29,12 +29,12 @@ public class AdminServerProperties {
private MonitorProperties monitor = new MonitorProperties();
/**
* For Spring Boot 2.x applications the endpoints should be discovered automatically.
* For Spring Boot 2.x applications the endpoints should be discovered automatically using the actuator links.
* For Spring Boot 1.x applications SBA probes for the specified endpoints using an OPTIONS request.
* If the path differs from the id you can specify this as id:path (e.g. health:ping).
*/
private String[] probedEndpoints = {"health", "env", "metrics", "trace", "dump", "jolokia", "info", "logfile",
"refresh", "flyway", "liquibase", "heapdump", "loggers", "auditevents"};
private String[] probedEndpoints = {"health", "env", "metrics", "trace", "threaddump:dump", "jolokia", "info",
"logfile", "refresh", "flyway", "liquibase", "heapdump", "loggers", "auditevents"};
public void setContextPath(String pathPrefix) {
if (!pathPrefix.startsWith("/") || pathPrefix.endsWith("/")) {
......
......@@ -24,6 +24,7 @@ public class Endpoint implements Serializable {
public static final String INFO = "info";
public static final String HEALTH = "health";
public static final String ENV = "env";
public static final String TRACE = "trace";
private final String id;
private final String url;
......
......@@ -22,6 +22,7 @@ import io.netty.handler.timeout.ReadTimeoutHandler;
import reactor.core.publisher.Mono;
import java.util.concurrent.TimeUnit;
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
......@@ -44,6 +45,7 @@ public class InstanceWebClient {
filters.add(InstanceFilterFunctions.rewriteEndpointUrl());
filters.add(InstanceFilterFunctions.convertLegacyEndpoint(LegacyEndpointConverters.health()));
filters.add(InstanceFilterFunctions.convertLegacyEndpoint(LegacyEndpointConverters.env()));
filters.add(InstanceFilterFunctions.convertLegacyEndpoint(LegacyEndpointConverters.trace()));
}).build();
}
......@@ -68,7 +70,8 @@ public class InstanceWebClient {
}));
return WebClient.builder()
.clientConnector(connector)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, ActuatorMediaType.V2_JSON, ActuatorMediaType.V1_JSON,
MediaType.APPLICATION_JSON_VALUE)
.build();
}
}
......@@ -35,25 +35,36 @@ import org.springframework.http.codec.json.Jackson2JsonEncoder;
import static java.util.Collections.singletonMap;
public class LegacyEndpointConverters {
private static final ParameterizedTypeReference<Map<String, Object>> RESPONSE_TYPE = new ParameterizedTypeReference<Map<String, Object>>() {
private static final ParameterizedTypeReference<Map<String, Object>> RESPONSE_TYPE_MAP = new ParameterizedTypeReference<Map<String, Object>>() {
};
private static final ParameterizedTypeReference<List<Object>> RESPONSE_TYPE_LIST = new ParameterizedTypeReference<List<Object>>() {
};
private static final Jackson2JsonDecoder DECODER = new Jackson2JsonDecoder();
private static final Jackson2JsonEncoder ENCODER = new Jackson2JsonEncoder();
public static LegacyEndpointConverter health() {
return new LegacyEndpointConverter(Endpoint.HEALTH, convertMapUsing(LegacyEndpointConverters::convertHealth));
return new LegacyEndpointConverter(Endpoint.HEALTH,
convertUsing(RESPONSE_TYPE_MAP, RESPONSE_TYPE_MAP, LegacyEndpointConverters::convertHealth));
}
public static LegacyEndpointConverter env() {
return new LegacyEndpointConverter(Endpoint.ENV, convertMapUsing(LegacyEndpointConverters::convertEnv));
return new LegacyEndpointConverter(Endpoint.ENV,
convertUsing(RESPONSE_TYPE_MAP, RESPONSE_TYPE_MAP, LegacyEndpointConverters::convertEnv));
}
public static LegacyEndpointConverter trace() {
return new LegacyEndpointConverter(Endpoint.TRACE,
convertUsing(RESPONSE_TYPE_LIST, RESPONSE_TYPE_MAP, LegacyEndpointConverters::convertTrace));
}
@SuppressWarnings("unchecked")
private static Function<Flux<DataBuffer>, Flux<DataBuffer>> convertMapUsing(Function<Map<String, Object>, Map<String, Object>> converterFn) {
return input -> DECODER.decodeToMono(input, ResolvableType.forType(RESPONSE_TYPE), null, null)
.map(body -> converterFn.apply((Map<String, Object>) body))
private static <S, T> Function<Flux<DataBuffer>, Flux<DataBuffer>> convertUsing(ParameterizedTypeReference<S> sourceType,
ParameterizedTypeReference<T> targetType,
Function<S, T> converterFn) {
return input -> DECODER.decodeToMono(input, ResolvableType.forType(sourceType), null, null)
.map(body -> converterFn.apply((S) body))
.flatMapMany(output -> ENCODER.encode(Mono.just(output), new DefaultDataBufferFactory(),
ResolvableType.forType(RESPONSE_TYPE), null, null));
ResolvableType.forType(targetType), null, null));
}
@SuppressWarnings("unchecked")
......@@ -104,4 +115,7 @@ public class LegacyEndpointConverters {
return converted;
}
private static Map<String, Object> convertTrace(List<Object> traces) {
return singletonMap("traces", traces);
}
}
......@@ -132,7 +132,7 @@ public abstract class AbstractAdminApplicationTest {
private Registration createRegistration() {
return Registration.builder()
.name("Test-Instance")
.healthUrl("http://localhost:" + port + "/mgmt/status")
.healthUrl("http://localhost:" + port + "/mgmt/health")
.managementUrl("http://localhost:" + port + "/mgmt")
.serviceUrl("http://localhost:" + port)
.build();
......
......@@ -54,7 +54,7 @@ public class AdminApplicationTest extends AbstractAdminApplicationTest {
public static class TestAdminApplication {
@Bean
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange().anyExchange().permitAll()//
.and().csrf().disable()//
.build();
......
......@@ -70,7 +70,9 @@ public class InstanceWebClientTest {
StepVerifier.create(exchange).expectNextCount(1).verifyComplete();
wireMock.verify(1,
getRequestedFor(urlEqualTo("/status")).withHeader(ACCEPT, equalTo(MediaType.APPLICATION_JSON_VALUE)));
getRequestedFor(urlEqualTo("/status")).withHeader(ACCEPT, equalTo(MediaType.APPLICATION_JSON_VALUE))
.withHeader(ACCEPT, equalTo(ActuatorMediaType.V1_JSON))
.withHeader(ACCEPT, equalTo(ActuatorMediaType.V2_JSON)));
}
@Test
......
......@@ -71,6 +71,22 @@ public class LegacyEndpointConvertersTest {
.verifyComplete();
}
@Test
public void should_convert_trace() {
LegacyEndpointConverter converter = LegacyEndpointConverters.trace();
assertThat(converter.canConvert("trace")).isTrue();
assertThat(converter.canConvert("foo")).isFalse();
Flux<DataBuffer> legacyInput = this.read("trace-legacy.json");
Flux<Object> converted = converter.convert(legacyInput).transform(this::unmarshal);
Flux<Object> expected = this.read("trace-expected.json").transform(this::unmarshal);
StepVerifier.create(Flux.zip(converted, expected))
.assertNext(t -> assertThat(t.getT1()).isEqualTo(t.getT2()))
.verifyComplete();
}
@SuppressWarnings("unchecked")
private Flux<Object> unmarshal(Flux<DataBuffer> buffer) {
return decoder.decode(buffer, type, null, null);
......
{
"traces": [
{
"timestamp": "15610000",
"info": {
"status": 200
}
},
{
"timestamp": "15610001",
"info": {
"status": 200
}
}
]
}
\ No newline at end of file
[
{
"timestamp": "15610000",
"info": {
"status": 200
}
},
{
"timestamp": "15610001",
"info": {
"status": 200
}
}
]
\ No newline at end of file
......@@ -65,12 +65,12 @@ public class DefaultApplicationFactoryTest {
@Test
public void test_default() {
when(endpointPathProvider.getPath("health")).thenReturn("/application/health");
when(endpointPathProvider.getPath("health")).thenReturn("/actuator/health");
publishApplicationReadyEvent(factory, 8080, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":8080/application");
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":8080/application/health");
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":8080/actuator");
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":8080/actuator/health");
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":8080/");
}
......@@ -78,12 +78,12 @@ public class DefaultApplicationFactoryTest {
public void test_ssl() {
server.setSsl(new Ssl());
server.getSsl().setEnabled(true);
when(endpointPathProvider.getPath("health")).thenReturn("/application/health");
when(endpointPathProvider.getPath("health")).thenReturn("/actuator/health");
publishApplicationReadyEvent(factory, 8080, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).isEqualTo("https://" + getHostname() + ":8080/application");
assertThat(app.getHealthUrl()).isEqualTo("https://" + getHostname() + ":8080/application/health");
assertThat(app.getManagementUrl()).isEqualTo("https://" + getHostname() + ":8080/actuator");
assertThat(app.getHealthUrl()).isEqualTo("https://" + getHostname() + ":8080/actuator/health");
assertThat(app.getServiceUrl()).isEqualTo("https://" + getHostname() + ":8080/");
}
......@@ -91,12 +91,12 @@ public class DefaultApplicationFactoryTest {
public void test_ssl_management() {
management.setSsl(new Ssl());
management.getSsl().setEnabled(true);
when(endpointPathProvider.getPath("health")).thenReturn("/application/alive");
when(endpointPathProvider.getPath("health")).thenReturn("/actuator/alive");
publishApplicationReadyEvent(factory, 8080, 9090);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).isEqualTo("https://" + getHostname() + ":9090/application");
assertThat(app.getHealthUrl()).isEqualTo("https://" + getHostname() + ":9090/application/alive");
assertThat(app.getManagementUrl()).isEqualTo("https://" + getHostname() + ":9090/actuator");
assertThat(app.getHealthUrl()).isEqualTo("https://" + getHostname() + ":9090/actuator/alive");
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":8080/");
}
......@@ -117,7 +117,7 @@ public class DefaultApplicationFactoryTest {
publishApplicationReadyEvent(factory, 8080, 8081);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).matches("http://\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}:8081/application");
assertThat(app.getManagementUrl()).matches("http://\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}:8081/actuator");
}
@Test
......@@ -125,12 +125,12 @@ public class DefaultApplicationFactoryTest {
instanceProperties.setPreferIp(true);
server.setAddress(InetAddress.getByName("127.0.0.1"));
management.setAddress(InetAddress.getByName("127.0.0.2"));
when(endpointPathProvider.getPath("health")).thenReturn("/application/health");
when(endpointPathProvider.getPath("health")).thenReturn("/actuator/health");
publishApplicationReadyEvent(factory, 8080, 8081);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).isEqualTo("http://127.0.0.2:8081/application");
assertThat(app.getHealthUrl()).isEqualTo("http://127.0.0.2:8081/application/health");
assertThat(app.getManagementUrl()).isEqualTo("http://127.0.0.2:8081/actuator");
assertThat(app.getHealthUrl()).isEqualTo("http://127.0.0.2:8081/actuator/health");
assertThat(app.getServiceUrl()).isEqualTo("http://127.0.0.1:8080/");
}
......
......@@ -79,12 +79,12 @@ public class ServletApplicationFactoryTest {
@Test
public void test_contextPath() {
servletContext.setContextPath("app");
when(endpointPathProvider.getPath("health")).thenReturn("/application/health");
when(endpointPathProvider.getPath("health")).thenReturn("/actuator/health");
publishApplicationReadyEvent(factory, 80, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":80/app/application");
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":80/app/application/health");
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":80/app/actuator");
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":80/app/actuator/health");
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":80/app");
}
......@@ -92,12 +92,12 @@ public class ServletApplicationFactoryTest {
public void test_servletPath() {
server.getServlet().setPath("app");
servletContext.setContextPath("srv");
when(endpointPathProvider.getPath("health")).thenReturn("/application/health");
when(endpointPathProvider.getPath("health")).thenReturn("/actuator/health");
publishApplicationReadyEvent(factory, 80, null);
Application app = factory.createApplication();
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":80/srv/app/application");
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":80/srv/app/application/health");
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":80/srv/app/actuator");
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":80/srv/app/actuator/health");
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":80/srv");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment