Merge branch '2.0.x' into 2.1.x
Closes gh-17078
This commit is contained in:
@@ -55,40 +55,36 @@ public class SpringApplicationHierarchyTests {
|
||||
public void testParent() {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(Child.class);
|
||||
builder.parent(Parent.class);
|
||||
this.context = builder.run("--server.port=0",
|
||||
"--management.metrics.use-global-registry=false");
|
||||
this.context = builder.run("--server.port=0", "--management.metrics.use-global-registry=false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChild() {
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder(Parent.class);
|
||||
builder.child(Child.class);
|
||||
this.context = builder.run("--server.port=0",
|
||||
"--management.metrics.use-global-registry=false");
|
||||
this.context = builder.run("--server.port=0", "--management.metrics.use-global-registry=false");
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class,
|
||||
ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
|
||||
FlywayAutoConfiguration.class, JestAutoConfiguration.class,
|
||||
MetricsAutoConfiguration.class },
|
||||
@EnableAutoConfiguration(
|
||||
exclude = { ElasticsearchDataAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
|
||||
FlywayAutoConfiguration.class, JestAutoConfiguration.class, MetricsAutoConfiguration.class },
|
||||
excludeName = {
|
||||
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
|
||||
public static class Child {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class,
|
||||
ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
|
||||
FlywayAutoConfiguration.class, JestAutoConfiguration.class,
|
||||
MetricsAutoConfiguration.class },
|
||||
@EnableAutoConfiguration(
|
||||
exclude = { ElasticsearchDataAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
|
||||
FlywayAutoConfiguration.class, JestAutoConfiguration.class, MetricsAutoConfiguration.class },
|
||||
excludeName = {
|
||||
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
|
||||
public static class Parent {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,21 +36,18 @@ public class RabbitHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(RabbitAutoConfiguration.class,
|
||||
RabbitHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
RabbitHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(RabbitHealthIndicator.class)
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(RabbitHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.rabbit.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(RabbitHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RabbitHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -55,34 +55,28 @@ public class AuditAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void ownAuditEventRepository() {
|
||||
registerAndRefresh(CustomAuditEventRepositoryConfiguration.class,
|
||||
AuditAutoConfiguration.class);
|
||||
assertThat(this.context.getBean(AuditEventRepository.class))
|
||||
.isInstanceOf(TestAuditEventRepository.class);
|
||||
registerAndRefresh(CustomAuditEventRepositoryConfiguration.class, AuditAutoConfiguration.class);
|
||||
assertThat(this.context.getBean(AuditEventRepository.class)).isInstanceOf(TestAuditEventRepository.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ownAuthenticationAuditListener() {
|
||||
registerAndRefresh(CustomAuthenticationAuditListenerConfiguration.class,
|
||||
AuditAutoConfiguration.class);
|
||||
registerAndRefresh(CustomAuthenticationAuditListenerConfiguration.class, AuditAutoConfiguration.class);
|
||||
assertThat(this.context.getBean(AbstractAuthenticationAuditListener.class))
|
||||
.isInstanceOf(TestAuthenticationAuditListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ownAuthorizationAuditListener() {
|
||||
registerAndRefresh(CustomAuthorizationAuditListenerConfiguration.class,
|
||||
AuditAutoConfiguration.class);
|
||||
registerAndRefresh(CustomAuthorizationAuditListenerConfiguration.class, AuditAutoConfiguration.class);
|
||||
assertThat(this.context.getBean(AbstractAuthorizationAuditListener.class))
|
||||
.isInstanceOf(TestAuthorizationAuditListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ownAuditListener() {
|
||||
registerAndRefresh(CustomAuditListenerConfiguration.class,
|
||||
AuditAutoConfiguration.class);
|
||||
assertThat(this.context.getBean(AbstractAuditListener.class))
|
||||
.isInstanceOf(TestAuditListener.class);
|
||||
registerAndRefresh(CustomAuditListenerConfiguration.class, AuditAutoConfiguration.class);
|
||||
assertThat(this.context.getBean(AbstractAuditListener.class)).isInstanceOf(TestAuditListener.class);
|
||||
}
|
||||
|
||||
private void registerAndRefresh(Class<?>... annotatedClasses) {
|
||||
@@ -114,8 +108,7 @@ public class AuditAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
protected static class TestAuthenticationAuditListener
|
||||
extends AbstractAuthenticationAuditListener {
|
||||
protected static class TestAuthenticationAuditListener extends AbstractAuthenticationAuditListener {
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
@@ -137,8 +130,7 @@ public class AuditAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
protected static class TestAuthorizationAuditListener
|
||||
extends AbstractAuthorizationAuditListener {
|
||||
protected static class TestAuthorizationAuditListener extends AbstractAuthorizationAuditListener {
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,22 +33,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class AuditEventsEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class,
|
||||
AuditEventsEndpointAutoConfiguration.class));
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(AuditAutoConfiguration.class, AuditEventsEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(AuditEventsEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(AuditEventsEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpoint() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.auditevents.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(AuditEventsEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.auditevents.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditEventsEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,20 +32,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class BeansEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(BeansEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(BeansEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).hasSingleBean(BeansEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(BeansEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.beans.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(BeansEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(BeansEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,27 +37,24 @@ import static org.mockito.Mockito.mock;
|
||||
public class CachesEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(CachesEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(CachesEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withUserConfiguration(CacheConfiguration.class).run(
|
||||
(context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
this.contextRunner.withUserConfiguration(CacheConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWithoutCacheManagerShouldHaveEndpointBean() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.caches.enabled:false")
|
||||
.withUserConfiguration(CacheConfiguration.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(CachesEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,21 +40,18 @@ public class CassandraHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CassandraConfiguration.class,
|
||||
CassandraHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
CassandraHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(CassandraHealthIndicator.class)
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.cassandra.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(CassandraHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CassandraHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,24 +40,19 @@ import static org.mockito.Mockito.mock;
|
||||
public class CassandraReactiveHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(CassandraMockConfiguration.class)
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
CassandraReactiveHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
.withUserConfiguration(CassandraMockConfiguration.class).withConfiguration(AutoConfigurations.of(
|
||||
CassandraReactiveHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(CassandraReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(CassandraHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(CassandraHealthIndicator.class).doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.cassandra.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(CassandraReactiveHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CassandraReactiveHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,50 +32,43 @@ public class CloudFoundryAuthorizationExceptionTests {
|
||||
|
||||
@Test
|
||||
public void statusCodeForInvalidTokenReasonShouldBe401() {
|
||||
assertThat(createException(Reason.INVALID_TOKEN).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThat(createException(Reason.INVALID_TOKEN).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForInvalidIssuerReasonShouldBe401() {
|
||||
assertThat(createException(Reason.INVALID_ISSUER).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThat(createException(Reason.INVALID_ISSUER).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForInvalidAudienceReasonShouldBe401() {
|
||||
assertThat(createException(Reason.INVALID_AUDIENCE).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThat(createException(Reason.INVALID_AUDIENCE).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForInvalidSignatureReasonShouldBe401() {
|
||||
assertThat(createException(Reason.INVALID_SIGNATURE).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThat(createException(Reason.INVALID_SIGNATURE).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForMissingAuthorizationReasonShouldBe401() {
|
||||
assertThat(createException(Reason.MISSING_AUTHORIZATION).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
assertThat(createException(Reason.MISSING_AUTHORIZATION).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForUnsupportedSignatureAlgorithmReasonShouldBe401() {
|
||||
assertThat(createException(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM)
|
||||
.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForTokenExpiredReasonShouldBe401() {
|
||||
assertThat(createException(Reason.TOKEN_EXPIRED).getStatusCode())
|
||||
assertThat(createException(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForTokenExpiredReasonShouldBe401() {
|
||||
assertThat(createException(Reason.TOKEN_EXPIRED).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void statusCodeForAccessDeniedReasonShouldBe403() {
|
||||
assertThat(createException(Reason.ACCESS_DENIED).getStatusCode())
|
||||
.isEqualTo(HttpStatus.FORBIDDEN);
|
||||
assertThat(createException(Reason.ACCESS_DENIED).getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,16 +36,14 @@ public class CloudFoundryEndpointFilterTests {
|
||||
@Test
|
||||
public void matchIfDiscovererCloudFoundryShouldReturnFalse() {
|
||||
DiscoveredEndpoint<?> endpoint = mock(DiscoveredEndpoint.class);
|
||||
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class))
|
||||
.willReturn(true);
|
||||
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class)).willReturn(true);
|
||||
assertThat(this.filter.match(endpoint)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchIfDiscovererNotCloudFoundryShouldReturnFalse() {
|
||||
DiscoveredEndpoint<?> endpoint = mock(DiscoveredEndpoint.class);
|
||||
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class))
|
||||
.willReturn(false);
|
||||
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class)).willReturn(false);
|
||||
assertThat(this.filter.match(endpoint)).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,8 +60,8 @@ public class CloudFoundryWebEndpointDiscovererTests {
|
||||
for (ExposableWebEndpoint endpoint : endpoints) {
|
||||
if (endpoint.getEndpointId().equals(EndpointId.of("health"))) {
|
||||
WebOperation operation = findMainReadOperation(endpoint);
|
||||
assertThat(operation.invoke(new InvocationContext(
|
||||
mock(SecurityContext.class), Collections.emptyMap())))
|
||||
assertThat(operation
|
||||
.invoke(new InvocationContext(mock(SecurityContext.class), Collections.emptyMap())))
|
||||
.isEqualTo("cf");
|
||||
}
|
||||
}
|
||||
@@ -74,31 +74,24 @@ public class CloudFoundryWebEndpointDiscovererTests {
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"No main read operation found from " + endpoint.getOperations());
|
||||
throw new IllegalStateException("No main read operation found from " + endpoint.getOperations());
|
||||
}
|
||||
|
||||
private void load(Class<?> configuration,
|
||||
Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
|
||||
private void load(Class<?> configuration, Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
|
||||
this.load((id) -> null, (id) -> id.toString(), configuration, consumer);
|
||||
}
|
||||
|
||||
private void load(Function<EndpointId, Long> timeToLive,
|
||||
PathMapper endpointPathMapper, Class<?> configuration,
|
||||
private void load(Function<EndpointId, Long> timeToLive, PathMapper endpointPathMapper, Class<?> configuration,
|
||||
Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
configuration);
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configuration);
|
||||
try {
|
||||
ConversionServiceParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
|
||||
DefaultConversionService.getSharedInstance());
|
||||
EndpointMediaTypes mediaTypes = new EndpointMediaTypes(
|
||||
Collections.singletonList("application/json"),
|
||||
EndpointMediaTypes mediaTypes = new EndpointMediaTypes(Collections.singletonList("application/json"),
|
||||
Collections.singletonList("application/json"));
|
||||
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(
|
||||
context, parameterMapper, mediaTypes,
|
||||
Collections.singletonList(endpointPathMapper),
|
||||
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
|
||||
Collections.emptyList());
|
||||
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(context,
|
||||
parameterMapper, mediaTypes, Collections.singletonList(endpointPathMapper),
|
||||
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)), Collections.emptyList());
|
||||
consumer.accept(discoverer);
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,8 +35,7 @@ public class TokenTests {
|
||||
|
||||
@Test
|
||||
public void invalidJwtShouldThrowException() {
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> new Token("invalid-token"))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> new Token("invalid-token"))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -45,8 +44,8 @@ public class TokenTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
|
||||
String claims = "invalid-claims";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes())
|
||||
+ "." + Base64Utils.encodeToString(claims.getBytes())))
|
||||
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes()) + "."
|
||||
+ Base64Utils.encodeToString(claims.getBytes())))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -55,8 +54,8 @@ public class TokenTests {
|
||||
String header = "invalid-header";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes())
|
||||
+ "." + Base64Utils.encodeToString(claims.getBytes())))
|
||||
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes()) + "."
|
||||
+ Base64Utils.encodeToString(claims.getBytes())))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -64,8 +63,7 @@ public class TokenTests {
|
||||
public void emptyJwtSignatureShouldThrowException() {
|
||||
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b3B0YWwu"
|
||||
+ "Y29tIiwiZXhwIjoxNDI2NDIwODAwLCJhd2Vzb21lIjp0cnVlfQ.";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> new Token(token))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> new Token(token))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -82,8 +80,7 @@ public class TokenTests {
|
||||
assertThat(token.getSignatureAlgorithm()).isEqualTo("RS256");
|
||||
assertThat(token.getKeyId()).isEqualTo("key-id");
|
||||
assertThat(token.getContent()).isEqualTo(content.getBytes());
|
||||
assertThat(token.getSignature())
|
||||
.isEqualTo(Base64Utils.decodeFromString(signature));
|
||||
assertThat(token.getSignature()).isEqualTo(Base64Utils.decodeFromString(signature));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,8 +89,7 @@ public class TokenTests {
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> token.getSignatureAlgorithm())
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.isThrownBy(() -> token.getSignatureAlgorithm()).satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -101,8 +97,7 @@ public class TokenTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> token.getIssuer())
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> token.getIssuer())
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -111,8 +106,7 @@ public class TokenTests {
|
||||
String header = "{\"alg\": \"RS256\", \"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> token.getKeyId())
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> token.getKeyId())
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -121,20 +115,18 @@ public class TokenTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
|
||||
String claims = "{\"iss\": \"http://localhost:8080/uaa/oauth/token\"" + "}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> token.getExpiry())
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> token.getExpiry())
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
private Token createToken(String header, String claims) {
|
||||
Token token = new Token(Base64Utils.encodeToString(header.getBytes()) + "."
|
||||
+ Base64Utils.encodeToString(claims.getBytes()) + "."
|
||||
+ Base64Utils.encodeToString("signature".getBytes()));
|
||||
Token token = new Token(
|
||||
Base64Utils.encodeToString(header.getBytes()) + "." + Base64Utils.encodeToString(claims.getBytes())
|
||||
+ "." + Base64Utils.encodeToString("signature".getBytes()));
|
||||
return token;
|
||||
}
|
||||
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(
|
||||
Reason reason) {
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
|
||||
return (ex) -> assertThat(ex.getReason()).isEqualTo(reason);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,18 +46,14 @@ public class CloudFoundryReactiveHealthEndpointWebExtensionTests {
|
||||
|
||||
private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfigurationTests.WebClientCustomizerConfig.class,
|
||||
WebClientAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
@@ -65,8 +61,7 @@ public class CloudFoundryReactiveHealthEndpointWebExtensionTests {
|
||||
this.contextRunner.run((context) -> {
|
||||
CloudFoundryReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(extension.health().block(Duration.ofSeconds(30)).getBody()
|
||||
.getDetails()).isNotEmpty();
|
||||
assertThat(extension.health().block(Duration.ofSeconds(30)).getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -70,109 +70,88 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
public class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
|
||||
private static ReactiveTokenValidator tokenValidator = mock(
|
||||
ReactiveTokenValidator.class);
|
||||
private static ReactiveTokenValidator tokenValidator = mock(ReactiveTokenValidator.class);
|
||||
|
||||
private static ReactiveCloudFoundrySecurityService securityService = mock(
|
||||
ReactiveCloudFoundrySecurityService.class);
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
|
||||
AnnotationConfigReactiveWebServerApplicationContext::new)
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(WebFluxAutoConfiguration.class,
|
||||
HttpHandlerAutoConfiguration.class,
|
||||
ReactiveWebServerFactoryAutoConfiguration.class))
|
||||
.withUserConfiguration(TestEndpointConfiguration.class)
|
||||
.withPropertyValues("server.port=0");
|
||||
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class,
|
||||
HttpHandlerAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class))
|
||||
.withUserConfiguration(TestEndpointConfiguration.class).withPropertyValues("server.port=0");
|
||||
|
||||
@Test
|
||||
public void operationWithSecurityInterceptorForbidden() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void operationWithSecurityInterceptorSuccess() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.OK)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseToOptionsRequestIncludesCorsHeaders() {
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.options()
|
||||
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Access-Control-Request-Method", "POST")
|
||||
.header("Origin", "https://example.com").exchange().expectStatus().isOk()
|
||||
.expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com")
|
||||
.expectHeader().valueEquals("Access-Control-Allow-Methods", "GET,POST")));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.options().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Access-Control-Request-Method", "POST")
|
||||
.header("Origin", "https://example.com").exchange().expectStatus().isOk().expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com").expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Methods", "GET,POST")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToOtherEndpointsWithFullAccess() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
|
||||
.isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false)
|
||||
.jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false)
|
||||
.jsonPath("_links.env.href").isNotEmpty().jsonPath("_links.env.templated")
|
||||
.isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
|
||||
.jsonPath("_links.test.templated").isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href").isNotEmpty()
|
||||
.jsonPath("_links.test-part.templated").isEqualTo(true)));
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner
|
||||
.run(withWebTestClient((client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env.href").isNotEmpty()
|
||||
.jsonPath("_links.env.templated").isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
|
||||
.jsonPath("_links.test.templated").isEqualTo(false).jsonPath("_links.test-part.href")
|
||||
.isNotEmpty().jsonPath("_links.test-part.templated").isEqualTo(true)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToOtherEndpointsForbidden() {
|
||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(
|
||||
Reason.INVALID_TOKEN, "invalid-token");
|
||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
||||
"invalid-token");
|
||||
willThrow(exception).given(tokenValidator).validate(any());
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isUnauthorized()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToOtherEndpointsWithRestrictedAccess() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
|
||||
.isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false)
|
||||
.jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env")
|
||||
.doesNotExist().jsonPath("_links.test").doesNotExist()
|
||||
.jsonPath("_links.test-part").doesNotExist()));
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner
|
||||
.run(withWebTestClient((client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env").doesNotExist()
|
||||
.jsonPath("_links.test").doesNotExist().jsonPath("_links.test-part").doesNotExist()));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableReactiveWebApplicationContext> withWebTestClient(
|
||||
Consumer<WebTestClient> clientConsumer) {
|
||||
return (context) -> {
|
||||
int port = ((AnnotationConfigReactiveWebServerApplicationContext) context
|
||||
.getSourceApplicationContext()).getWebServer().getPort();
|
||||
clientConsumer.accept(WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + port).build());
|
||||
int port = ((AnnotationConfigReactiveWebServerApplicationContext) context.getSourceApplicationContext())
|
||||
.getWebServer().getPort();
|
||||
clientConsumer.accept(WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -187,8 +166,7 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
|
||||
@Bean
|
||||
public CloudFoundrySecurityInterceptor interceptor() {
|
||||
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService,
|
||||
"app-id");
|
||||
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -199,28 +177,23 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
|
||||
@Bean
|
||||
public CloudFoundryWebFluxEndpointHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
|
||||
WebEndpointDiscoverer webEndpointDiscoverer,
|
||||
EndpointMediaTypes endpointMediaTypes,
|
||||
WebEndpointDiscoverer webEndpointDiscoverer, EndpointMediaTypes endpointMediaTypes,
|
||||
CloudFoundrySecurityInterceptor interceptor) {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
|
||||
return new CloudFoundryWebFluxEndpointHandlerMapping(
|
||||
new EndpointMapping("/cfApplication"),
|
||||
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes,
|
||||
corsConfiguration, interceptor,
|
||||
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"),
|
||||
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
|
||||
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebEndpointDiscoverer webEndpointDiscoverer(
|
||||
ApplicationContext applicationContext,
|
||||
public WebEndpointDiscoverer webEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
EndpointMediaTypes endpointMediaTypes) {
|
||||
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
|
||||
DefaultConversionService.getSharedInstance());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper, endpointMediaTypes, null,
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -76,17 +76,13 @@ import static org.mockito.Mockito.mock;
|
||||
public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
WebClientCustomizerConfig.class, WebClientAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebClientCustomizerConfig.class,
|
||||
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@After
|
||||
@@ -96,90 +92,67 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActive() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils
|
||||
.getField(handlerMapping, "endpointMapping");
|
||||
assertThat(endpointMapping.getPath())
|
||||
.isEqualTo("/cloudfoundryapplication");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
|
||||
"endpointMapping");
|
||||
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
|
||||
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
|
||||
.getField(handlerMapping, "corsConfiguration");
|
||||
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
|
||||
assertThat(corsConfiguration.getAllowedMethods()).containsAll(
|
||||
Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedMethods())
|
||||
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedHeaders())
|
||||
.containsAll(Arrays.asList("Authorization",
|
||||
"X-Cf-App-Instance", "Content-Type"));
|
||||
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudfoundryapplicationProducesActuatorMediaType() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
WebTestClient webTestClient = WebTestClient
|
||||
.bindToApplicationContext(context).build();
|
||||
webTestClient.get().uri("/cloudfoundryapplication").header(
|
||||
"Content-Type", ActuatorMediaType.V2_JSON + ";charset=UTF-8");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
WebTestClient webTestClient = WebTestClient.bindToApplicationContext(context).build();
|
||||
webTestClient.get().uri("/cloudfoundryapplication").header("Content-Type",
|
||||
ActuatorMediaType.V2_JSON + ";charset=UTF-8");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveSetsApplicationId() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils
|
||||
.getField(interceptor, "applicationId");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
|
||||
assertThat(applicationId).isEqualTo("my-app-id");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(interceptor, "cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils
|
||||
.getField(interceptorSecurityService, "cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl)
|
||||
.isEqualTo("https://my-cloud-controller.com");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context
|
||||
.getBean("cloudFoundryWebFluxEndpointHandlerMapping",
|
||||
CloudFoundryWebFluxEndpointHandlerMapping.class);
|
||||
Object securityInterceptor = ReflectionTestUtils
|
||||
.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(securityInterceptor, "cloudFoundrySecurityService");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context.getBean(
|
||||
"cloudFoundryWebFluxEndpointHandlerMapping",
|
||||
CloudFoundryWebFluxEndpointHandlerMapping.class);
|
||||
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
assertThat(interceptorSecurityService).isNull();
|
||||
});
|
||||
}
|
||||
@@ -187,28 +160,22 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void cloudFoundryPathsIgnoredBySpringSecurity() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
WebFilterChainProxy chainProxy = context
|
||||
.getBean(WebFilterChainProxy.class);
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
|
||||
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
|
||||
.getField(chainProxy, "filters");
|
||||
Boolean cfRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest
|
||||
.get("/cloudfoundryapplication/my-path").build()))
|
||||
.matches(MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
Boolean otherRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest
|
||||
.get("/some-other-path").build()))
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(cfRequestMatches).isTrue();
|
||||
assertThat(otherRequestMatches).isFalse();
|
||||
otherRequestMatches = filters.get(1)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest
|
||||
.get("/some-other-path").build()))
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(otherRequestMatches).isTrue();
|
||||
});
|
||||
@@ -217,34 +184,24 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformInactive() {
|
||||
this.contextRunner.run((context) -> assertThat(
|
||||
context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
|
||||
.isFalse());
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryManagementEndpointsDisabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION=---",
|
||||
"management.cloudfoundry.enabled:false")
|
||||
.run((context) -> assertThat(
|
||||
context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
|
||||
.isFalse());
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false").run(
|
||||
(context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allEndpointsAvailableUnderCloudFoundryWithoutEnablingWebIncludes() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping
|
||||
.getEndpoints();
|
||||
List<EndpointId> endpointIds = endpoints.stream()
|
||||
.map(ExposableEndpoint::getEndpointId)
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
List<EndpointId> endpointIds = endpoints.stream().map(ExposableEndpoint::getEndpointId)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(endpointIds).contains(EndpointId.of("test"));
|
||||
});
|
||||
@@ -252,112 +209,84 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void endpointPathCustomizationIsNotApplied() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping
|
||||
.getEndpoints();
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test")
|
||||
.equals(candidate.getEndpointId()))
|
||||
.findFirst().get();
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst()
|
||||
.get();
|
||||
assertThat(endpoint.getOperations()).hasSize(1);
|
||||
WebOperation operation = endpoint.getOperations().iterator().next();
|
||||
assertThat(operation.getRequestPredicate().getPath())
|
||||
.isEqualTo("test");
|
||||
assertThat(operation.getRequestPredicate().getPath()).isEqualTo("test");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
|
||||
this.contextRunner
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(
|
||||
context).getEndpoints();
|
||||
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(context).getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.iterator().next();
|
||||
assertThat(endpoint.getOperations()).hasSize(3);
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint,
|
||||
"health");
|
||||
Object invoker = ReflectionTestUtils.getField(webOperation,
|
||||
"invoker");
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
|
||||
Object invoker = ReflectionTestUtils.getField(webOperation, "invoker");
|
||||
assertThat(ReflectionTestUtils.getField(invoker, "target"))
|
||||
.isInstanceOf(
|
||||
CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
.isInstanceOf(CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipSslValidation() {
|
||||
this.contextRunner
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(interceptor, "cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils
|
||||
.getField(interceptorSecurityService, "webClient");
|
||||
webClient.get().uri("https://self-signed.badssl.com/").exchange()
|
||||
.block(Duration.ofSeconds(30));
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"webClient");
|
||||
webClient.get().uri("https://self-signed.badssl.com/").exchange().block(Duration.ofSeconds(30));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslValidationNotSkippedByDefault() {
|
||||
this.contextRunner
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(interceptor, "cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils
|
||||
.getField(interceptorSecurityService, "webClient");
|
||||
assertThatExceptionOfType(RuntimeException.class)
|
||||
.isThrownBy(() -> webClient.get()
|
||||
.uri("https://self-signed.badssl.com/").exchange()
|
||||
.block(Duration.ofSeconds(30)))
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"webClient");
|
||||
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> webClient.get()
|
||||
.uri("https://self-signed.badssl.com/").exchange().block(Duration.ofSeconds(30)))
|
||||
.withCauseInstanceOf(SSLException.class);
|
||||
});
|
||||
}
|
||||
|
||||
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(
|
||||
ApplicationContext context) {
|
||||
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(ApplicationContext context) {
|
||||
return context.getBean("cloudFoundryWebFluxEndpointHandlerMapping",
|
||||
CloudFoundryWebFluxEndpointHandlerMapping.class);
|
||||
}
|
||||
|
||||
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint,
|
||||
String requestPath) {
|
||||
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint, String requestPath) {
|
||||
for (WebOperation operation : endpoint.getOperations()) {
|
||||
if (operation.getRequestPredicate().getPath().equals(requestPath)) {
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No operation found with request path "
|
||||
+ requestPath + " from " + endpoint.getOperations());
|
||||
throw new IllegalStateException(
|
||||
"No operation found with request path " + requestPath + " from " + endpoint.getOperations());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -54,62 +54,54 @@ public class ReactiveCloudFoundrySecurityInterceptorTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
|
||||
this.securityService, "my-app-id");
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, "my-app-id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenRequestIsPreFlightShouldBeOk() {
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest
|
||||
.options("/a").header(HttpHeaders.ORIGIN, "https://example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(HttpStatus.OK))
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.options("/a").header(HttpHeaders.ORIGIN, "https://example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus()).isEqualTo(HttpStatus.OK))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenTokenIsMissingShouldReturnMissingAuthorization() {
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a").build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a").build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenTokenIsNotBearerShouldReturnMissingAuthorization() {
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest
|
||||
.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenApplicationIdIsNullShouldReturnError() {
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
|
||||
this.securityService, null);
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeErrorWith(
|
||||
(ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, null);
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenCloudFoundrySecurityServiceIsNullShouldReturnError() {
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
|
||||
"my-app-id");
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest
|
||||
.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeErrorWith(
|
||||
(ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null, "my-app-id");
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
}
|
||||
@@ -119,33 +111,25 @@ public class ReactiveCloudFoundrySecurityInterceptorTests {
|
||||
given(this.securityService.getAccessLevel(mockAccessToken(), "my-app-id"))
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.ACCESS_DENIED.getStatus()))
|
||||
.consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleSuccessfulWithFullAccess() {
|
||||
String accessToken = mockAccessToken();
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
|
||||
.willReturn(Mono.just(AccessLevel.FULL));
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(Mono.just(AccessLevel.FULL));
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
MockServerWebExchange exchange = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(exchange, "/a"))
|
||||
.consumeNextWith((response) -> {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat((AccessLevel) exchange
|
||||
.getAttribute("cloudFoundryAccessLevel"))
|
||||
.isEqualTo(AccessLevel.FULL);
|
||||
}).verifyComplete();
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(exchange, "/a")).consumeNextWith((response) -> {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat((AccessLevel) exchange.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.FULL);
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,17 +138,13 @@ public class ReactiveCloudFoundrySecurityInterceptorTests {
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
MockServerWebExchange exchange = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/info")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(exchange, "info"))
|
||||
.consumeNextWith((response) -> {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat((AccessLevel) exchange
|
||||
.getAttribute("cloudFoundryAccessLevel"))
|
||||
.isEqualTo(AccessLevel.RESTRICTED);
|
||||
}).verifyComplete();
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/info")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(exchange, "info")).consumeNextWith((response) -> {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat((AccessLevel) exchange.getAttribute("cloudFoundryAccessLevel"))
|
||||
.isEqualTo(AccessLevel.RESTRICTED);
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
private String mockAccessToken() {
|
||||
|
||||
@@ -43,8 +43,7 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
|
||||
private static final String CLOUD_CONTROLLER = "/my-cloud-controller.com";
|
||||
|
||||
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER
|
||||
+ "/v2/apps/my-app-id/permissions";
|
||||
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER + "/v2/apps/my-app-id/permissions";
|
||||
|
||||
private static final String UAA_URL = "https://my-cloud-controller.com/uaa";
|
||||
|
||||
@@ -58,8 +57,7 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
public void setup() {
|
||||
this.server = new MockWebServer();
|
||||
this.builder = WebClient.builder().baseUrl(this.server.url("/").toString());
|
||||
this.securityService = new ReactiveCloudFoundrySecurityService(this.builder,
|
||||
CLOUD_CONTROLLER, false);
|
||||
this.securityService = new ReactiveCloudFoundrySecurityService(this.builder, CLOUD_CONTROLLER, false);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -70,36 +68,25 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
public void getAccessLevelWhenSpaceDeveloperShouldReturnFull() throws Exception {
|
||||
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
|
||||
prepareResponse((response) -> response.setBody(responseBody)
|
||||
.setHeader("Content-Type", "application/json"));
|
||||
StepVerifier
|
||||
.create(this.securityService.getAccessLevel("my-access-token",
|
||||
"my-app-id"))
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel)
|
||||
.isEqualTo(AccessLevel.FULL))
|
||||
.expectComplete().verify();
|
||||
prepareResponse((response) -> response.setBody(responseBody).setHeader("Content-Type", "application/json"));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.FULL)).expectComplete()
|
||||
.verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
|
||||
.isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccessLevelWhenNotSpaceDeveloperShouldReturnRestricted()
|
||||
throws Exception {
|
||||
public void getAccessLevelWhenNotSpaceDeveloperShouldReturnRestricted() throws Exception {
|
||||
String responseBody = "{\"read_sensitive_data\": false,\"read_basic_data\": true}";
|
||||
prepareResponse((response) -> response.setBody(responseBody)
|
||||
.setHeader("Content-Type", "application/json"));
|
||||
StepVerifier
|
||||
.create(this.securityService.getAccessLevel("my-access-token",
|
||||
"my-app-id"))
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel)
|
||||
.isEqualTo(AccessLevel.RESTRICTED))
|
||||
prepareResponse((response) -> response.setBody(responseBody).setHeader("Content-Type", "application/json"));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED))
|
||||
.expectComplete().verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
|
||||
.isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
});
|
||||
}
|
||||
@@ -107,18 +94,14 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
public void getAccessLevelWhenTokenIsNotValidShouldThrowException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(401));
|
||||
StepVerifier.create(
|
||||
this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable)
|
||||
.isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(
|
||||
((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.INVALID_TOKEN);
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.INVALID_TOKEN);
|
||||
}).verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
|
||||
.isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
});
|
||||
}
|
||||
@@ -126,45 +109,35 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
public void getAccessLevelWhenForbiddenShouldThrowException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(403));
|
||||
StepVerifier.create(
|
||||
this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable)
|
||||
.isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(
|
||||
((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.ACCESS_DENIED);
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.ACCESS_DENIED);
|
||||
}).verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
|
||||
.isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccessLevelWhenCloudControllerIsNotReachableThrowsException()
|
||||
throws Exception {
|
||||
public void getAccessLevelWhenCloudControllerIsNotReachableThrowsException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(500));
|
||||
StepVerifier.create(
|
||||
this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable)
|
||||
.isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(
|
||||
((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
}).verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
|
||||
.isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA()
|
||||
throws Exception {
|
||||
public void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA() throws Exception {
|
||||
String tokenKeyValue = "-----BEGIN PUBLIC KEY-----\n"
|
||||
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\n"
|
||||
+ "rn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\n"
|
||||
@@ -177,20 +150,17 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
response.setBody("{\"token_endpoint\":\"/my-uaa.com\"}");
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \""
|
||||
+ tokenKeyValue.replace("\n", "\\n") + "\"} ]}";
|
||||
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \"" + tokenKeyValue.replace("\n", "\\n")
|
||||
+ "\"} ]}";
|
||||
prepareResponse((response) -> {
|
||||
response.setBody(responseBody);
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
StepVerifier.create(this.securityService.fetchTokenKeys())
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys.get("test-key"))
|
||||
.isEqualTo(tokenKeyValue))
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys.get("test-key")).isEqualTo(tokenKeyValue))
|
||||
.expectComplete().verify();
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo("/my-uaa.com/token_keys"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -205,12 +175,9 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
StepVerifier.create(this.securityService.fetchTokenKeys())
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys).hasSize(0))
|
||||
.expectComplete().verify();
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo("/my-uaa.com/token_keys"));
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys).hasSize(0)).expectComplete().verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -221,14 +188,12 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
});
|
||||
prepareResponse((response) -> response.setResponseCode(500));
|
||||
StepVerifier.create(this.securityService.fetchTokenKeys())
|
||||
.consumeErrorWith((throwable) -> assertThat(
|
||||
((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.consumeErrorWith(
|
||||
(throwable) -> assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo("/my-uaa.com/token_keys"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -238,29 +203,22 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
StepVerifier.create(this.securityService.getUaaUrl())
|
||||
.consumeNextWith((uaaUrl) -> assertThat(uaaUrl).isEqualTo(UAA_URL))
|
||||
.expectComplete().verify();
|
||||
.consumeNextWith((uaaUrl) -> assertThat(uaaUrl).isEqualTo(UAA_URL)).expectComplete().verify();
|
||||
// this.securityService.getUaaUrl().block(); //FIXME subscribe again to check that
|
||||
// it isn't called again
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo(CLOUD_CONTROLLER + "/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER + "/info"));
|
||||
expectRequestCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException()
|
||||
throws Exception {
|
||||
public void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(500));
|
||||
StepVerifier.create(this.securityService.getUaaUrl())
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable)
|
||||
.isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(
|
||||
((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
}).verify();
|
||||
expectRequest((request) -> assertThat(request.getPath())
|
||||
.isEqualTo(CLOUD_CONTROLLER + "/info"));
|
||||
StepVerifier.create(this.securityService.getUaaUrl()).consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
}).verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER + "/info"));
|
||||
}
|
||||
|
||||
private void prepareResponse(Consumer<MockResponse> consumer) {
|
||||
@@ -269,8 +227,7 @@ public class ReactiveCloudFoundrySecurityServiceTests {
|
||||
this.server.enqueue(response);
|
||||
}
|
||||
|
||||
private void expectRequest(Consumer<RecordedRequest> consumer)
|
||||
throws InterruptedException {
|
||||
private void expectRequest(Consumer<RecordedRequest> consumer) throws InterruptedException {
|
||||
consumer.accept(this.server.takeRequest());
|
||||
}
|
||||
|
||||
|
||||
@@ -92,90 +92,66 @@ public class ReactiveTokenValidatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException()
|
||||
throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||
.of(Mono.just(VALID_KEYS));
|
||||
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException() throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
||||
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", VALID_KEYS);
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"invalid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_KEY_ID);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
|
||||
}).verify();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
|
||||
VALID_KEYS);
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt()
|
||||
throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||
.of(Mono.just(VALID_KEYS));
|
||||
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys",
|
||||
INVALID_KEYS);
|
||||
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt() throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
||||
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", INVALID_KEYS);
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
|
||||
VALID_KEYS);
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenCacheIsEmptyShouldFetchTokenKeys() throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||
.of(Mono.just(VALID_KEYS));
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
|
||||
VALID_KEYS);
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenCacheEmptyAndInvalidKeyShouldThrowException()
|
||||
throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||
.of(Mono.just(VALID_KEYS));
|
||||
public void validateTokenWhenCacheEmptyAndInvalidKeyShouldThrowException() throws Exception {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"invalid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_KEY_ID);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
|
||||
}).verify();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
|
||||
VALID_KEYS);
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
|
||||
@@ -184,13 +160,11 @@ public class ReactiveTokenValidatorTests {
|
||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.empty();
|
||||
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", VALID_KEYS);
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
fetchTokenKeys.assertWasNotSubscribed();
|
||||
}
|
||||
@@ -199,35 +173,28 @@ public class ReactiveTokenValidatorTests {
|
||||
public void validateTokenWhenSignatureInvalidShouldThrowException() throws Exception {
|
||||
Map<String, String> KEYS = Collections.singletonMap("valid-key", INVALID_KEY);
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(KEYS));
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_SIGNATURE);
|
||||
}).verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException()
|
||||
throws Exception {
|
||||
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException() throws Exception {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{ \"alg\": \"HS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM);
|
||||
}).verify();
|
||||
@@ -236,53 +203,41 @@ public class ReactiveTokenValidatorTests {
|
||||
@Test
|
||||
public void validateTokenWhenExpiredShouldThrowException() throws Exception {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"jti\": \"0236399c350c47f3ae77e67a75e75e7d\", \"exp\": 1477509977, \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.TOKEN_EXPIRED);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.TOKEN_EXPIRED);
|
||||
}).verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenIssuerIsNotValidShouldThrowException() throws Exception {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("https://other-uaa.com"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("https://other-uaa.com"));
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\", \"scope\": [\"actuator.read\"]}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_ISSUER);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_ISSUER);
|
||||
}).verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenAudienceIsNotValidShouldThrowException()
|
||||
throws Exception {
|
||||
public void validateTokenWhenAudienceIsNotValidShouldThrowException() throws Exception {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
|
||||
given(this.securityService.getUaaUrl())
|
||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(
|
||||
CloudFoundryAuthorizationException.class);
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_AUDIENCE);
|
||||
}).verify();
|
||||
@@ -292,17 +247,15 @@ public class ReactiveTokenValidatorTests {
|
||||
PrivateKey privateKey = getPrivateKey();
|
||||
Signature signature = Signature.getInstance("SHA256WithRSA");
|
||||
signature.initSign(privateKey);
|
||||
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header),
|
||||
Base64Utils.encode(claims));
|
||||
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encode(claims));
|
||||
signature.update(content);
|
||||
byte[] crypto = signature.sign();
|
||||
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header),
|
||||
Base64Utils.encodeUrlSafe(claims), Base64Utils.encodeUrlSafe(crypto));
|
||||
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encodeUrlSafe(claims),
|
||||
Base64Utils.encodeUrlSafe(crypto));
|
||||
return new String(token, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private PrivateKey getPrivateKey()
|
||||
throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
private PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
String signingKey = "-----BEGIN PRIVATE KEY-----\n"
|
||||
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSbn2Xa72IOcxu\n"
|
||||
+ "tcd+qQ6ufZ1VDe98EmpwO4VQrTd37U9kZtWU0KqeSkgnyzIWmlbyWOdbB4/v4uJa\n"
|
||||
|
||||
@@ -69,108 +69,77 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
public class CloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
CloudFoundryActuatorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActive() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils
|
||||
.getField(handlerMapping, "endpointMapping");
|
||||
assertThat(endpointMapping.getPath())
|
||||
.isEqualTo("/cloudfoundryapplication");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
|
||||
"endpointMapping");
|
||||
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
|
||||
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
|
||||
.getField(handlerMapping, "corsConfiguration");
|
||||
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
|
||||
assertThat(corsConfiguration.getAllowedMethods()).containsAll(
|
||||
Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedMethods())
|
||||
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedHeaders())
|
||||
.containsAll(Arrays.asList("Authorization",
|
||||
"X-Cf-App-Instance", "Content-Type"));
|
||||
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudfoundryapplicationProducesActuatorMediaType() throws Exception {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||
mockMvc.perform(get("/cloudfoundryapplication"))
|
||||
.andExpect(header().string("Content-Type",
|
||||
ActuatorMediaType.V2_JSON + ";charset=UTF-8"));
|
||||
.andExpect(header().string("Content-Type", ActuatorMediaType.V2_JSON + ";charset=UTF-8"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveSetsApplicationId() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils
|
||||
.getField(interceptor, "applicationId");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
|
||||
assertThat(applicationId).isEqualTo("my-app-id");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(interceptor, "cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils
|
||||
.getField(interceptorSecurityService, "cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl)
|
||||
.isEqualTo("https://my-cloud-controller.com");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipSslValidation() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(interceptor, "cloudFoundrySecurityService");
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
|
||||
.getField(interceptorSecurityService, "restTemplate");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
});
|
||||
@@ -178,26 +147,23 @@ public class CloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Object securityInterceptor = ReflectionTestUtils
|
||||
.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils
|
||||
.getField(securityInterceptor, "cloudFoundrySecurityService");
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
assertThat(interceptorSecurityService).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPathsIgnoredBySpringSecurity() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id").run((context) -> {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
FilterChainProxy securityFilterChain = (FilterChainProxy) context
|
||||
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
SecurityFilterChain chain = securityFilterChain.getFilterChains()
|
||||
.get(0);
|
||||
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/cloudfoundryapplication/my-path");
|
||||
assertThat(chain.getFilters()).isEmpty();
|
||||
@@ -210,72 +176,54 @@ public class CloudFoundryActuatorAutoConfigurationTests {
|
||||
@Test
|
||||
public void cloudFoundryPlatformInactive() {
|
||||
this.contextRunner.withPropertyValues()
|
||||
.run((context) -> assertThat(context
|
||||
.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
|
||||
.isFalse());
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
|
||||
.isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryManagementEndpointsDisabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION=---",
|
||||
"management.cloudfoundry.enabled:false")
|
||||
.run((context) -> assertThat(
|
||||
context.containsBean("cloudFoundryEndpointHandlerMapping"))
|
||||
.isFalse());
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false")
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryEndpointHandlerMapping")).isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allEndpointsAvailableUnderCloudFoundryWithoutExposeAllOnWeb() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping
|
||||
.getEndpoints();
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
assertThat(endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test")
|
||||
.equals(candidate.getEndpointId()))
|
||||
.findFirst()).isNotEmpty();
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst())
|
||||
.isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointPathCustomizationIsNotApplied() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.endpoints.web.path-mapping.test=custom")
|
||||
.withUserConfiguration(TestConfiguration.class).run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
|
||||
context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping
|
||||
.getEndpoints();
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test")
|
||||
.equals(candidate.getEndpointId()))
|
||||
.findFirst().get();
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst()
|
||||
.get();
|
||||
Collection<WebOperation> operations = endpoint.getOperations();
|
||||
assertThat(operations).hasSize(1);
|
||||
assertThat(
|
||||
operations.iterator().next().getRequestPredicate().getPath())
|
||||
.isEqualTo("test");
|
||||
assertThat(operations.iterator().next().getRequestPredicate().getPath()).isEqualTo("test");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id",
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class))
|
||||
.withConfiguration(AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
Collection<ExposableWebEndpoint> endpoints = context
|
||||
.getBean("cloudFoundryWebEndpointServletHandlerMapping",
|
||||
@@ -283,30 +231,26 @@ public class CloudFoundryActuatorAutoConfigurationTests {
|
||||
.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.iterator().next();
|
||||
assertThat(endpoint.getOperations()).hasSize(3);
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint,
|
||||
"health");
|
||||
Object invoker = ReflectionTestUtils.getField(webOperation,
|
||||
"invoker");
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
|
||||
Object invoker = ReflectionTestUtils.getField(webOperation, "invoker");
|
||||
assertThat(ReflectionTestUtils.getField(invoker, "target"))
|
||||
.isInstanceOf(CloudFoundryHealthEndpointWebExtension.class);
|
||||
});
|
||||
}
|
||||
|
||||
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(
|
||||
ApplicationContext context) {
|
||||
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(ApplicationContext context) {
|
||||
return context.getBean("cloudFoundryWebEndpointServletHandlerMapping",
|
||||
CloudFoundryWebEndpointServletHandlerMapping.class);
|
||||
}
|
||||
|
||||
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint,
|
||||
String requestPath) {
|
||||
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint, String requestPath) {
|
||||
for (WebOperation operation : endpoint.getOperations()) {
|
||||
if (operation.getRequestPredicate().getPath().equals(requestPath)) {
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No operation found with request path "
|
||||
+ requestPath + " from " + endpoint.getOperations());
|
||||
throw new IllegalStateException(
|
||||
"No operation found with request path " + requestPath + " from " + endpoint.getOperations());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,18 +45,13 @@ public class CloudFoundryHealthEndpointWebExtensionTests {
|
||||
|
||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class,
|
||||
CloudFoundryActuatorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void healthDetailsAlwaysPresent() {
|
||||
|
||||
@@ -67,92 +67,74 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
|
||||
private static TokenValidator tokenValidator = mock(TokenValidator.class);
|
||||
|
||||
private static CloudFoundrySecurityService securityService = mock(
|
||||
CloudFoundrySecurityService.class);
|
||||
private static CloudFoundrySecurityService securityService = mock(CloudFoundrySecurityService.class);
|
||||
|
||||
@Test
|
||||
public void operationWithSecurityInterceptorForbidden() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(AccessLevel.RESTRICTED);
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN));
|
||||
(client) -> client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
|
||||
.isEqualTo(HttpStatus.FORBIDDEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void operationWithSecurityInterceptorSuccess() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(AccessLevel.FULL);
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.OK));
|
||||
(client) -> client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
|
||||
.isEqualTo(HttpStatus.OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseToOptionsRequestIncludesCorsHeaders() {
|
||||
load(TestEndpointConfiguration.class, (client) -> client.options()
|
||||
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Access-Control-Request-Method", "POST")
|
||||
.header("Origin", "https://example.com").exchange().expectStatus().isOk()
|
||||
.expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com")
|
||||
.expectHeader().valueEquals("Access-Control-Allow-Methods", "GET,POST"));
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.options().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Access-Control-Request-Method", "POST").header("Origin", "https://example.com")
|
||||
.exchange().expectStatus().isOk().expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com").expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Methods", "GET,POST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToOtherEndpointsWithFullAccess() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(AccessLevel.FULL);
|
||||
load(TestEndpointConfiguration.class, (client) -> client.get()
|
||||
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
|
||||
.isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false)
|
||||
.jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false)
|
||||
.jsonPath("_links.env.href").isNotEmpty().jsonPath("_links.env.templated")
|
||||
.isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
|
||||
.jsonPath("_links.test.templated").isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href").isNotEmpty()
|
||||
.jsonPath("_links.test-part.templated").isEqualTo(true));
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env.href").isNotEmpty()
|
||||
.jsonPath("_links.env.templated").isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
|
||||
.jsonPath("_links.test.templated").isEqualTo(false).jsonPath("_links.test-part.href")
|
||||
.isNotEmpty().jsonPath("_links.test-part.templated").isEqualTo(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToOtherEndpointsForbidden() {
|
||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(
|
||||
Reason.INVALID_TOKEN, "invalid-token");
|
||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
||||
"invalid-token");
|
||||
willThrow(exception).given(tokenValidator).validate(any());
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isUnauthorized());
|
||||
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
|
||||
.isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksToOtherEndpointsWithRestrictedAccess() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id")))
|
||||
.willReturn(AccessLevel.RESTRICTED);
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
|
||||
.isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false)
|
||||
.jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false)
|
||||
.jsonPath("_links.env").doesNotExist().jsonPath("_links.test")
|
||||
.doesNotExist().jsonPath("_links.test-part").doesNotExist());
|
||||
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env").doesNotExist()
|
||||
.jsonPath("_links.test").doesNotExist().jsonPath("_links.test-part").doesNotExist());
|
||||
}
|
||||
|
||||
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(
|
||||
Class<?>... config) {
|
||||
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(Class<?>... config) {
|
||||
return new AnnotationConfigServletWebServerApplicationContext(config);
|
||||
}
|
||||
|
||||
@@ -161,13 +143,12 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
}
|
||||
|
||||
private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) {
|
||||
BiConsumer<ApplicationContext, WebTestClient> consumer = (context,
|
||||
client) -> clientConsumer.accept(client);
|
||||
AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(
|
||||
configuration, CloudFoundryMvcConfiguration.class);
|
||||
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client);
|
||||
AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(configuration,
|
||||
CloudFoundryMvcConfiguration.class);
|
||||
try {
|
||||
consumer.accept(context, WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + getPort(context)).build());
|
||||
consumer.accept(context,
|
||||
WebTestClient.bindToServer().baseUrl("http://localhost:" + getPort(context)).build());
|
||||
}
|
||||
finally {
|
||||
context.close();
|
||||
@@ -186,8 +167,7 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
|
||||
@Bean
|
||||
public CloudFoundrySecurityInterceptor interceptor() {
|
||||
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService,
|
||||
"app-id");
|
||||
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -198,28 +178,23 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
|
||||
@Bean
|
||||
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
|
||||
WebEndpointDiscoverer webEndpointDiscoverer,
|
||||
EndpointMediaTypes endpointMediaTypes,
|
||||
WebEndpointDiscoverer webEndpointDiscoverer, EndpointMediaTypes endpointMediaTypes,
|
||||
CloudFoundrySecurityInterceptor interceptor) {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
|
||||
return new CloudFoundryWebEndpointServletHandlerMapping(
|
||||
new EndpointMapping("/cfApplication"),
|
||||
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes,
|
||||
corsConfiguration, interceptor,
|
||||
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cfApplication"),
|
||||
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
|
||||
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebEndpointDiscoverer webEndpointDiscoverer(
|
||||
ApplicationContext applicationContext,
|
||||
public WebEndpointDiscoverer webEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
EndpointMediaTypes endpointMediaTypes) {
|
||||
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
|
||||
DefaultConversionService.getSharedInstance());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
|
||||
endpointMediaTypes, null, Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
return new WebEndpointDiscoverer(applicationContext, parameterMapper, endpointMediaTypes, null,
|
||||
Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -56,8 +56,7 @@ public class CloudFoundrySecurityInterceptorTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
|
||||
this.securityService, "my-app-id");
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, "my-app-id");
|
||||
this.request = new MockHttpServletRequest();
|
||||
}
|
||||
|
||||
@@ -66,58 +65,45 @@ public class CloudFoundrySecurityInterceptorTests {
|
||||
this.request.setMethod("OPTIONS");
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "https://example.com");
|
||||
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenTokenIsMissingShouldReturnFalse() {
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenTokenIsNotBearerShouldReturnFalse() {
|
||||
this.request.addHeader("Authorization", mockAccessToken());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenApplicationIdIsNullShouldReturnFalse() {
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
|
||||
this.securityService, null);
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, null);
|
||||
this.request.addHeader("Authorization", "bearer " + mockAccessToken());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenCloudFoundrySecurityServiceIsNullShouldReturnFalse() {
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
|
||||
"my-app-id");
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null, "my-app-id");
|
||||
this.request.addHeader("Authorization", "bearer " + mockAccessToken());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
assertThat(response.getStatus())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleWhenAccessIsNotAllowedShouldReturnFalse() {
|
||||
String accessToken = mockAccessToken();
|
||||
this.request.addHeader("Authorization", "bearer " + accessToken);
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
|
||||
.willReturn(AccessLevel.RESTRICTED);
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(AccessLevel.RESTRICTED);
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus());
|
||||
}
|
||||
|
||||
@@ -125,34 +111,28 @@ public class CloudFoundrySecurityInterceptorTests {
|
||||
public void preHandleSuccessfulWithFullAccess() {
|
||||
String accessToken = mockAccessToken();
|
||||
this.request.addHeader("Authorization", "Bearer " + accessToken);
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
|
||||
.willReturn(AccessLevel.FULL);
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("test"));
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(AccessLevel.FULL);
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
|
||||
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
|
||||
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
|
||||
Token token = tokenArgumentCaptor.getValue();
|
||||
assertThat(token.toString()).isEqualTo(accessToken);
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(this.request.getAttribute("cloudFoundryAccessLevel"))
|
||||
.isEqualTo(AccessLevel.FULL);
|
||||
assertThat(this.request.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.FULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preHandleSuccessfulWithRestrictedAccess() {
|
||||
String accessToken = mockAccessToken();
|
||||
this.request.addHeader("Authorization", "Bearer " + accessToken);
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
|
||||
.willReturn(AccessLevel.RESTRICTED);
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request,
|
||||
EndpointId.of("info"));
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(AccessLevel.RESTRICTED);
|
||||
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("info"));
|
||||
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
|
||||
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
|
||||
Token token = tokenArgumentCaptor.getValue();
|
||||
assertThat(token.toString()).isEqualTo(accessToken);
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(this.request.getAttribute("cloudFoundryAccessLevel"))
|
||||
.isEqualTo(AccessLevel.RESTRICTED);
|
||||
assertThat(this.request.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.RESTRICTED);
|
||||
}
|
||||
|
||||
private String mockAccessToken() {
|
||||
|
||||
@@ -51,8 +51,7 @@ public class CloudFoundrySecurityServiceTests {
|
||||
|
||||
private static final String CLOUD_CONTROLLER = "https://my-cloud-controller.com";
|
||||
|
||||
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER
|
||||
+ "/v2/apps/my-app-id/permissions";
|
||||
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER + "/v2/apps/my-app-id/permissions";
|
||||
|
||||
private static final String UAA_URL = "https://my-uaa.com";
|
||||
|
||||
@@ -64,31 +63,24 @@ public class CloudFoundrySecurityServiceTests {
|
||||
public void setup() {
|
||||
MockServerRestTemplateCustomizer mockServerCustomizer = new MockServerRestTemplateCustomizer();
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder(mockServerCustomizer);
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||
false);
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER, false);
|
||||
this.server = mockServerCustomizer.getServer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipSslValidationWhenTrue() {
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder();
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||
true);
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
|
||||
.getField(this.securityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER, true);
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(this.securityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory()).isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNotskipSslValidationWhenFalse() {
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder();
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||
false);
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
|
||||
.getField(this.securityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isNotInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER, false);
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(this.securityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory()).isNotInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,8 +89,7 @@ public class CloudFoundrySecurityServiceTests {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token",
|
||||
"my-app-id");
|
||||
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token", "my-app-id");
|
||||
this.server.verify();
|
||||
assertThat(accessLevel).isEqualTo(AccessLevel.FULL);
|
||||
}
|
||||
@@ -109,8 +100,7 @@ public class CloudFoundrySecurityServiceTests {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token",
|
||||
"my-app-id");
|
||||
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token", "my-app-id");
|
||||
this.server.verify();
|
||||
assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED);
|
||||
}
|
||||
@@ -118,10 +108,9 @@ public class CloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
public void getAccessLevelWhenTokenIsNotValidShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withUnauthorizedRequest());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.andExpect(header("Authorization", "bearer my-access-token")).andRespond(withUnauthorizedRequest());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@@ -130,26 +119,24 @@ public class CloudFoundrySecurityServiceTests {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withStatus(HttpStatus.FORBIDDEN));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.ACCESS_DENIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccessLevelWhenCloudControllerIsNotReachableThrowsException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.andExpect(header("Authorization", "bearer my-access-token")).andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"https://my-uaa.com\"}",
|
||||
MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"https://my-uaa.com\"}", MediaType.APPLICATION_JSON));
|
||||
String tokenKeyValue = "-----BEGIN PUBLIC KEY-----\n"
|
||||
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\n"
|
||||
+ "rn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\n"
|
||||
@@ -158,8 +145,8 @@ public class CloudFoundrySecurityServiceTests {
|
||||
+ "kqwIn7Glry9n9Suxygbf8g5AzpWcusZgDLIIZ7JTUldBb8qU2a0Dl4mvLZOn4wPo\n"
|
||||
+ "jfj9Cw2QICsc5+Pwf21fP+hzf+1WSRHbnYv8uanRO0gZ8ekGaghM/2H6gqJbo2nI\n"
|
||||
+ "JwIDAQAB\n-----END PUBLIC KEY-----";
|
||||
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \""
|
||||
+ tokenKeyValue.replace("\n", "\\n") + "\"} ]}";
|
||||
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \"" + tokenKeyValue.replace("\n", "\\n")
|
||||
+ "\"} ]}";
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
Map<String, String> tokenKeys = this.securityService.fetchTokenKeys();
|
||||
@@ -169,8 +156,8 @@ public class CloudFoundrySecurityServiceTests {
|
||||
|
||||
@Test
|
||||
public void fetchTokenKeysWhenNoKeysReturnedFromUAA() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withSuccess(
|
||||
"{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
String responseBody = "{\"keys\": []}";
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
@@ -181,10 +168,9 @@ public class CloudFoundrySecurityServiceTests {
|
||||
|
||||
@Test
|
||||
public void fetchTokenKeysWhenUnsuccessfulShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withSuccess(
|
||||
"{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys"))
|
||||
.andRespond(withServerError());
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys")).andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.fetchTokenKeys())
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
@@ -192,8 +178,8 @@ public class CloudFoundrySecurityServiceTests {
|
||||
|
||||
@Test
|
||||
public void getUaaUrlShouldCallCloudControllerInfoOnlyOnce() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withSuccess(
|
||||
"{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
String uaaUrl = this.securityService.getUaaUrl();
|
||||
this.server.verify();
|
||||
assertThat(uaaUrl).isEqualTo(UAA_URL);
|
||||
@@ -204,15 +190,13 @@ public class CloudFoundrySecurityServiceTests {
|
||||
|
||||
@Test
|
||||
public void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withServerError());
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getUaaUrl())
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
}
|
||||
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(
|
||||
Reason reason) {
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
|
||||
return (ex) -> assertThat(ex.getReason()).isEqualTo(reason);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,8 +54,7 @@ public class SkipSslVerificationHttpRequestFactoryTests {
|
||||
SkipSslVerificationHttpRequestFactory requestFactory = new SkipSslVerificationHttpRequestFactory();
|
||||
RestTemplate restTemplate = new RestTemplate(requestFactory);
|
||||
RestTemplate otherRestTemplate = new RestTemplate();
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity(httpsUrl,
|
||||
String.class);
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity(httpsUrl, String.class);
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThatExceptionOfType(ResourceAccessException.class)
|
||||
.isThrownBy(() -> otherRestTemplate.getForEntity(httpsUrl, String.class))
|
||||
@@ -65,8 +64,7 @@ public class SkipSslVerificationHttpRequestFactoryTests {
|
||||
private String getHttpsUrl() {
|
||||
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
|
||||
factory.setSsl(getSsl("password", "classpath:test.jks"));
|
||||
this.webServer = factory.getWebServer(
|
||||
new ServletRegistrationBean<>(new ExampleServlet(), "/hello"));
|
||||
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(), "/hello"));
|
||||
this.webServer.start();
|
||||
return "https://localhost:" + this.webServer.getPort() + "/hello";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,11 +79,9 @@ public class TokenValidatorTests {
|
||||
+ "r3F7aM9YpErzeYLrl0GhQr9BVJxOvXcVd4kmY+XkiCcrkyS1cnghnllh+LCwQu1s\n"
|
||||
+ "YwIDAQAB\n-----END PUBLIC KEY-----";
|
||||
|
||||
private static final Map<String, String> INVALID_KEYS = Collections
|
||||
.singletonMap("invalid-key", INVALID_KEY);
|
||||
private static final Map<String, String> INVALID_KEYS = Collections.singletonMap("invalid-key", INVALID_KEY);
|
||||
|
||||
private static final Map<String, String> VALID_KEYS = Collections
|
||||
.singletonMap("valid-key", VALID_KEY);
|
||||
private static final Map<String, String> VALID_KEYS = Collections.singletonMap("valid-key", VALID_KEY);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -92,28 +90,24 @@ public class TokenValidatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException()
|
||||
throws Exception {
|
||||
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException() throws Exception {
|
||||
ReflectionTestUtils.setField(this.tokenValidator, "tokenKeys", INVALID_KEYS);
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(INVALID_KEYS);
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_KEY_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt()
|
||||
throws Exception {
|
||||
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt() throws Exception {
|
||||
ReflectionTestUtils.setField(this.tokenValidator, "tokenKeys", INVALID_KEYS);
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
|
||||
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes())));
|
||||
this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes())));
|
||||
verify(this.securityService).fetchTokenKeys();
|
||||
}
|
||||
|
||||
@@ -123,8 +117,7 @@ public class TokenValidatorTests {
|
||||
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes())));
|
||||
this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes())));
|
||||
verify(this.securityService).fetchTokenKeys();
|
||||
}
|
||||
|
||||
@@ -134,8 +127,7 @@ public class TokenValidatorTests {
|
||||
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes())));
|
||||
this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes())));
|
||||
verify(this.securityService, Mockito.never()).fetchTokenKeys();
|
||||
}
|
||||
|
||||
@@ -146,21 +138,18 @@ public class TokenValidatorTests {
|
||||
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_SIGNATURE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException()
|
||||
throws Exception {
|
||||
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException() throws Exception {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
|
||||
String header = "{ \"alg\": \"HS256\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM));
|
||||
}
|
||||
|
||||
@@ -170,9 +159,8 @@ public class TokenValidatorTests {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"jti\": \"0236399c350c47f3ae77e67a75e75e7d\", \"exp\": 1477509977, \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.TOKEN_EXPIRED));
|
||||
}
|
||||
|
||||
@@ -182,22 +170,19 @@ public class TokenValidatorTests {
|
||||
given(this.securityService.getUaaUrl()).willReturn("https://other-uaa.com");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\", \"scope\": [\"actuator.read\"]}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_ISSUER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenWhenAudienceIsNotValidShouldThrowException()
|
||||
throws Exception {
|
||||
public void validateTokenWhenAudienceIsNotValidShouldThrowException() throws Exception {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
|
||||
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.tokenValidator.validate(
|
||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_AUDIENCE));
|
||||
}
|
||||
|
||||
@@ -205,17 +190,15 @@ public class TokenValidatorTests {
|
||||
PrivateKey privateKey = getPrivateKey();
|
||||
Signature signature = Signature.getInstance("SHA256WithRSA");
|
||||
signature.initSign(privateKey);
|
||||
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header),
|
||||
Base64Utils.encode(claims));
|
||||
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encode(claims));
|
||||
signature.update(content);
|
||||
byte[] crypto = signature.sign();
|
||||
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header),
|
||||
Base64Utils.encodeUrlSafe(claims), Base64Utils.encodeUrlSafe(crypto));
|
||||
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encodeUrlSafe(claims),
|
||||
Base64Utils.encodeUrlSafe(crypto));
|
||||
return new String(token, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private PrivateKey getPrivateKey()
|
||||
throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
private PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
String signingKey = "-----BEGIN PRIVATE KEY-----\n"
|
||||
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSbn2Xa72IOcxu\n"
|
||||
+ "tcd+qQ6ufZ1VDe98EmpwO4VQrTd37U9kZtWU0KqeSkgnyzIWmlbyWOdbB4/v4uJa\n"
|
||||
@@ -263,8 +246,7 @@ public class TokenValidatorTests {
|
||||
return result.toByteArray();
|
||||
}
|
||||
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(
|
||||
Reason reason) {
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
|
||||
return (ex) -> assertThat(ex.getReason()).isEqualTo(reason);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,21 +31,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class ConditionsReportEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations
|
||||
.of(ConditionsReportEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ConditionsReportEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ConditionsReportEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ConditionsReportEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.conditions.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ConditionsReportEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.conditions.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConditionsReportEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,17 +47,14 @@ public class ConditionsReportEndpointTests {
|
||||
|
||||
@Test
|
||||
public void invoke() {
|
||||
new ApplicationContextRunner().withUserConfiguration(Config.class)
|
||||
.run((context) -> {
|
||||
ContextConditionEvaluation report = context
|
||||
.getBean(ConditionsReportEndpoint.class)
|
||||
.applicationConditionEvaluation().getContexts()
|
||||
.get(context.getId());
|
||||
assertThat(report.getPositiveMatches()).isEmpty();
|
||||
assertThat(report.getNegativeMatches()).containsKey("a");
|
||||
assertThat(report.getUnconditionalClasses()).contains("b");
|
||||
assertThat(report.getExclusions()).contains("com.foo.Bar");
|
||||
});
|
||||
new ApplicationContextRunner().withUserConfiguration(Config.class).run((context) -> {
|
||||
ContextConditionEvaluation report = context.getBean(ConditionsReportEndpoint.class)
|
||||
.applicationConditionEvaluation().getContexts().get(context.getId());
|
||||
assertThat(report.getPositiveMatches()).isEmpty();
|
||||
assertThat(report.getNegativeMatches()).containsKey("a");
|
||||
assertThat(report.getUnconditionalClasses()).contains("b");
|
||||
assertThat(report.getExclusions()).contains("com.foo.Bar");
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -72,11 +69,9 @@ public class ConditionsReportEndpointTests {
|
||||
|
||||
@PostConstruct
|
||||
public void setupAutoConfigurationReport() {
|
||||
ConditionEvaluationReport report = ConditionEvaluationReport
|
||||
.get(this.context.getBeanFactory());
|
||||
ConditionEvaluationReport report = ConditionEvaluationReport.get(this.context.getBeanFactory());
|
||||
report.recordEvaluationCandidates(Arrays.asList("a", "b"));
|
||||
report.recordConditionEvaluation("a", mock(Condition.class),
|
||||
mock(ConditionOutcome.class));
|
||||
report.recordConditionEvaluation("a", mock(Condition.class), mock(ConditionOutcome.class));
|
||||
report.recordExclusions(Collections.singletonList("com.foo.Bar"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,22 +32,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class ShutdownEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(ShutdownEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ShutdownEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:true")
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ShutdownEndpoint.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ShutdownEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.shutdown.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ShutdownEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ShutdownEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,42 +41,35 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations
|
||||
.of(ConfigurationPropertiesReportEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ConfigurationPropertiesReportEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.run(validateTestProperties("******", "654321"));
|
||||
this.contextRunner.withUserConfiguration(Config.class).run(validateTestProperties("******", "654321"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.configprops.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.configprops.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keysToSanitizeCanBeConfiguredViaTheEnvironment() {
|
||||
this.contextRunner.withUserConfiguration(Config.class).withPropertyValues(
|
||||
"management.endpoint.configprops.keys-to-sanitize: .*pass.*, property")
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("management.endpoint.configprops.keys-to-sanitize: .*pass.*, property")
|
||||
.run(validateTestProperties("******", "******"));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableApplicationContext> validateTestProperties(
|
||||
String dbPassword, String myTestProperty) {
|
||||
private ContextConsumer<AssertableApplicationContext> validateTestProperties(String dbPassword,
|
||||
String myTestProperty) {
|
||||
return (context) -> {
|
||||
assertThat(context)
|
||||
.hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ApplicationConfigurationProperties properties = endpoint
|
||||
.configurationProperties();
|
||||
Map<String, Object> nestedProperties = properties.getContexts()
|
||||
.get(context.getId()).getBeans().get("testProperties")
|
||||
.getProperties();
|
||||
ApplicationConfigurationProperties properties = endpoint.configurationProperties();
|
||||
Map<String, Object> nestedProperties = properties.getContexts().get(context.getId()).getBeans()
|
||||
.get("testProperties").getProperties();
|
||||
assertThat(nestedProperties).isNotNull();
|
||||
assertThat(nestedProperties.get("dbPassword")).isEqualTo(dbPassword);
|
||||
assertThat(nestedProperties.get("myTestProperty")).isEqualTo(myTestProperty);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,14 +39,12 @@ import static org.mockito.Mockito.mock;
|
||||
public class CouchbaseHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(CouchbaseMockConfiguration.class).withConfiguration(
|
||||
AutoConfigurations.of(CouchbaseHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
.withUserConfiguration(CouchbaseMockConfiguration.class).withConfiguration(AutoConfigurations
|
||||
.of(CouchbaseHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(CouchbaseHealthIndicator.class)
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseHealthIndicator.class)
|
||||
.doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
@@ -54,8 +52,7 @@ public class CouchbaseHealthIndicatorAutoConfigurationTests {
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.couchbase.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(CouchbaseHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,24 +38,19 @@ import static org.mockito.Mockito.mock;
|
||||
public class CouchbaseReactiveHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(CouchbaseMockConfiguration.class)
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
CouchbaseReactiveHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
.withUserConfiguration(CouchbaseMockConfiguration.class).withConfiguration(AutoConfigurations.of(
|
||||
CouchbaseReactiveHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(CouchbaseHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(CouchbaseHealthIndicator.class).doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.couchbase.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,19 +42,15 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
public class ElasticsearchHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchAutoConfiguration.class,
|
||||
ElasticSearchClientHealthIndicatorAutoConfiguration.class,
|
||||
ElasticSearchJestHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
|
||||
.of(ElasticsearchAutoConfiguration.class, ElasticSearchClientHealthIndicatorAutoConfiguration.class,
|
||||
ElasticSearchJestHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.data.elasticsearch.cluster-nodes:localhost:0")
|
||||
this.contextRunner.withPropertyValues("spring.data.elasticsearch.cluster-nodes:localhost:0")
|
||||
.withSystemProperties("es.set.netty.runtime.available.processors=false")
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ElasticsearchHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchHealthIndicator.class)
|
||||
.doesNotHaveBean(ElasticsearchJestHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
@@ -63,18 +59,15 @@ public class ElasticsearchHealthIndicatorAutoConfigurationTests {
|
||||
public void runWhenUsingJestClientShouldCreateIndicator() {
|
||||
this.contextRunner.withUserConfiguration(JestClientConfiguration.class)
|
||||
.withSystemProperties("es.set.netty.runtime.available.processors=false")
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ElasticsearchJestHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchJestHealthIndicator.class)
|
||||
.doesNotHaveBean(ElasticsearchHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.health.elasticsearch.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ElasticsearchHealthIndicator.class)
|
||||
this.contextRunner.withPropertyValues("management.health.elasticsearch.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchHealthIndicator.class)
|
||||
.doesNotHaveBean(ElasticsearchJestHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,8 +35,7 @@ public class EndpointIdTimeToLivePropertyFunctionTests {
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
private final Function<EndpointId, Long> timeToLive = new EndpointIdTimeToLivePropertyFunction(
|
||||
this.environment);
|
||||
private final Function<EndpointId, Long> timeToLive = new EndpointIdTimeToLivePropertyFunction(this.environment);
|
||||
|
||||
@Test
|
||||
public void defaultConfiguration() {
|
||||
@@ -46,16 +45,14 @@ public class EndpointIdTimeToLivePropertyFunctionTests {
|
||||
|
||||
@Test
|
||||
public void userConfiguration() {
|
||||
this.environment.setProperty("management.endpoint.test.cache.time-to-live",
|
||||
"500");
|
||||
this.environment.setProperty("management.endpoint.test.cache.time-to-live", "500");
|
||||
Long result = this.timeToLive.apply(EndpointId.of("test"));
|
||||
assertThat(result).isEqualTo(500L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedCaseUserConfiguration() {
|
||||
this.environment.setProperty(
|
||||
"management.endpoint.another-test.cache.time-to-live", "500");
|
||||
this.environment.setProperty("management.endpoint.another-test.cache.time-to-live", "500");
|
||||
Long result = this.timeToLive.apply(EndpointId.of("anotherTest"));
|
||||
assertThat(result).isEqualTo(500L);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,32 +48,28 @@ public class ExposeExcludePropertyEndpointFilterTests {
|
||||
@Test
|
||||
public void createWhenEndpointTypeIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(null,
|
||||
new MockEnvironment(), "foo"))
|
||||
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(null, new MockEnvironment(), "foo"))
|
||||
.withMessageContaining("EndpointType must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenEnvironmentIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(
|
||||
ExposableEndpoint.class, null, "foo"))
|
||||
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(ExposableEndpoint.class, null, "foo"))
|
||||
.withMessageContaining("Environment must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenPrefixIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(
|
||||
ExposableEndpoint.class, new MockEnvironment(), null))
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new ExposeExcludePropertyEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), null))
|
||||
.withMessageContaining("Prefix must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenPrefixIsEmptyShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(
|
||||
ExposableEndpoint.class, new MockEnvironment(), ""))
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new ExposeExcludePropertyEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), ""))
|
||||
.withMessageContaining("Prefix must not be empty");
|
||||
}
|
||||
|
||||
@@ -124,8 +120,8 @@ public class ExposeExcludePropertyEndpointFilterTests {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("foo.include", "bar");
|
||||
environment.setProperty("foo.exclude", "");
|
||||
this.filter = new ExposeExcludePropertyEndpointFilter<>(
|
||||
DifferentTestExposableWebEndpoint.class, environment, "foo");
|
||||
this.filter = new ExposeExcludePropertyEndpointFilter<>(DifferentTestExposableWebEndpoint.class, environment,
|
||||
"foo");
|
||||
assertThat(match(EndpointId.of("baz"))).isTrue();
|
||||
}
|
||||
|
||||
@@ -155,8 +151,8 @@ public class ExposeExcludePropertyEndpointFilterTests {
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("foo.include", include);
|
||||
environment.setProperty("foo.exclude", exclude);
|
||||
this.filter = new ExposeExcludePropertyEndpointFilter<>(
|
||||
TestExposableWebEndpoint.class, environment, "foo", "def");
|
||||
this.filter = new ExposeExcludePropertyEndpointFilter<>(TestExposableWebEndpoint.class, environment, "foo",
|
||||
"def");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@@ -166,13 +162,11 @@ public class ExposeExcludePropertyEndpointFilterTests {
|
||||
return ((EndpointFilter) this.filter).match(endpoint);
|
||||
}
|
||||
|
||||
private abstract static class TestExposableWebEndpoint
|
||||
implements ExposableWebEndpoint {
|
||||
private abstract static class TestExposableWebEndpoint implements ExposableWebEndpoint {
|
||||
|
||||
}
|
||||
|
||||
private abstract static class DifferentTestExposableWebEndpoint
|
||||
implements ExposableWebEndpoint {
|
||||
private abstract static class DifferentTestExposableWebEndpoint implements ExposableWebEndpoint {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ public class ConditionalOnEnabledEndpointTests {
|
||||
@Test
|
||||
public void outcomeWhenEndpointEnabledPropertyIsTrueShouldMatch() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.foo.enabled=true")
|
||||
.withUserConfiguration(
|
||||
FooEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
.withUserConfiguration(FooEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasBean("foo"));
|
||||
}
|
||||
|
||||
@@ -55,51 +54,40 @@ public class ConditionalOnEnabledEndpointTests {
|
||||
|
||||
@Test
|
||||
public void outcomeWhenNoEndpointPropertyAndUserDefinedDefaultIsTrueShouldMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.enabled-by-default=true")
|
||||
.withUserConfiguration(
|
||||
FooEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
this.contextRunner.withPropertyValues("management.endpoints.enabled-by-default=true")
|
||||
.withUserConfiguration(FooEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasBean("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenNoEndpointPropertyAndUserDefinedDefaultIsFalseShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.enabled-by-default=false")
|
||||
this.contextRunner.withPropertyValues("management.endpoints.enabled-by-default=false")
|
||||
.withUserConfiguration(FooEndpointEnabledByDefaultTrueConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenNoPropertiesAndAnnotationIsEnabledByDefaultShouldMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(FooEndpointEnabledByDefaultTrueConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(FooEndpointEnabledByDefaultTrueConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasBean("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenNoPropertiesAndAnnotationIsNotEnabledByDefaultShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(
|
||||
FooEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(FooEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenNoPropertiesAndExtensionAnnotationIsEnabledByDefaultShouldMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(
|
||||
FooEndpointAndExtensionEnabledByDefaultTrueConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(FooEndpointAndExtensionEnabledByDefaultTrueConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasBean("foo").hasBean("fooExt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenNoPropertiesAndExtensionAnnotationIsNotEnabledByDefaultShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(
|
||||
FooEndpointAndExtensionEnabledByDefaultFalseConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("foo")
|
||||
.doesNotHaveBean("fooExt"));
|
||||
this.contextRunner.withUserConfiguration(FooEndpointAndExtensionEnabledByDefaultFalseConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("foo").doesNotHaveBean("fooExt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -128,31 +116,25 @@ public class ConditionalOnEnabledEndpointTests {
|
||||
|
||||
@Test
|
||||
public void outcomeWithNoReferenceShouldFail() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(
|
||||
ComponentWithNoEndpointReferenceConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure().getCause().getMessage())
|
||||
.contains(
|
||||
"No endpoint is specified and the return type of the @Bean method "
|
||||
+ "is neither an @Endpoint, nor an @EndpointExtension");
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(ComponentWithNoEndpointReferenceConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure().getCause().getMessage())
|
||||
.contains("No endpoint is specified and the return type of the @Bean method "
|
||||
+ "is neither an @Endpoint, nor an @EndpointExtension");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenEndpointEnabledPropertyIsTrueAndMixedCaseShouldMatch() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.foo-bar.enabled=true")
|
||||
.withUserConfiguration(
|
||||
FooBarEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
.withUserConfiguration(FooBarEndpointEnabledByDefaultFalseConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasBean("fooBar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void outcomeWhenEndpointEnabledPropertyIsFalseOnClassShouldNotMatch() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.foo.enabled=false")
|
||||
.withUserConfiguration(
|
||||
FooEndpointEnabledByDefaultTrueOnConfigurationConfiguration.class)
|
||||
.withUserConfiguration(FooEndpointEnabledByDefaultTrueOnConfigurationConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
|
||||
}
|
||||
|
||||
@@ -171,14 +153,12 @@ public class ConditionalOnEnabledEndpointTests {
|
||||
|
||||
}
|
||||
|
||||
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultTrue.class,
|
||||
filter = TestFilter.class)
|
||||
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultTrue.class, filter = TestFilter.class)
|
||||
static class FooEndpointExtensionEnabledByDefaultTrue {
|
||||
|
||||
}
|
||||
|
||||
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultFalse.class,
|
||||
filter = TestFilter.class)
|
||||
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultFalse.class, filter = TestFilter.class)
|
||||
static class FooEndpointExtensionEnabledByDefaultFalse {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,8 +43,7 @@ public class DefaultEndpointObjectNameFactoryTests {
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
private final JmxEndpointProperties properties = new JmxEndpointProperties(
|
||||
this.environment);
|
||||
private final JmxEndpointProperties properties = new JmxEndpointProperties(this.environment);
|
||||
|
||||
private final MBeanServer mBeanServer = mock(MBeanServer.class);
|
||||
|
||||
@@ -53,24 +52,20 @@ public class DefaultEndpointObjectNameFactoryTests {
|
||||
@Test
|
||||
public void generateObjectName() {
|
||||
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
|
||||
assertThat(objectName.toString())
|
||||
.isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
|
||||
assertThat(objectName.toString()).isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateObjectNameWithCapitalizedId() {
|
||||
ObjectName objectName = generateObjectName(
|
||||
endpoint(EndpointId.of("testEndpoint")));
|
||||
assertThat(objectName.toString())
|
||||
.isEqualTo("org.springframework.boot:type=Endpoint,name=TestEndpoint");
|
||||
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("testEndpoint")));
|
||||
assertThat(objectName.toString()).isEqualTo("org.springframework.boot:type=Endpoint,name=TestEndpoint");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateObjectNameWithCustomDomain() {
|
||||
this.properties.setDomain("com.example.acme");
|
||||
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
|
||||
assertThat(objectName.toString())
|
||||
.isEqualTo("com.example.acme:type=Endpoint,name=Test");
|
||||
assertThat(objectName.toString()).isEqualTo("com.example.acme:type=Endpoint,name=Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,8 +85,7 @@ public class DefaultEndpointObjectNameFactoryTests {
|
||||
ExposableJmxEndpoint endpoint = endpoint(EndpointId.of("test"));
|
||||
String id = ObjectUtils.getIdentityHexString(endpoint);
|
||||
ObjectName objectName = generateObjectName(endpoint);
|
||||
assertThat(objectName.toString()).isEqualTo(
|
||||
"org.springframework.boot:type=Endpoint,name=Test,identity=" + id);
|
||||
assertThat(objectName.toString()).isEqualTo("org.springframework.boot:type=Endpoint,name=Test,identity=" + id);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -99,8 +93,7 @@ public class DefaultEndpointObjectNameFactoryTests {
|
||||
public void generateObjectNameWithUniqueNamesDeprecatedPropertyMismatchMainProperty() {
|
||||
this.environment.setProperty("spring.jmx.unique-names", "false");
|
||||
this.properties.setUniqueNames(true);
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> generateObjectName(endpoint(EndpointId.of("test"))))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> generateObjectName(endpoint(EndpointId.of("test"))))
|
||||
.withMessageContaining("spring.jmx.unique-names")
|
||||
.withMessageContaining("management.endpoints.jmx.unique-names");
|
||||
}
|
||||
@@ -112,28 +105,24 @@ public class DefaultEndpointObjectNameFactoryTests {
|
||||
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
|
||||
assertThat(objectName.getKeyProperty("counter")).isEqualTo("42");
|
||||
assertThat(objectName.getKeyProperty("foo")).isEqualTo("bar");
|
||||
assertThat(objectName.toString())
|
||||
.startsWith("org.springframework.boot:type=Endpoint,name=Test,");
|
||||
assertThat(objectName.toString()).startsWith("org.springframework.boot:type=Endpoint,name=Test,");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateObjectNameWithDuplicate() throws MalformedObjectNameException {
|
||||
this.contextId = "testContext";
|
||||
given(this.mBeanServer.queryNames(
|
||||
new ObjectName("org.springframework.boot:type=Endpoint,name=Test,*"),
|
||||
null)).willReturn(
|
||||
Collections.singleton(new ObjectName(
|
||||
"org.springframework.boot:type=Endpoint,name=Test")));
|
||||
given(this.mBeanServer.queryNames(new ObjectName("org.springframework.boot:type=Endpoint,name=Test,*"), null))
|
||||
.willReturn(Collections.singleton(new ObjectName("org.springframework.boot:type=Endpoint,name=Test")));
|
||||
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
|
||||
assertThat(objectName.toString()).isEqualTo(
|
||||
"org.springframework.boot:type=Endpoint,name=Test,context=testContext");
|
||||
assertThat(objectName.toString())
|
||||
.isEqualTo("org.springframework.boot:type=Endpoint,name=Test,context=testContext");
|
||||
|
||||
}
|
||||
|
||||
private ObjectName generateObjectName(ExposableJmxEndpoint endpoint) {
|
||||
try {
|
||||
return new DefaultEndpointObjectNameFactory(this.properties, this.environment,
|
||||
this.mBeanServer, this.contextId).getObjectName(endpoint);
|
||||
return new DefaultEndpointObjectNameFactory(this.properties, this.environment, this.mBeanServer,
|
||||
this.contextId).getObjectName(endpoint);
|
||||
}
|
||||
catch (MalformedObjectNameException ex) {
|
||||
throw new AssertionError("Invalid object name", ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,34 +34,31 @@ public class MappingWebEndpointPathMapperTests {
|
||||
|
||||
@Test
|
||||
public void defaultConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.emptyMap());
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("test"))).isEqualTo("test");
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(Collections.emptyMap());
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("test"))).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.singletonMap("test", "custom"));
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("test"))).isEqualTo("custom");
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("test")))
|
||||
.isEqualTo("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedCaseDefaultConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.emptyMap());
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("testEndpoint"))).isEqualTo("testEndpoint");
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(Collections.emptyMap());
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("testEndpoint")))
|
||||
.isEqualTo("testEndpoint");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mixedCaseUserConfiguration() {
|
||||
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
|
||||
Collections.singletonMap("test-endpoint", "custom"));
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
|
||||
EndpointId.of("testEndpoint"))).isEqualTo("custom");
|
||||
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("testEndpoint")))
|
||||
.isEqualTo("custom");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,20 +52,17 @@ public class ServletEndpointManagementContextConfigurationTests {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(ResourceConfig.class);
|
||||
this.contextRunner.withClassLoader(classLoader).run((context) -> {
|
||||
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
|
||||
ServletEndpointRegistrar bean = context
|
||||
.getBean(ServletEndpointRegistrar.class);
|
||||
ServletEndpointRegistrar bean = context.getBean(ServletEndpointRegistrar.class);
|
||||
assertThat(bean).hasFieldOrPropertyWithValue("basePath", "/test/actuator");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextWhenJerseyShouldContainServletEndpointRegistrar() {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(
|
||||
DispatcherServlet.class);
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(DispatcherServlet.class);
|
||||
this.contextRunner.withClassLoader(classLoader).run((context) -> {
|
||||
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
|
||||
ServletEndpointRegistrar bean = context
|
||||
.getBean(ServletEndpointRegistrar.class);
|
||||
ServletEndpointRegistrar bean = context.getBean(ServletEndpointRegistrar.class);
|
||||
assertThat(bean).hasFieldOrPropertyWithValue("basePath", "/jersey/actuator");
|
||||
});
|
||||
}
|
||||
@@ -73,8 +70,7 @@ public class ServletEndpointManagementContextConfigurationTests {
|
||||
@Test
|
||||
public void contextWhenNoServletBasedShouldNotContainServletEndpointRegistrar() {
|
||||
new ApplicationContextRunner().withUserConfiguration(TestConfig.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ServletEndpointRegistrar.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ServletEndpointRegistrar.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,8 +51,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class WebEndpointAutoConfigurationTests {
|
||||
|
||||
private static final AutoConfigurations CONFIGURATIONS = AutoConfigurations
|
||||
.of(EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class);
|
||||
private static final AutoConfigurations CONFIGURATIONS = AutoConfigurations.of(EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class);
|
||||
|
||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(CONFIGURATIONS);
|
||||
@@ -60,22 +60,17 @@ public class WebEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
public void webApplicationConfiguresEndpointMediaTypes() {
|
||||
this.contextRunner.run((context) -> {
|
||||
EndpointMediaTypes endpointMediaTypes = context
|
||||
.getBean(EndpointMediaTypes.class);
|
||||
assertThat(endpointMediaTypes.getConsumed())
|
||||
.containsExactly(ActuatorMediaType.V2_JSON, "application/json");
|
||||
EndpointMediaTypes endpointMediaTypes = context.getBean(EndpointMediaTypes.class);
|
||||
assertThat(endpointMediaTypes.getConsumed()).containsExactly(ActuatorMediaType.V2_JSON, "application/json");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webApplicationConfiguresPathMapper() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"management.endpoints.web.path-mapping.health=healthcheck")
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.path-mapping.health=healthcheck")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(PathMapper.class);
|
||||
String pathMapping = context.getBean(PathMapper.class)
|
||||
.getRootPath(EndpointId.of("health"));
|
||||
String pathMapping = context.getBean(PathMapper.class).getRootPath(EndpointId.of("health"));
|
||||
assertThat(pathMapping).isEqualTo("healthcheck");
|
||||
});
|
||||
}
|
||||
@@ -85,17 +80,13 @@ public class WebEndpointAutoConfigurationTests {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoints.web.path-mapping.testanotherone=foo")
|
||||
.withUserConfiguration(TestPathMatcher.class, TestOneEndpoint.class,
|
||||
TestAnotherOneEndpoint.class, TestTwoEndpoint.class)
|
||||
.withUserConfiguration(TestPathMatcher.class, TestOneEndpoint.class, TestAnotherOneEndpoint.class,
|
||||
TestTwoEndpoint.class)
|
||||
.run((context) -> {
|
||||
WebEndpointDiscoverer discoverer = context
|
||||
.getBean(WebEndpointDiscoverer.class);
|
||||
Collection<ExposableWebEndpoint> endpoints = discoverer
|
||||
.getEndpoints();
|
||||
ExposableWebEndpoint[] webEndpoints = endpoints
|
||||
.toArray(new ExposableWebEndpoint[0]);
|
||||
List<String> paths = Arrays.stream(webEndpoints)
|
||||
.map(PathMappedEndpoint::getRootPath)
|
||||
WebEndpointDiscoverer discoverer = context.getBean(WebEndpointDiscoverer.class);
|
||||
Collection<ExposableWebEndpoint> endpoints = discoverer.getEndpoints();
|
||||
ExposableWebEndpoint[] webEndpoints = endpoints.toArray(new ExposableWebEndpoint[0]);
|
||||
List<String> paths = Arrays.stream(webEndpoints).map(PathMappedEndpoint::getRootPath)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(paths).containsOnly("1/testone", "foo", "testtwo");
|
||||
});
|
||||
@@ -111,23 +102,20 @@ public class WebEndpointAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void webApplicationConfiguresExposeExcludePropertyEndpointFilter() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.getBeans(ExposeExcludePropertyEndpointFilter.class)
|
||||
.containsKeys("webExposeExcludePropertyEndpointFilter",
|
||||
"controllerExposeExcludePropertyEndpointFilter"));
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).getBeans(ExposeExcludePropertyEndpointFilter.class).containsKeys(
|
||||
"webExposeExcludePropertyEndpointFilter", "controllerExposeExcludePropertyEndpointFilter"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextShouldConfigureServletEndpointDiscoverer() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ServletEndpointDiscoverer.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ServletEndpointDiscoverer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextWhenNotServletShouldNotConfigureServletEndpointDiscoverer() {
|
||||
new ApplicationContextRunner().withConfiguration(CONFIGURATIONS)
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ServletEndpointDiscoverer.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ServletEndpointDiscoverer.class));
|
||||
}
|
||||
|
||||
@Component
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,8 +46,7 @@ public class WebEndpointPropertiesTests {
|
||||
@Test
|
||||
public void basePathMustStartWithSlash() {
|
||||
WebEndpointProperties properties = new WebEndpointProperties();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> properties.setBasePath("admin"))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> properties.setBasePath("admin"))
|
||||
.withMessageContaining("Base path must start with '/' or be empty");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,15 +56,12 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWit
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@TestPropertySource(properties = { "spring.jackson.serialization.indent_output=true",
|
||||
"management.endpoints.web.exposure.include=*",
|
||||
"spring.jackson.default-property-inclusion=non_null" })
|
||||
"management.endpoints.web.exposure.include=*", "spring.jackson.default-property-inclusion=non_null" })
|
||||
public abstract class AbstractEndpointDocumentationTests {
|
||||
|
||||
protected String describeEnumValues(Class<? extends Enum<?>> enumType) {
|
||||
return StringUtils
|
||||
.collectionToDelimitedString(Stream.of(enumType.getEnumConstants())
|
||||
.map((constant) -> "`" + constant.name() + "`")
|
||||
.collect(Collectors.toList()), ", ");
|
||||
return StringUtils.collectionToDelimitedString(Stream.of(enumType.getEnumConstants())
|
||||
.map((constant) -> "`" + constant.name() + "`").collect(Collectors.toList()), ", ");
|
||||
}
|
||||
|
||||
protected OperationPreprocessor limit(String... keys) {
|
||||
@@ -74,8 +71,7 @@ public abstract class AbstractEndpointDocumentationTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> OperationPreprocessor limit(Predicate<T> filter, String... keys) {
|
||||
return new ContentModifyingOperationPreprocessor((content, mediaType) -> {
|
||||
ObjectMapper objectMapper = new ObjectMapper()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
|
||||
try {
|
||||
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
|
||||
Object target = payload;
|
||||
@@ -90,12 +86,10 @@ public abstract class AbstractEndpointDocumentationTests {
|
||||
}
|
||||
}
|
||||
if (target instanceof Map) {
|
||||
parent.put(keys[keys.length - 1],
|
||||
select((Map<String, Object>) target, filter));
|
||||
parent.put(keys[keys.length - 1], select((Map<String, Object>) target, filter));
|
||||
}
|
||||
else {
|
||||
parent.put(keys[keys.length - 1],
|
||||
select((List<Object>) target, filter));
|
||||
parent.put(keys[keys.length - 1], select((List<Object>) target, filter));
|
||||
}
|
||||
return objectMapper.writeValueAsBytes(payload);
|
||||
}
|
||||
@@ -106,36 +100,30 @@ public abstract class AbstractEndpointDocumentationTests {
|
||||
}
|
||||
|
||||
protected FieldDescriptor parentIdField() {
|
||||
return fieldWithPath("contexts.*.parentId")
|
||||
.description("Id of the parent application context, if any.").optional()
|
||||
.type(JsonFieldType.STRING);
|
||||
return fieldWithPath("contexts.*.parentId").description("Id of the parent application context, if any.")
|
||||
.optional().type(JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Map<String, Object> select(Map<String, Object> candidates,
|
||||
Predicate<T> filter) {
|
||||
private <T> Map<String, Object> select(Map<String, Object> candidates, Predicate<T> filter) {
|
||||
Map<String, Object> selected = new HashMap<>();
|
||||
candidates.entrySet().stream().filter((candidate) -> filter.test((T) candidate))
|
||||
.limit(3)
|
||||
candidates.entrySet().stream().filter((candidate) -> filter.test((T) candidate)).limit(3)
|
||||
.forEach((entry) -> selected.put(entry.getKey(), entry.getValue()));
|
||||
return selected;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<Object> select(List<Object> candidates, Predicate<T> filter) {
|
||||
return candidates.stream().filter((candidate) -> filter.test((T) candidate))
|
||||
.limit(3).collect(Collectors.toList());
|
||||
return candidates.stream().filter((candidate) -> filter.test((T) candidate)).limit(3)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
WebMvcEndpointManagementContextConfiguration.class,
|
||||
WebFluxEndpointManagementContextConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
HttpHandlerAutoConfiguration.class })
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, WebMvcEndpointManagementContextConfiguration.class,
|
||||
WebFluxEndpointManagementContextConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class })
|
||||
static class BaseDocumentationConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,8 +47,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class AuditEventsEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class AuditEventsEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@MockBean
|
||||
private AuditEventRepository repository;
|
||||
@@ -56,41 +55,33 @@ public class AuditEventsEndpointDocumentationTests
|
||||
@Test
|
||||
public void allAuditEvents() throws Exception {
|
||||
String queryTimestamp = "2017-11-07T09:37Z";
|
||||
given(this.repository.find(any(), any(), any())).willReturn(
|
||||
Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
|
||||
this.mockMvc.perform(get("/actuator/auditevents").param("after", queryTimestamp))
|
||||
.andExpect(status().isOk())
|
||||
given(this.repository.find(any(), any(), any()))
|
||||
.willReturn(Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
|
||||
this.mockMvc.perform(get("/actuator/auditevents").param("after", queryTimestamp)).andExpect(status().isOk())
|
||||
.andDo(document("auditevents/all", responseFields(
|
||||
fieldWithPath("events").description("An array of audit events."),
|
||||
fieldWithPath("events.[].timestamp")
|
||||
.description("The timestamp of when the event occurred."),
|
||||
fieldWithPath("events.[].principal")
|
||||
.description("The principal that triggered the event."),
|
||||
fieldWithPath("events.[].type")
|
||||
.description("The type of the event."))));
|
||||
fieldWithPath("events.[].timestamp").description("The timestamp of when the event occurred."),
|
||||
fieldWithPath("events.[].principal").description("The principal that triggered the event."),
|
||||
fieldWithPath("events.[].type").description("The type of the event."))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filteredAuditEvents() throws Exception {
|
||||
OffsetDateTime now = OffsetDateTime.now();
|
||||
String queryTimestamp = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(now);
|
||||
given(this.repository.find("alice", now.toInstant(), "logout")).willReturn(
|
||||
Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
|
||||
given(this.repository.find("alice", now.toInstant(), "logout"))
|
||||
.willReturn(Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
|
||||
this.mockMvc
|
||||
.perform(get("/actuator/auditevents").param("principal", "alice")
|
||||
.param("after", queryTimestamp).param("type", "logout"))
|
||||
.perform(get("/actuator/auditevents")
|
||||
.param("principal", "alice").param("after", queryTimestamp).param("type", "logout"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("auditevents/filtered",
|
||||
requestParameters(
|
||||
parameterWithName("after").description(
|
||||
"Restricts the events to those that occurred "
|
||||
+ "after the given time. Optional."),
|
||||
parameterWithName("principal").description(
|
||||
"Restricts the events to those with the given "
|
||||
+ "principal. Optional."),
|
||||
parameterWithName("type").description(
|
||||
"Restricts the events to those with the given "
|
||||
+ "type. Optional."))));
|
||||
.andDo(document("auditevents/filtered", requestParameters(
|
||||
parameterWithName("after").description(
|
||||
"Restricts the events to those that occurred " + "after the given time. Optional."),
|
||||
parameterWithName("principal")
|
||||
.description("Restricts the events to those with the given " + "principal. Optional."),
|
||||
parameterWithName("type")
|
||||
.description("Restricts the events to those with the given " + "type. Optional."))));
|
||||
verify(this.repository).find("alice", now.toInstant(), "logout");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,32 +49,25 @@ public class BeansEndpointDocumentationTests extends MockMvcEndpointDocumentatio
|
||||
|
||||
@Test
|
||||
public void beans() throws Exception {
|
||||
List<FieldDescriptor> beanFields = Arrays.asList(
|
||||
fieldWithPath("aliases").description("Names of any aliases."),
|
||||
List<FieldDescriptor> beanFields = Arrays.asList(fieldWithPath("aliases").description("Names of any aliases."),
|
||||
fieldWithPath("scope").description("Scope of the bean."),
|
||||
fieldWithPath("type").description("Fully qualified type of the bean."),
|
||||
fieldWithPath("resource")
|
||||
.description("Resource in which the bean was defined, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("resource").description("Resource in which the bean was defined, if any.").optional(),
|
||||
fieldWithPath("dependencies").description("Names of any dependencies."));
|
||||
ResponseFieldsSnippet responseFields = responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."),
|
||||
parentIdField(),
|
||||
fieldWithPath("contexts.*.beans")
|
||||
.description("Beans in the application context keyed by name."))
|
||||
.andWithPrefix("contexts.*.beans.*.", beanFields);
|
||||
fieldWithPath("contexts").description("Application contexts keyed by id."), parentIdField(),
|
||||
fieldWithPath("contexts.*.beans").description("Beans in the application context keyed by name."))
|
||||
.andWithPrefix("contexts.*.beans.*.", beanFields);
|
||||
this.mockMvc.perform(get("/actuator/beans")).andExpect(status().isOk())
|
||||
.andDo(document("beans",
|
||||
preprocessResponse(limit(this::isIndependentBean, "contexts",
|
||||
getApplicationContext().getId(), "beans")),
|
||||
preprocessResponse(
|
||||
limit(this::isIndependentBean, "contexts", getApplicationContext().getId(), "beans")),
|
||||
responseFields));
|
||||
}
|
||||
|
||||
private boolean isIndependentBean(Entry<String, Map<String, Object>> bean) {
|
||||
return CollectionUtils.isEmpty((Collection<?>) bean.getValue().get("aliases"))
|
||||
&& CollectionUtils
|
||||
.isEmpty((Collection<?>) bean.getValue().get("dependencies"));
|
||||
&& CollectionUtils.isEmpty((Collection<?>) bean.getValue().get("dependencies"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,34 +53,28 @@ public class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
private static final List<FieldDescriptor> levelFields = Arrays.asList(
|
||||
fieldWithPath("name").description("Cache name."),
|
||||
fieldWithPath("cacheManager").description("Cache manager name."),
|
||||
fieldWithPath("target")
|
||||
.description("Fully qualified name of the native cache."));
|
||||
fieldWithPath("target").description("Fully qualified name of the native cache."));
|
||||
|
||||
private static final List<ParameterDescriptor> requestParameters = Collections
|
||||
.singletonList(parameterWithName("cacheManager")
|
||||
.description("Name of the cacheManager to qualify the cache. May be "
|
||||
+ "omitted if the cache name is unique.")
|
||||
.singletonList(parameterWithName("cacheManager").description(
|
||||
"Name of the cacheManager to qualify the cache. May be " + "omitted if the cache name is unique.")
|
||||
.optional());
|
||||
|
||||
@Test
|
||||
public void allCaches() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/caches")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("caches/all", responseFields(
|
||||
fieldWithPath("cacheManagers")
|
||||
.description("Cache managers keyed by id."),
|
||||
fieldWithPath("cacheManagers.*.caches").description(
|
||||
"Caches in the application context keyed by " + "name."))
|
||||
.andWithPrefix("cacheManagers.*.caches.*.",
|
||||
fieldWithPath("target").description(
|
||||
"Fully qualified name of the native cache."))));
|
||||
.andDo(MockMvcRestDocumentation.document("caches/all",
|
||||
responseFields(fieldWithPath("cacheManagers").description("Cache managers keyed by id."),
|
||||
fieldWithPath("cacheManagers.*.caches")
|
||||
.description("Caches in the application context keyed by " + "name."))
|
||||
.andWithPrefix("cacheManagers.*.caches.*.", fieldWithPath("target")
|
||||
.description("Fully qualified name of the native cache."))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namedCache() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/caches/cities")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("caches/named",
|
||||
requestParameters(requestParameters),
|
||||
responseFields(levelFields)));
|
||||
this.mockMvc.perform(get("/actuator/caches/cities")).andExpect(status().isOk()).andDo(MockMvcRestDocumentation
|
||||
.document("caches/named", requestParameters(requestParameters), responseFields(levelFields)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,12 +85,9 @@ public class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
|
||||
@Test
|
||||
public void evictNamedCache() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(delete(
|
||||
"/actuator/caches/countries?cacheManager=anotherCacheManager"))
|
||||
this.mockMvc.perform(delete("/actuator/caches/countries?cacheManager=anotherCacheManager"))
|
||||
.andExpect(status().isNoContent())
|
||||
.andDo(MockMvcRestDocumentation.document("caches/evict-named",
|
||||
requestParameters(requestParameters)));
|
||||
.andDo(MockMvcRestDocumentation.document("caches/evict-named", requestParameters(requestParameters)));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -106,10 +97,8 @@ public class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
@Bean
|
||||
public CachesEndpoint endpoint() {
|
||||
Map<String, CacheManager> cacheManagers = new HashMap<>();
|
||||
cacheManagers.put("cacheManager",
|
||||
new ConcurrentMapCacheManager("countries", "cities"));
|
||||
cacheManagers.put("anotherCacheManager",
|
||||
new ConcurrentMapCacheManager("countries"));
|
||||
cacheManagers.put("cacheManager", new ConcurrentMapCacheManager("countries", "cities"));
|
||||
cacheManagers.put("anotherCacheManager", new ConcurrentMapCacheManager("countries"));
|
||||
return new CachesEndpoint(cacheManagers);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,8 +50,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ConditionsReportEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class ConditionsReportEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
@@ -65,53 +64,36 @@ public class ConditionsReportEndpointDocumentationTests
|
||||
@Before
|
||||
public void before() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext)
|
||||
.apply(MockMvcRestDocumentation
|
||||
.documentationConfiguration(this.restDocumentation).uris())
|
||||
.build();
|
||||
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation).uris()).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void conditions() throws Exception {
|
||||
List<FieldDescriptor> positiveMatchFields = Arrays.asList(
|
||||
fieldWithPath("").description(
|
||||
"Classes and methods with conditions that were " + "matched."),
|
||||
fieldWithPath("").description("Classes and methods with conditions that were " + "matched."),
|
||||
fieldWithPath(".*.[].condition").description("Name of the condition."),
|
||||
fieldWithPath(".*.[].message")
|
||||
.description("Details of why the condition was matched."));
|
||||
fieldWithPath(".*.[].message").description("Details of why the condition was matched."));
|
||||
List<FieldDescriptor> negativeMatchFields = Arrays.asList(
|
||||
fieldWithPath("").description("Classes and methods with conditions that "
|
||||
+ "were not matched."),
|
||||
fieldWithPath(".*.notMatched")
|
||||
.description("Conditions that were matched."),
|
||||
fieldWithPath(".*.notMatched.[].condition")
|
||||
.description("Name of the condition."),
|
||||
fieldWithPath(".*.notMatched.[].message").description(
|
||||
"Details of why the condition was" + " not matched."),
|
||||
fieldWithPath("").description("Classes and methods with conditions that " + "were not matched."),
|
||||
fieldWithPath(".*.notMatched").description("Conditions that were matched."),
|
||||
fieldWithPath(".*.notMatched.[].condition").description("Name of the condition."),
|
||||
fieldWithPath(".*.notMatched.[].message")
|
||||
.description("Details of why the condition was" + " not matched."),
|
||||
fieldWithPath(".*.matched").description("Conditions that were matched."),
|
||||
fieldWithPath(".*.matched.[].condition")
|
||||
.description("Name of the condition.").type(JsonFieldType.STRING)
|
||||
.optional(),
|
||||
fieldWithPath(".*.matched.[].message")
|
||||
.description("Details of why the condition was matched.")
|
||||
fieldWithPath(".*.matched.[].condition").description("Name of the condition.")
|
||||
.type(JsonFieldType.STRING).optional(),
|
||||
fieldWithPath(".*.matched.[].message").description("Details of why the condition was matched.")
|
||||
.type(JsonFieldType.STRING).optional());
|
||||
FieldDescriptor unconditionalClassesField = fieldWithPath(
|
||||
"contexts.*.unconditionalClasses").description(
|
||||
"Names of unconditional auto-configuration classes if any.");
|
||||
FieldDescriptor unconditionalClassesField = fieldWithPath("contexts.*.unconditionalClasses")
|
||||
.description("Names of unconditional auto-configuration classes if any.");
|
||||
this.mockMvc.perform(get("/actuator/conditions")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("conditions",
|
||||
preprocessResponse(
|
||||
limit("contexts", getApplicationContext()
|
||||
.getId(), "positiveMatches"),
|
||||
limit("contexts", getApplicationContext().getId(),
|
||||
"negativeMatches")),
|
||||
responseFields(fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."))
|
||||
.andWithPrefix("contexts.*.positiveMatches",
|
||||
positiveMatchFields)
|
||||
.andWithPrefix("contexts.*.negativeMatches",
|
||||
negativeMatchFields)
|
||||
.and(unconditionalClassesField,
|
||||
parentIdField())));
|
||||
preprocessResponse(limit("contexts", getApplicationContext().getId(), "positiveMatches"),
|
||||
limit("contexts", getApplicationContext().getId(), "negativeMatches")),
|
||||
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id."))
|
||||
.andWithPrefix("contexts.*.positiveMatches", positiveMatchFields)
|
||||
.andWithPrefix("contexts.*.negativeMatches", negativeMatchFields)
|
||||
.and(unconditionalClassesField, parentIdField())));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -119,12 +101,11 @@ public class ConditionsReportEndpointDocumentationTests
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public ConditionsReportEndpoint autoConfigurationReportEndpoint(
|
||||
ConfigurableApplicationContext context) {
|
||||
public ConditionsReportEndpoint autoConfigurationReportEndpoint(ConfigurableApplicationContext context) {
|
||||
ConditionEvaluationReport conditionEvaluationReport = ConditionEvaluationReport
|
||||
.get(context.getBeanFactory());
|
||||
conditionEvaluationReport.recordEvaluationCandidates(
|
||||
Arrays.asList(PropertyPlaceholderAutoConfiguration.class.getName()));
|
||||
conditionEvaluationReport
|
||||
.recordEvaluationCandidates(Arrays.asList(PropertyPlaceholderAutoConfiguration.class.getName()));
|
||||
return new ConditionsReportEndpoint(context);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,25 +37,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ConfigurationPropertiesReportEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class ConfigurationPropertiesReportEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void configProps() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/configprops")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("configprops",
|
||||
preprocessResponse(limit("contexts",
|
||||
getApplicationContext().getId(), "beans")),
|
||||
responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."),
|
||||
fieldWithPath("contexts.*.beans.*").description(
|
||||
"`@ConfigurationProperties` beans keyed by bean name."),
|
||||
fieldWithPath("contexts.*.beans.*.prefix").description(
|
||||
"Prefix applied to the names of the bean's properties."),
|
||||
preprocessResponse(limit("contexts", getApplicationContext().getId(), "beans")),
|
||||
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id."),
|
||||
fieldWithPath("contexts.*.beans.*")
|
||||
.description("`@ConfigurationProperties` beans keyed by bean name."),
|
||||
fieldWithPath("contexts.*.beans.*.prefix")
|
||||
.description("Prefix applied to the names of the bean's properties."),
|
||||
subsectionWithPath("contexts.*.beans.*.properties")
|
||||
.description(
|
||||
"Properties of the bean as name-value pairs."),
|
||||
.description("Properties of the bean as name-value pairs."),
|
||||
parentIdField())));
|
||||
}
|
||||
|
||||
|
||||
@@ -57,61 +57,49 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*/
|
||||
@TestPropertySource(
|
||||
properties = "spring.config.location=classpath:/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/")
|
||||
public class EnvironmentEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class EnvironmentEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
private static final FieldDescriptor activeProfiles = fieldWithPath("activeProfiles")
|
||||
.description("Names of the active profiles, if any.");
|
||||
|
||||
private static final FieldDescriptor propertySources = fieldWithPath(
|
||||
"propertySources").description("Property sources in order of precedence.");
|
||||
private static final FieldDescriptor propertySources = fieldWithPath("propertySources")
|
||||
.description("Property sources in order of precedence.");
|
||||
|
||||
private static final FieldDescriptor propertySourceName = fieldWithPath(
|
||||
"propertySources.[].name").description("Name of the property source.");
|
||||
private static final FieldDescriptor propertySourceName = fieldWithPath("propertySources.[].name")
|
||||
.description("Name of the property source.");
|
||||
|
||||
@Test
|
||||
public void env() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/env")).andExpect(status().isOk()).andDo(
|
||||
document("env/all", preprocessResponse(replacePattern(Pattern.compile(
|
||||
"org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
|
||||
this.mockMvc.perform(get("/actuator/env")).andExpect(status().isOk())
|
||||
.andDo(document("env/all", preprocessResponse(replacePattern(
|
||||
Pattern.compile("org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
|
||||
""), filterProperties()),
|
||||
responseFields(activeProfiles, propertySources,
|
||||
propertySourceName,
|
||||
responseFields(activeProfiles, propertySources, propertySourceName,
|
||||
fieldWithPath("propertySources.[].properties")
|
||||
.description(
|
||||
"Properties in the property source keyed by property name."),
|
||||
.description("Properties in the property source keyed by property name."),
|
||||
fieldWithPath("propertySources.[].properties.*.value")
|
||||
.description("Value of the property."),
|
||||
fieldWithPath("propertySources.[].properties.*.origin")
|
||||
.description("Origin of the property, if any.")
|
||||
.optional())));
|
||||
.description("Origin of the property, if any.").optional())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singlePropertyFromEnv() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/env/com.example.cache.max-size"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("env/single",
|
||||
preprocessResponse(replacePattern(Pattern.compile(
|
||||
"org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
|
||||
"")),
|
||||
responseFields(
|
||||
fieldWithPath("property").description(
|
||||
"Property from the environment, if found.")
|
||||
.optional(),
|
||||
fieldWithPath("property.source").description(
|
||||
"Name of the source of the property."),
|
||||
fieldWithPath("property.value")
|
||||
.description("Value of the property."),
|
||||
activeProfiles, propertySources, propertySourceName,
|
||||
fieldWithPath("propertySources.[].property").description(
|
||||
"Property in the property source, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("propertySources.[].property.value")
|
||||
.description("Value of the property."),
|
||||
fieldWithPath("propertySources.[].property.origin")
|
||||
.description("Origin of the property, if any.")
|
||||
.optional())));
|
||||
this.mockMvc.perform(get("/actuator/env/com.example.cache.max-size")).andExpect(status().isOk()).andDo(document(
|
||||
"env/single",
|
||||
preprocessResponse(replacePattern(
|
||||
Pattern.compile("org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
|
||||
"")),
|
||||
responseFields(
|
||||
fieldWithPath("property").description("Property from the environment, if found.").optional(),
|
||||
fieldWithPath("property.source").description("Name of the source of the property."),
|
||||
fieldWithPath("property.value").description("Value of the property."), activeProfiles,
|
||||
propertySources, propertySourceName,
|
||||
fieldWithPath("propertySources.[].property")
|
||||
.description("Property in the property source, if any.").optional(),
|
||||
fieldWithPath("propertySources.[].property.value").description("Value of the property."),
|
||||
fieldWithPath("propertySources.[].property.origin")
|
||||
.description("Origin of the property, if any.").optional())));
|
||||
}
|
||||
|
||||
private OperationPreprocessor filterProperties() {
|
||||
@@ -120,17 +108,14 @@ public class EnvironmentEndpointDocumentationTests
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private byte[] filterProperties(byte[] content, MediaType mediaType) {
|
||||
ObjectMapper objectMapper = new ObjectMapper()
|
||||
.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
|
||||
try {
|
||||
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
|
||||
List<Map<String, Object>> propertySources = (List<Map<String, Object>>) payload
|
||||
.get("propertySources");
|
||||
List<Map<String, Object>> propertySources = (List<Map<String, Object>>) payload.get("propertySources");
|
||||
for (Map<String, Object> propertySource : propertySources) {
|
||||
Map<String, String> properties = (Map<String, String>) propertySource
|
||||
.get("properties");
|
||||
Set<String> filteredKeys = properties.keySet().stream()
|
||||
.filter(this::retainKey).limit(3).collect(Collectors.toSet());
|
||||
Map<String, String> properties = (Map<String, String>) propertySource.get("properties");
|
||||
Set<String> filteredKeys = properties.keySet().stream().filter(this::retainKey).limit(3)
|
||||
.collect(Collectors.toSet());
|
||||
properties.keySet().retainAll(filteredKeys);
|
||||
}
|
||||
return objectMapper.writeValueAsBytes(payload);
|
||||
@@ -141,8 +126,7 @@ public class EnvironmentEndpointDocumentationTests
|
||||
}
|
||||
|
||||
private boolean retainKey(String key) {
|
||||
return key.startsWith("java.") || key.equals("JAVA_HOME")
|
||||
|| key.startsWith("com.example");
|
||||
return key.startsWith("java.") || key.equals("JAVA_HOME") || key.startsWith("com.example");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -154,17 +138,14 @@ public class EnvironmentEndpointDocumentationTests
|
||||
return new EnvironmentEndpoint(new AbstractEnvironment() {
|
||||
|
||||
@Override
|
||||
protected void customizePropertySources(
|
||||
MutablePropertySources propertySources) {
|
||||
environment.getPropertySources().stream()
|
||||
.filter(this::includedPropertySource)
|
||||
protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||
environment.getPropertySources().stream().filter(this::includedPropertySource)
|
||||
.forEach(propertySources::addLast);
|
||||
}
|
||||
|
||||
private boolean includedPropertySource(PropertySource<?> propertySource) {
|
||||
return propertySource instanceof EnumerablePropertySource
|
||||
&& !"Inlined Test Properties"
|
||||
.equals(propertySource.getName());
|
||||
&& !"Inlined Test Properties".equals(propertySource.getName());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,49 +52,35 @@ public class FlywayEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
@Test
|
||||
public void flyway() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/flyway")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("flyway", responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id"),
|
||||
fieldWithPath("contexts.*.flywayBeans.*.migrations").description(
|
||||
"Migrations performed by the Flyway instance, keyed by"
|
||||
+ " Flyway bean name.")).andWithPrefix(
|
||||
"contexts.*.flywayBeans.*.migrations.[].",
|
||||
migrationFieldDescriptors())
|
||||
.andDo(MockMvcRestDocumentation.document("flyway",
|
||||
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id"),
|
||||
fieldWithPath("contexts.*.flywayBeans.*.migrations").description(
|
||||
"Migrations performed by the Flyway instance, keyed by" + " Flyway bean name."))
|
||||
.andWithPrefix("contexts.*.flywayBeans.*.migrations.[].",
|
||||
migrationFieldDescriptors())
|
||||
.and(parentIdField())));
|
||||
}
|
||||
|
||||
private List<FieldDescriptor> migrationFieldDescriptors() {
|
||||
return Arrays.asList(
|
||||
fieldWithPath("checksum")
|
||||
.description("Checksum of the migration, if any.").optional(),
|
||||
fieldWithPath("description")
|
||||
.description("Description of the migration, if any.").optional(),
|
||||
fieldWithPath("executionTime")
|
||||
.description(
|
||||
"Execution time in milliseconds of an applied migration.")
|
||||
return Arrays.asList(fieldWithPath("checksum").description("Checksum of the migration, if any.").optional(),
|
||||
fieldWithPath("description").description("Description of the migration, if any.").optional(),
|
||||
fieldWithPath("executionTime").description("Execution time in milliseconds of an applied migration.")
|
||||
.optional(),
|
||||
fieldWithPath("installedBy")
|
||||
.description("User that installed the applied migration, if any.")
|
||||
fieldWithPath("installedBy").description("User that installed the applied migration, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("installedOn").description(
|
||||
"Timestamp of when the applied migration was installed, "
|
||||
+ "if any.")
|
||||
fieldWithPath("installedOn")
|
||||
.description("Timestamp of when the applied migration was installed, " + "if any.").optional(),
|
||||
fieldWithPath("installedRank")
|
||||
.description("Rank of the applied migration, if any. Later migrations have " + "higher ranks.")
|
||||
.optional(),
|
||||
fieldWithPath("installedRank").description(
|
||||
"Rank of the applied migration, if any. Later migrations have "
|
||||
+ "higher ranks.")
|
||||
fieldWithPath("script").description("Name of the script used to execute the migration, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("script").description(
|
||||
"Name of the script used to execute the migration, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("state").description("State of the migration. ("
|
||||
+ describeEnumValues(MigrationState.class) + ")"),
|
||||
fieldWithPath("type").description("Type of the migration. ("
|
||||
+ describeEnumValues(MigrationType.class) + ")"),
|
||||
fieldWithPath("version").description(
|
||||
"Version of the database after applying the migration, "
|
||||
+ "if any.")
|
||||
.optional());
|
||||
fieldWithPath("state")
|
||||
.description("State of the migration. (" + describeEnumValues(MigrationState.class) + ")"),
|
||||
fieldWithPath("type")
|
||||
.description("Type of the migration. (" + describeEnumValues(MigrationType.class) + ")"),
|
||||
fieldWithPath("version")
|
||||
.description("Version of the database after applying the migration, " + "if any.").optional());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -104,9 +90,8 @@ public class FlywayEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder().generateUniqueName(true).setType(
|
||||
EmbeddedDatabaseConnection.get(getClass().getClassLoader()).getType())
|
||||
.build();
|
||||
return new EmbeddedDatabaseBuilder().generateUniqueName(true)
|
||||
.setType(EmbeddedDatabaseConnection.get(getClass().getClassLoader()).getType()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,25 +58,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
private static final List<FieldDescriptor> componentFields = Arrays.asList(
|
||||
fieldWithPath("status")
|
||||
.description("Status of a specific part of the application"),
|
||||
subsectionWithPath("details").description(
|
||||
"Details of the health of a specific part of the" + " application."));
|
||||
fieldWithPath("status").description("Status of a specific part of the application"),
|
||||
subsectionWithPath("details")
|
||||
.description("Details of the health of a specific part of the" + " application."));
|
||||
|
||||
@Test
|
||||
public void health() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/health")).andExpect(status().isOk())
|
||||
.andDo(document("health", responseFields(
|
||||
fieldWithPath("status")
|
||||
.description("Overall status of the application."),
|
||||
fieldWithPath("details").description(
|
||||
"Details of the health of the application. Presence is controlled by "
|
||||
this.mockMvc.perform(get("/actuator/health")).andExpect(status().isOk()).andDo(document("health",
|
||||
responseFields(fieldWithPath("status").description("Overall status of the application."),
|
||||
fieldWithPath("details")
|
||||
.description("Details of the health of the application. Presence is controlled by "
|
||||
+ "`management.endpoint.health.show-details`)."),
|
||||
fieldWithPath("details.*.status").description(
|
||||
"Status of a specific part of the application."),
|
||||
subsectionWithPath("details.*.details").description(
|
||||
"Details of the health of a specific part of the"
|
||||
+ " application."))));
|
||||
fieldWithPath("details.*.status").description("Status of a specific part of the application."),
|
||||
subsectionWithPath("details.*.details")
|
||||
.description("Details of the health of a specific part of the" + " application."))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,8 +82,7 @@ public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
|
||||
@Test
|
||||
public void healthComponentInstance() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/health/broker/us1"))
|
||||
.andExpect(status().isOk())
|
||||
this.mockMvc.perform(get("/actuator/health/broker/us1")).andExpect(status().isOk())
|
||||
.andDo(document("health/instance", responseFields(componentFields)));
|
||||
}
|
||||
|
||||
@@ -99,9 +93,8 @@ public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
|
||||
@Bean
|
||||
public HealthEndpoint endpoint(Map<String, HealthIndicator> healthIndicators) {
|
||||
return new HealthEndpoint(new CompositeHealthIndicator(
|
||||
new OrderedHealthAggregator(), new HealthIndicatorRegistryFactory()
|
||||
.createHealthIndicatorRegistry(healthIndicators)));
|
||||
return new HealthEndpoint(new CompositeHealthIndicator(new OrderedHealthAggregator(),
|
||||
new HealthIndicatorRegistryFactory().createHealthIndicatorRegistry(healthIndicators)));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -117,12 +110,9 @@ public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
@Bean
|
||||
public CompositeHealthIndicator brokerHealthIndicator() {
|
||||
Map<String, HealthIndicator> indicators = new LinkedHashMap<>();
|
||||
indicators.put("us1",
|
||||
() -> Health.up().withDetail("version", "1.0.2").build());
|
||||
indicators.put("us2",
|
||||
() -> Health.up().withDetail("version", "1.0.4").build());
|
||||
return new CompositeHealthIndicator(new OrderedHealthAggregator(),
|
||||
indicators);
|
||||
indicators.put("us1", () -> Health.up().withDetail("version", "1.0.2").build());
|
||||
indicators.put("us2", () -> Health.up().withDetail("version", "1.0.4").build());
|
||||
return new CompositeHealthIndicator(new OrderedHealthAggregator(), indicators);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,24 +39,21 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class HeapDumpWebEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class HeapDumpWebEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void heapDump() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/heapdump")).andExpect(status().isOk())
|
||||
.andDo(document("heapdump",
|
||||
new CurlRequestSnippet(CliDocumentation.multiLineFormat()) {
|
||||
.andDo(document("heapdump", new CurlRequestSnippet(CliDocumentation.multiLineFormat()) {
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> createModel(
|
||||
Operation operation) {
|
||||
Map<String, Object> model = super.createModel(operation);
|
||||
model.put("options", "-O");
|
||||
return model;
|
||||
}
|
||||
@Override
|
||||
protected Map<String, Object> createModel(Operation operation) {
|
||||
Map<String, Object> model = super.createModel(operation);
|
||||
model.put("options", "-O");
|
||||
return model;
|
||||
}
|
||||
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -68,10 +65,8 @@ public class HeapDumpWebEndpointDocumentationTests
|
||||
return new HeapDumpWebEndpoint() {
|
||||
|
||||
@Override
|
||||
protected HeapDumper createHeapDumper()
|
||||
throws HeapDumperUnavailableException {
|
||||
return (file, live) -> FileCopyUtils.copy("<<binary content>>",
|
||||
new FileWriter(file));
|
||||
protected HeapDumper createHeapDumper() throws HeapDumperUnavailableException {
|
||||
return (file, live) -> FileCopyUtils.copy("<<binary content>>", new FileWriter(file));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,8 +52,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class HttpTraceEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class HttpTraceEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@MockBean
|
||||
private HttpTraceRepository repository;
|
||||
@@ -63,55 +62,43 @@ public class HttpTraceEndpointDocumentationTests
|
||||
TraceableRequest request = mock(TraceableRequest.class);
|
||||
given(request.getUri()).willReturn(URI.create("https://api.example.com"));
|
||||
given(request.getMethod()).willReturn("GET");
|
||||
given(request.getHeaders()).willReturn(Collections
|
||||
.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json")));
|
||||
given(request.getHeaders())
|
||||
.willReturn(Collections.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json")));
|
||||
TraceableResponse response = mock(TraceableResponse.class);
|
||||
given(response.getStatus()).willReturn(200);
|
||||
given(response.getHeaders()).willReturn(Collections.singletonMap(
|
||||
HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json")));
|
||||
given(response.getHeaders())
|
||||
.willReturn(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json")));
|
||||
Principal principal = mock(Principal.class);
|
||||
given(principal.getName()).willReturn("alice");
|
||||
HttpExchangeTracer tracer = new HttpExchangeTracer(EnumSet.allOf(Include.class));
|
||||
HttpTrace trace = tracer.receivedRequest(request);
|
||||
tracer.sendingResponse(trace, response, () -> principal,
|
||||
() -> UUID.randomUUID().toString());
|
||||
tracer.sendingResponse(trace, response, () -> principal, () -> UUID.randomUUID().toString());
|
||||
given(this.repository.findAll()).willReturn(Arrays.asList(trace));
|
||||
this.mockMvc.perform(get("/actuator/httptrace")).andExpect(status().isOk())
|
||||
.andDo(document("httptrace", responseFields(
|
||||
fieldWithPath("traces").description(
|
||||
"An array of traced HTTP request-response exchanges."),
|
||||
fieldWithPath("traces.[].timestamp").description(
|
||||
"Timestamp of when the traced exchange occurred."),
|
||||
fieldWithPath("traces.[].principal")
|
||||
.description("Principal of the exchange, if any.")
|
||||
fieldWithPath("traces").description("An array of traced HTTP request-response exchanges."),
|
||||
fieldWithPath("traces.[].timestamp")
|
||||
.description("Timestamp of when the traced exchange occurred."),
|
||||
fieldWithPath("traces.[].principal").description("Principal of the exchange, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("traces.[].principal.name")
|
||||
.description("Name of the principal.").optional(),
|
||||
fieldWithPath("traces.[].request.method")
|
||||
.description("HTTP method of the request."),
|
||||
fieldWithPath("traces.[].request.remoteAddress").description(
|
||||
"Remote address from which the request was received, if known.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("traces.[].request.uri")
|
||||
.description("URI of the request."),
|
||||
fieldWithPath("traces.[].request.headers").description(
|
||||
"Headers of the request, keyed by header name."),
|
||||
fieldWithPath("traces.[].request.headers.*.[]")
|
||||
.description("Values of the header"),
|
||||
fieldWithPath("traces.[].response.status")
|
||||
.description("Status of the response"),
|
||||
fieldWithPath("traces.[].response.headers").description(
|
||||
"Headers of the response, keyed by header name."),
|
||||
fieldWithPath("traces.[].response.headers.*.[]")
|
||||
.description("Values of the header"),
|
||||
fieldWithPath("traces.[].session")
|
||||
.description(
|
||||
"Session associated with the exchange, if any.")
|
||||
fieldWithPath("traces.[].principal.name").description("Name of the principal.").optional(),
|
||||
fieldWithPath("traces.[].request.method").description("HTTP method of the request."),
|
||||
fieldWithPath("traces.[].request.remoteAddress")
|
||||
.description("Remote address from which the request was received, if known.").optional()
|
||||
.type(JsonFieldType.STRING),
|
||||
fieldWithPath("traces.[].request.uri").description("URI of the request."),
|
||||
fieldWithPath("traces.[].request.headers")
|
||||
.description("Headers of the request, keyed by header name."),
|
||||
fieldWithPath("traces.[].request.headers.*.[]").description("Values of the header"),
|
||||
fieldWithPath("traces.[].response.status").description("Status of the response"),
|
||||
fieldWithPath("traces.[].response.headers")
|
||||
.description("Headers of the response, keyed by header name."),
|
||||
fieldWithPath("traces.[].response.headers.*.[]").description("Values of the header"),
|
||||
fieldWithPath("traces.[].session").description("Session associated with the exchange, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("traces.[].session.id")
|
||||
.description("ID of the session."),
|
||||
fieldWithPath("traces.[].timeTaken").description(
|
||||
"Time, in milliseconds, taken to handle the exchange."))));
|
||||
fieldWithPath("traces.[].session.id").description("ID of the session."),
|
||||
fieldWithPath("traces.[].timeTaken")
|
||||
.description("Time, in milliseconds, taken to handle the exchange."))));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,33 +51,20 @@ public class InfoEndpointDocumentationTests extends MockMvcEndpointDocumentation
|
||||
this.mockMvc.perform(get("/actuator/info")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("info",
|
||||
responseFields(beneathPath("git"),
|
||||
fieldWithPath("branch")
|
||||
.description("Name of the Git branch, if any."),
|
||||
fieldWithPath("commit").description(
|
||||
"Details of the Git commit, if any."),
|
||||
fieldWithPath("commit.time")
|
||||
.description("Timestamp of the commit, if any.")
|
||||
fieldWithPath("branch").description("Name of the Git branch, if any."),
|
||||
fieldWithPath("commit").description("Details of the Git commit, if any."),
|
||||
fieldWithPath("commit.time").description("Timestamp of the commit, if any.")
|
||||
.type(JsonFieldType.VARIES),
|
||||
fieldWithPath("commit.id")
|
||||
.description("ID of the commit, if any.")),
|
||||
fieldWithPath("commit.id").description("ID of the commit, if any.")),
|
||||
responseFields(beneathPath("build"),
|
||||
fieldWithPath("artifact")
|
||||
.description(
|
||||
"Artifact ID of the application, if any.")
|
||||
fieldWithPath("artifact").description("Artifact ID of the application, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("group")
|
||||
.description(
|
||||
"Group ID of the application, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("name")
|
||||
.description("Name of the application, if any.")
|
||||
fieldWithPath("group").description("Group ID of the application, if any.").optional(),
|
||||
fieldWithPath("name").description("Name of the application, if any.")
|
||||
.type(JsonFieldType.STRING).optional(),
|
||||
fieldWithPath("version")
|
||||
.description(
|
||||
"Version of the application, if any.")
|
||||
.optional(),
|
||||
fieldWithPath("time").description(
|
||||
"Timestamp of when the application was built, if any.")
|
||||
fieldWithPath("version").description("Version of the application, if any.").optional(),
|
||||
fieldWithPath("time")
|
||||
.description("Timestamp of when the application was built, if any.")
|
||||
.type(JsonFieldType.VARIES).optional())));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,8 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
public class IntegrationGraphEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class IntegrationGraphEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void graph() throws Exception {
|
||||
@@ -46,8 +45,7 @@ public class IntegrationGraphEndpointDocumentationTests
|
||||
|
||||
@Test
|
||||
public void rebuild() throws Exception {
|
||||
this.mockMvc.perform(post("/actuator/integrationgraph"))
|
||||
.andExpect(status().isNoContent())
|
||||
this.mockMvc.perform(post("/actuator/integrationgraph")).andExpect(status().isNoContent())
|
||||
.andDo(MockMvcRestDocumentation.document("integrationgraph/rebuild"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,50 +43,37 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class LiquibaseEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class LiquibaseEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void liquibase() throws Exception {
|
||||
FieldDescriptor changeSetsField = fieldWithPath(
|
||||
"contexts.*.liquibaseBeans.*.changeSets")
|
||||
.description("Change sets made by the Liquibase beans, keyed by "
|
||||
+ "bean name.");
|
||||
FieldDescriptor changeSetsField = fieldWithPath("contexts.*.liquibaseBeans.*.changeSets")
|
||||
.description("Change sets made by the Liquibase beans, keyed by " + "bean name.");
|
||||
this.mockMvc.perform(get("/actuator/liquibase")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("liquibase",
|
||||
responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id"),
|
||||
changeSetsField).andWithPrefix(
|
||||
"contexts.*.liquibaseBeans.*.changeSets[].",
|
||||
getChangeSetFieldDescriptors())
|
||||
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id"),
|
||||
changeSetsField)
|
||||
.andWithPrefix("contexts.*.liquibaseBeans.*.changeSets[].",
|
||||
getChangeSetFieldDescriptors())
|
||||
.and(parentIdField())));
|
||||
}
|
||||
|
||||
private List<FieldDescriptor> getChangeSetFieldDescriptors() {
|
||||
return Arrays.asList(
|
||||
fieldWithPath("author").description("Author of the change set."),
|
||||
fieldWithPath("changeLog")
|
||||
.description("Change log that contains the change set."),
|
||||
return Arrays.asList(fieldWithPath("author").description("Author of the change set."),
|
||||
fieldWithPath("changeLog").description("Change log that contains the change set."),
|
||||
fieldWithPath("comments").description("Comments on the change set."),
|
||||
fieldWithPath("contexts").description("Contexts of the change set."),
|
||||
fieldWithPath("dateExecuted")
|
||||
.description("Timestamp of when the change set was executed."),
|
||||
fieldWithPath("deploymentId")
|
||||
.description("ID of the deployment that ran the change set."),
|
||||
fieldWithPath("description")
|
||||
.description("Description of the change set."),
|
||||
fieldWithPath("execType").description("Execution type of the change set ("
|
||||
+ describeEnumValues(ExecType.class) + ")."),
|
||||
fieldWithPath("dateExecuted").description("Timestamp of when the change set was executed."),
|
||||
fieldWithPath("deploymentId").description("ID of the deployment that ran the change set."),
|
||||
fieldWithPath("description").description("Description of the change set."),
|
||||
fieldWithPath("execType")
|
||||
.description("Execution type of the change set (" + describeEnumValues(ExecType.class) + ")."),
|
||||
fieldWithPath("id").description("ID of the change set."),
|
||||
fieldWithPath("labels")
|
||||
.description("Labels associated with the change set."),
|
||||
fieldWithPath("labels").description("Labels associated with the change set."),
|
||||
fieldWithPath("checksum").description("Checksum of the change set."),
|
||||
fieldWithPath("orderExecuted")
|
||||
.description("Order of the execution of the change set."),
|
||||
fieldWithPath("tag")
|
||||
.description("Tag associated with the change set, if any.")
|
||||
.optional().type(JsonFieldType.STRING));
|
||||
fieldWithPath("orderExecuted").description("Order of the execution of the change set."),
|
||||
fieldWithPath("tag").description("Tag associated with the change set, if any.").optional()
|
||||
.type(JsonFieldType.STRING));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -36,8 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*/
|
||||
@TestPropertySource(
|
||||
properties = "logging.file=src/test/resources/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/sample.log")
|
||||
public class LogFileWebEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class LogFileWebEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void logFile() throws Exception {
|
||||
@@ -48,8 +47,7 @@ public class LogFileWebEndpointDocumentationTests
|
||||
@Test
|
||||
public void logFileRange() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/logfile").header("Range", "bytes=0-1023"))
|
||||
.andExpect(status().isPartialContent())
|
||||
.andDo(MockMvcRestDocumentation.document("logfile/range"));
|
||||
.andExpect(status().isPartialContent()).andDo(MockMvcRestDocumentation.document("logfile/range"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,60 +51,49 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
public class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
private static final List<FieldDescriptor> levelFields = Arrays.asList(
|
||||
fieldWithPath("configuredLevel")
|
||||
.description("Configured level of the logger, if any.").optional(),
|
||||
fieldWithPath("effectiveLevel")
|
||||
.description("Effective level of the logger."));
|
||||
fieldWithPath("configuredLevel").description("Configured level of the logger, if any.").optional(),
|
||||
fieldWithPath("effectiveLevel").description("Effective level of the logger."));
|
||||
|
||||
@MockBean
|
||||
private LoggingSystem loggingSystem;
|
||||
|
||||
@Test
|
||||
public void allLoggers() throws Exception {
|
||||
given(this.loggingSystem.getSupportedLogLevels())
|
||||
.willReturn(EnumSet.allOf(LogLevel.class));
|
||||
given(this.loggingSystem.getLoggerConfigurations()).willReturn(Arrays.asList(
|
||||
new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO),
|
||||
new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG)));
|
||||
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
||||
given(this.loggingSystem.getLoggerConfigurations())
|
||||
.willReturn(Arrays.asList(new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO),
|
||||
new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG)));
|
||||
this.mockMvc.perform(get("/actuator/loggers")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("loggers/all", responseFields(
|
||||
fieldWithPath("levels")
|
||||
.description("Levels support by the logging system."),
|
||||
fieldWithPath("loggers").description("Loggers keyed by name."))
|
||||
.andWithPrefix("loggers.*.", levelFields)));
|
||||
.andDo(MockMvcRestDocumentation.document("loggers/all",
|
||||
responseFields(fieldWithPath("levels").description("Levels support by the logging system."),
|
||||
fieldWithPath("loggers").description("Loggers keyed by name."))
|
||||
.andWithPrefix("loggers.*.", levelFields)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logger() throws Exception {
|
||||
given(this.loggingSystem.getLoggerConfiguration("com.example")).willReturn(
|
||||
new LoggerConfiguration("com.example", LogLevel.INFO, LogLevel.INFO));
|
||||
this.mockMvc.perform(get("/actuator/loggers/com.example"))
|
||||
.andExpect(status().isOk()).andDo(MockMvcRestDocumentation
|
||||
.document("loggers/single", responseFields(levelFields)));
|
||||
given(this.loggingSystem.getLoggerConfiguration("com.example"))
|
||||
.willReturn(new LoggerConfiguration("com.example", LogLevel.INFO, LogLevel.INFO));
|
||||
this.mockMvc.perform(get("/actuator/loggers/com.example")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("loggers/single", responseFields(levelFields)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLogLevel() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(post("/actuator/loggers/com.example")
|
||||
.content("{\"configuredLevel\":\"debug\"}")
|
||||
.perform(post("/actuator/loggers/com.example").content("{\"configuredLevel\":\"debug\"}")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNoContent()).andDo(
|
||||
MockMvcRestDocumentation.document("loggers/set",
|
||||
requestFields(fieldWithPath("configuredLevel")
|
||||
.description("Level for the logger. May be"
|
||||
+ " omitted to clear the level.")
|
||||
.optional())));
|
||||
.andExpect(status().isNoContent())
|
||||
.andDo(MockMvcRestDocumentation.document("loggers/set", requestFields(fieldWithPath("configuredLevel")
|
||||
.description("Level for the logger. May be" + " omitted to clear the level.").optional())));
|
||||
verify(this.loggingSystem).setLogLevel("com.example", LogLevel.DEBUG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearLogLevel() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(post("/actuator/loggers/com.example").content("{}")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNoContent())
|
||||
.andDo(MockMvcRestDocumentation.document("loggers/clear"));
|
||||
.perform(post("/actuator/loggers/com.example").content("{}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNoContent()).andDo(MockMvcRestDocumentation.document("loggers/clear"));
|
||||
verify(this.loggingSystem).setLogLevel("com.example", null);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,8 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = "spring.main.web-application-type=reactive")
|
||||
public class MappingsEndpointReactiveDocumentationTests
|
||||
extends AbstractEndpointDocumentationTests {
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive")
|
||||
public class MappingsEndpointReactiveDocumentationTests extends AbstractEndpointDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
@@ -77,92 +75,61 @@ public class MappingsEndpointReactiveDocumentationTests
|
||||
|
||||
@Before
|
||||
public void webTestClient() {
|
||||
this.client = WebTestClient
|
||||
.bindToServer().filter(documentationConfiguration(this.restDocumentation)
|
||||
.snippets().withDefaults())
|
||||
this.client = WebTestClient.bindToServer()
|
||||
.filter(documentationConfiguration(this.restDocumentation).snippets().withDefaults())
|
||||
.baseUrl("http://localhost:" + this.port).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappings() throws Exception {
|
||||
List<FieldDescriptor> requestMappingConditions = Arrays.asList(
|
||||
requestMappingConditionField("")
|
||||
.description("Details of the request mapping conditions.")
|
||||
.optional(),
|
||||
requestMappingConditionField(".consumes")
|
||||
.description("Details of the consumes condition"),
|
||||
requestMappingConditionField(".consumes.[].mediaType")
|
||||
.description("Consumed media type."),
|
||||
requestMappingConditionField(".consumes.[].negated")
|
||||
.description("Whether the media type is negated."),
|
||||
requestMappingConditionField(".headers")
|
||||
.description("Details of the headers condition."),
|
||||
requestMappingConditionField(".headers.[].name")
|
||||
.description("Name of the header."),
|
||||
requestMappingConditionField(".headers.[].value")
|
||||
.description("Required value of the header, if any."),
|
||||
requestMappingConditionField(".headers.[].negated")
|
||||
.description("Whether the value is negated."),
|
||||
requestMappingConditionField(".methods")
|
||||
.description("HTTP methods that are handled."),
|
||||
requestMappingConditionField(".params")
|
||||
.description("Details of the params condition."),
|
||||
requestMappingConditionField(".params.[].name")
|
||||
.description("Name of the parameter."),
|
||||
requestMappingConditionField("").description("Details of the request mapping conditions.").optional(),
|
||||
requestMappingConditionField(".consumes").description("Details of the consumes condition"),
|
||||
requestMappingConditionField(".consumes.[].mediaType").description("Consumed media type."),
|
||||
requestMappingConditionField(".consumes.[].negated").description("Whether the media type is negated."),
|
||||
requestMappingConditionField(".headers").description("Details of the headers condition."),
|
||||
requestMappingConditionField(".headers.[].name").description("Name of the header."),
|
||||
requestMappingConditionField(".headers.[].value").description("Required value of the header, if any."),
|
||||
requestMappingConditionField(".headers.[].negated").description("Whether the value is negated."),
|
||||
requestMappingConditionField(".methods").description("HTTP methods that are handled."),
|
||||
requestMappingConditionField(".params").description("Details of the params condition."),
|
||||
requestMappingConditionField(".params.[].name").description("Name of the parameter."),
|
||||
requestMappingConditionField(".params.[].value")
|
||||
.description("Required value of the parameter, if any."),
|
||||
requestMappingConditionField(".params.[].negated")
|
||||
.description("Whether the value is negated."),
|
||||
requestMappingConditionField(".patterns").description(
|
||||
"Patterns identifying the paths handled by the mapping."),
|
||||
requestMappingConditionField(".produces")
|
||||
.description("Details of the produces condition."),
|
||||
requestMappingConditionField(".produces.[].mediaType")
|
||||
.description("Produced media type."),
|
||||
requestMappingConditionField(".produces.[].negated")
|
||||
.description("Whether the media type is negated."));
|
||||
requestMappingConditionField(".params.[].negated").description("Whether the value is negated."),
|
||||
requestMappingConditionField(".patterns")
|
||||
.description("Patterns identifying the paths handled by the mapping."),
|
||||
requestMappingConditionField(".produces").description("Details of the produces condition."),
|
||||
requestMappingConditionField(".produces.[].mediaType").description("Produced media type."),
|
||||
requestMappingConditionField(".produces.[].negated").description("Whether the media type is negated."));
|
||||
List<FieldDescriptor> handlerMethod = Arrays.asList(
|
||||
fieldWithPath("*.[].details.handlerMethod").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Details of the method, if any, "
|
||||
+ "that will handle requests to this mapping."),
|
||||
fieldWithPath("*.[].details.handlerMethod.className")
|
||||
.type(JsonFieldType.STRING)
|
||||
fieldWithPath("*.[].details.handlerMethod").optional().type(JsonFieldType.OBJECT)
|
||||
.description("Details of the method, if any, " + "that will handle requests to this mapping."),
|
||||
fieldWithPath("*.[].details.handlerMethod.className").type(JsonFieldType.STRING)
|
||||
.description("Fully qualified name of the class of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.name")
|
||||
.type(JsonFieldType.STRING).description("Name of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.descriptor")
|
||||
.type(JsonFieldType.STRING)
|
||||
.description("Descriptor of the method as specified in the Java "
|
||||
+ "Language Specification."));
|
||||
fieldWithPath("*.[].details.handlerMethod.name").type(JsonFieldType.STRING)
|
||||
.description("Name of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.descriptor").type(JsonFieldType.STRING)
|
||||
.description("Descriptor of the method as specified in the Java " + "Language Specification."));
|
||||
List<FieldDescriptor> handlerFunction = Arrays.asList(
|
||||
fieldWithPath("*.[].details.handlerFunction").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Details of the function, if any, that will handle "
|
||||
+ "requests to this mapping."),
|
||||
fieldWithPath("*.[].details.handlerFunction.className")
|
||||
.type(JsonFieldType.STRING).description(
|
||||
"Fully qualified name of the class of the function."));
|
||||
fieldWithPath("*.[].details.handlerFunction").optional().type(JsonFieldType.OBJECT).description(
|
||||
"Details of the function, if any, that will handle " + "requests to this mapping."),
|
||||
fieldWithPath("*.[].details.handlerFunction.className").type(JsonFieldType.STRING)
|
||||
.description("Fully qualified name of the class of the function."));
|
||||
List<FieldDescriptor> dispatcherHandlerFields = new ArrayList<>(Arrays.asList(
|
||||
fieldWithPath("*")
|
||||
.description("Dispatcher handler mappings, if any, keyed by "
|
||||
+ "dispatcher handler bean name."),
|
||||
fieldWithPath("*").description(
|
||||
"Dispatcher handler mappings, if any, keyed by " + "dispatcher handler bean name."),
|
||||
fieldWithPath("*.[].details").optional().type(JsonFieldType.OBJECT)
|
||||
.description("Additional implementation-specific "
|
||||
+ "details about the mapping. Optional."),
|
||||
.description("Additional implementation-specific " + "details about the mapping. Optional."),
|
||||
fieldWithPath("*.[].handler").description("Handler for the mapping."),
|
||||
fieldWithPath("*.[].predicate")
|
||||
.description("Predicate for the mapping.")));
|
||||
fieldWithPath("*.[].predicate").description("Predicate for the mapping.")));
|
||||
dispatcherHandlerFields.addAll(requestMappingConditions);
|
||||
dispatcherHandlerFields.addAll(handlerMethod);
|
||||
dispatcherHandlerFields.addAll(handlerFunction);
|
||||
this.client.get().uri("/actuator/mappings").exchange().expectStatus().isOk()
|
||||
.expectBody()
|
||||
.consumeWith(document("mappings",
|
||||
responseFields(
|
||||
beneathPath("contexts.*.mappings.dispatcherHandlers")
|
||||
.withSubsectionId("dispatcher-handlers"),
|
||||
dispatcherHandlerFields)));
|
||||
this.client.get().uri("/actuator/mappings").exchange().expectStatus().isOk().expectBody()
|
||||
.consumeWith(document("mappings", responseFields(
|
||||
beneathPath("contexts.*.mappings.dispatcherHandlers").withSubsectionId("dispatcher-handlers"),
|
||||
dispatcherHandlerFields)));
|
||||
}
|
||||
|
||||
private FieldDescriptor requestMappingConditionField(String path) {
|
||||
@@ -184,8 +151,7 @@ public class MappingsEndpointReactiveDocumentationTests
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MappingsEndpoint mappingsEndpoint(
|
||||
Collection<MappingDescriptionProvider> descriptionProviders,
|
||||
public MappingsEndpoint mappingsEndpoint(Collection<MappingDescriptionProvider> descriptionProviders,
|
||||
ConfigurableApplicationContext context) {
|
||||
return new MappingsEndpoint(descriptionProviders, context);
|
||||
}
|
||||
@@ -205,10 +171,8 @@ public class MappingsEndpointReactiveDocumentationTests
|
||||
@RestController
|
||||
private static class ExampleController {
|
||||
|
||||
@PostMapping(path = "/",
|
||||
consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
|
||||
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo",
|
||||
params = "a!=alpha")
|
||||
@PostMapping(path = "/", consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
|
||||
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo", params = "a!=alpha")
|
||||
public String example() {
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ import static org.springframework.restdocs.webtestclient.WebTestClientRestDocume
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class MappingsEndpointServletDocumentationTests
|
||||
extends AbstractEndpointDocumentationTests {
|
||||
public class MappingsEndpointServletDocumentationTests extends AbstractEndpointDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
@@ -76,115 +75,76 @@ public class MappingsEndpointServletDocumentationTests
|
||||
|
||||
@Before
|
||||
public void webTestClient() {
|
||||
this.client = WebTestClient.bindToServer()
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
this.client = WebTestClient.bindToServer().filter(documentationConfiguration(this.restDocumentation))
|
||||
.baseUrl("http://localhost:" + this.port).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappings() throws Exception {
|
||||
ResponseFieldsSnippet commonResponseFields = responseFields(
|
||||
fieldWithPath("contexts")
|
||||
.description("Application contexts keyed by id."),
|
||||
fieldWithPath("contexts.*.mappings")
|
||||
.description("Mappings in the context, keyed by mapping type."),
|
||||
fieldWithPath("contexts").description("Application contexts keyed by id."),
|
||||
fieldWithPath("contexts.*.mappings").description("Mappings in the context, keyed by mapping type."),
|
||||
subsectionWithPath("contexts.*.mappings.dispatcherServlets")
|
||||
.description("Dispatcher servlet mappings, if any."),
|
||||
subsectionWithPath("contexts.*.mappings.servletFilters")
|
||||
.description("Servlet filter mappings, if any."),
|
||||
subsectionWithPath("contexts.*.mappings.servlets")
|
||||
.description("Servlet mappings, if any."),
|
||||
subsectionWithPath("contexts.*.mappings.servlets").description("Servlet mappings, if any."),
|
||||
subsectionWithPath("contexts.*.mappings.dispatcherHandlers")
|
||||
.description("Dispatcher handler mappings, if any.").optional()
|
||||
.type(JsonFieldType.OBJECT),
|
||||
.description("Dispatcher handler mappings, if any.").optional().type(JsonFieldType.OBJECT),
|
||||
parentIdField());
|
||||
List<FieldDescriptor> dispatcherServletFields = new ArrayList<>(Arrays.asList(
|
||||
fieldWithPath("*")
|
||||
.description("Dispatcher servlet mappings, if any, keyed by "
|
||||
+ "dispatcher servlet bean name."),
|
||||
fieldWithPath("*").description(
|
||||
"Dispatcher servlet mappings, if any, keyed by " + "dispatcher servlet bean name."),
|
||||
fieldWithPath("*.[].details").optional().type(JsonFieldType.OBJECT)
|
||||
.description("Additional implementation-specific "
|
||||
+ "details about the mapping. Optional."),
|
||||
.description("Additional implementation-specific " + "details about the mapping. Optional."),
|
||||
fieldWithPath("*.[].handler").description("Handler for the mapping."),
|
||||
fieldWithPath("*.[].predicate")
|
||||
.description("Predicate for the mapping.")));
|
||||
fieldWithPath("*.[].predicate").description("Predicate for the mapping.")));
|
||||
List<FieldDescriptor> requestMappingConditions = Arrays.asList(
|
||||
requestMappingConditionField("")
|
||||
.description("Details of the request mapping conditions.")
|
||||
.optional(),
|
||||
requestMappingConditionField(".consumes")
|
||||
.description("Details of the consumes condition"),
|
||||
requestMappingConditionField(".consumes.[].mediaType")
|
||||
.description("Consumed media type."),
|
||||
requestMappingConditionField(".consumes.[].negated")
|
||||
.description("Whether the media type is negated."),
|
||||
requestMappingConditionField(".headers")
|
||||
.description("Details of the headers condition."),
|
||||
requestMappingConditionField(".headers.[].name")
|
||||
.description("Name of the header."),
|
||||
requestMappingConditionField(".headers.[].value")
|
||||
.description("Required value of the header, if any."),
|
||||
requestMappingConditionField(".headers.[].negated")
|
||||
.description("Whether the value is negated."),
|
||||
requestMappingConditionField(".methods")
|
||||
.description("HTTP methods that are handled."),
|
||||
requestMappingConditionField(".params")
|
||||
.description("Details of the params condition."),
|
||||
requestMappingConditionField(".params.[].name")
|
||||
.description("Name of the parameter."),
|
||||
requestMappingConditionField("").description("Details of the request mapping conditions.").optional(),
|
||||
requestMappingConditionField(".consumes").description("Details of the consumes condition"),
|
||||
requestMappingConditionField(".consumes.[].mediaType").description("Consumed media type."),
|
||||
requestMappingConditionField(".consumes.[].negated").description("Whether the media type is negated."),
|
||||
requestMappingConditionField(".headers").description("Details of the headers condition."),
|
||||
requestMappingConditionField(".headers.[].name").description("Name of the header."),
|
||||
requestMappingConditionField(".headers.[].value").description("Required value of the header, if any."),
|
||||
requestMappingConditionField(".headers.[].negated").description("Whether the value is negated."),
|
||||
requestMappingConditionField(".methods").description("HTTP methods that are handled."),
|
||||
requestMappingConditionField(".params").description("Details of the params condition."),
|
||||
requestMappingConditionField(".params.[].name").description("Name of the parameter."),
|
||||
requestMappingConditionField(".params.[].value")
|
||||
.description("Required value of the parameter, if any."),
|
||||
requestMappingConditionField(".params.[].negated")
|
||||
.description("Whether the value is negated."),
|
||||
requestMappingConditionField(".patterns").description(
|
||||
"Patterns identifying the paths handled by the mapping."),
|
||||
requestMappingConditionField(".produces")
|
||||
.description("Details of the produces condition."),
|
||||
requestMappingConditionField(".produces.[].mediaType")
|
||||
.description("Produced media type."),
|
||||
requestMappingConditionField(".produces.[].negated")
|
||||
.description("Whether the media type is negated."));
|
||||
requestMappingConditionField(".params.[].negated").description("Whether the value is negated."),
|
||||
requestMappingConditionField(".patterns")
|
||||
.description("Patterns identifying the paths handled by the mapping."),
|
||||
requestMappingConditionField(".produces").description("Details of the produces condition."),
|
||||
requestMappingConditionField(".produces.[].mediaType").description("Produced media type."),
|
||||
requestMappingConditionField(".produces.[].negated").description("Whether the media type is negated."));
|
||||
List<FieldDescriptor> handlerMethod = Arrays.asList(
|
||||
fieldWithPath("*.[].details.handlerMethod").optional()
|
||||
.type(JsonFieldType.OBJECT)
|
||||
.description("Details of the method, if any, "
|
||||
+ "that will handle requests to this mapping."),
|
||||
fieldWithPath("*.[].details.handlerMethod").optional().type(JsonFieldType.OBJECT)
|
||||
.description("Details of the method, if any, " + "that will handle requests to this mapping."),
|
||||
fieldWithPath("*.[].details.handlerMethod.className")
|
||||
.description("Fully qualified name of the class of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.name")
|
||||
.description("Name of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.name").description("Name of the method."),
|
||||
fieldWithPath("*.[].details.handlerMethod.descriptor")
|
||||
.description("Descriptor of the method as specified in the Java "
|
||||
+ "Language Specification."));
|
||||
.description("Descriptor of the method as specified in the Java " + "Language Specification."));
|
||||
dispatcherServletFields.addAll(handlerMethod);
|
||||
dispatcherServletFields.addAll(requestMappingConditions);
|
||||
this.client.get().uri("/actuator/mappings").exchange().expectBody()
|
||||
.consumeWith(document(
|
||||
"mappings", commonResponseFields,
|
||||
responseFields(beneathPath(
|
||||
"contexts.*.mappings.dispatcherServlets")
|
||||
.withSubsectionId("dispatcher-servlets"),
|
||||
dispatcherServletFields),
|
||||
.consumeWith(document("mappings", commonResponseFields,
|
||||
responseFields(beneathPath("contexts.*.mappings.dispatcherServlets")
|
||||
.withSubsectionId("dispatcher-servlets"), dispatcherServletFields),
|
||||
responseFields(
|
||||
beneathPath("contexts.*.mappings.servletFilters")
|
||||
.withSubsectionId("servlet-filters"),
|
||||
fieldWithPath("[].servletNameMappings").description(
|
||||
"Names of the servlets to which the filter is mapped."),
|
||||
fieldWithPath("[].urlPatternMappings").description(
|
||||
"URL pattern to which the filter is mapped."),
|
||||
fieldWithPath("[].name")
|
||||
.description("Name of the filter."),
|
||||
fieldWithPath("[].className")
|
||||
.description("Class name of the filter")),
|
||||
responseFields(
|
||||
beneathPath("contexts.*.mappings.servlets")
|
||||
.withSubsectionId("servlets"),
|
||||
fieldWithPath("[].mappings")
|
||||
.description("Mappings of the servlet."),
|
||||
fieldWithPath("[].name")
|
||||
.description("Name of the servlet."),
|
||||
fieldWithPath("[].className")
|
||||
.description("Class name of the servlet"))));
|
||||
beneathPath("contexts.*.mappings.servletFilters").withSubsectionId("servlet-filters"),
|
||||
fieldWithPath("[].servletNameMappings")
|
||||
.description("Names of the servlets to which the filter is mapped."),
|
||||
fieldWithPath("[].urlPatternMappings")
|
||||
.description("URL pattern to which the filter is mapped."),
|
||||
fieldWithPath("[].name").description("Name of the filter."),
|
||||
fieldWithPath("[].className").description("Class name of the filter")),
|
||||
responseFields(beneathPath("contexts.*.mappings.servlets").withSubsectionId("servlets"),
|
||||
fieldWithPath("[].mappings").description("Mappings of the servlet."),
|
||||
fieldWithPath("[].name").description("Name of the servlet."),
|
||||
fieldWithPath("[].className").description("Class name of the servlet"))));
|
||||
}
|
||||
|
||||
private FieldDescriptor requestMappingConditionField(String path) {
|
||||
@@ -216,8 +176,7 @@ public class MappingsEndpointServletDocumentationTests
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MappingsEndpoint mappingsEndpoint(
|
||||
Collection<MappingDescriptionProvider> descriptionProviders,
|
||||
public MappingsEndpoint mappingsEndpoint(Collection<MappingDescriptionProvider> descriptionProviders,
|
||||
ConfigurableApplicationContext context) {
|
||||
return new MappingsEndpoint(descriptionProviders, context);
|
||||
}
|
||||
@@ -232,10 +191,8 @@ public class MappingsEndpointServletDocumentationTests
|
||||
@RestController
|
||||
private static class ExampleController {
|
||||
|
||||
@PostMapping(path = "/",
|
||||
consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
|
||||
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo",
|
||||
params = "a!=alpha")
|
||||
@PostMapping(path = "/", consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
|
||||
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo", params = "a!=alpha")
|
||||
public String example() {
|
||||
return "Hello World";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,43 +43,34 @@ public class MetricsEndpointDocumentationTests extends MockMvcEndpointDocumentat
|
||||
|
||||
@Test
|
||||
public void metricNames() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/metrics")).andExpect(status().isOk())
|
||||
.andDo(document("metrics/names", responseFields(fieldWithPath("names")
|
||||
.description("Names of the known metrics."))));
|
||||
this.mockMvc.perform(get("/actuator/metrics")).andExpect(status().isOk()).andDo(document("metrics/names",
|
||||
responseFields(fieldWithPath("names").description("Names of the known metrics."))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void metric() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/metrics/jvm.memory.max"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("metrics/metric", responseFields(
|
||||
fieldWithPath("name").description("Name of the metric"),
|
||||
fieldWithPath("description")
|
||||
.description("Description of the metric"),
|
||||
fieldWithPath("baseUnit").description("Base unit of the metric"),
|
||||
fieldWithPath("measurements")
|
||||
.description("Measurements of the metric"),
|
||||
fieldWithPath("measurements[].statistic")
|
||||
.description("Statistic of the measurement. ("
|
||||
+ describeEnumValues(Statistic.class) + ")."),
|
||||
fieldWithPath("measurements[].value")
|
||||
.description("Value of the measurement."),
|
||||
fieldWithPath("availableTags")
|
||||
.description("Tags that are available for drill-down."),
|
||||
fieldWithPath("availableTags[].tag")
|
||||
.description("Name of the tag."),
|
||||
fieldWithPath("availableTags[].values")
|
||||
.description("Possible values of the tag."))));
|
||||
this.mockMvc.perform(get("/actuator/metrics/jvm.memory.max")).andExpect(status().isOk())
|
||||
.andDo(document("metrics/metric",
|
||||
responseFields(fieldWithPath("name").description("Name of the metric"),
|
||||
fieldWithPath("description").description("Description of the metric"),
|
||||
fieldWithPath("baseUnit").description("Base unit of the metric"),
|
||||
fieldWithPath("measurements").description("Measurements of the metric"),
|
||||
fieldWithPath("measurements[].statistic").description(
|
||||
"Statistic of the measurement. (" + describeEnumValues(Statistic.class) + ")."),
|
||||
fieldWithPath("measurements[].value").description("Value of the measurement."),
|
||||
fieldWithPath("availableTags").description("Tags that are available for drill-down."),
|
||||
fieldWithPath("availableTags[].tag").description("Name of the tag."),
|
||||
fieldWithPath("availableTags[].values").description("Possible values of the tag."))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void metricWithTags() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/metrics/jvm.memory.max")
|
||||
.param("tag", "area:nonheap").param("tag", "id:Compressed Class Space"))
|
||||
this.mockMvc
|
||||
.perform(get("/actuator/metrics/jvm.memory.max").param("tag", "area:nonheap").param("tag",
|
||||
"id:Compressed Class Space"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("metrics/metric-with-tags",
|
||||
requestParameters(parameterWithName("tag").description(
|
||||
"A tag to use for drill-down in the form `name:value`."))));
|
||||
.andDo(document("metrics/metric-with-tags", requestParameters(parameterWithName("tag")
|
||||
.description("A tag to use for drill-down in the form `name:value`."))));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,8 +37,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public abstract class MockMvcEndpointDocumentationTests
|
||||
extends AbstractEndpointDocumentationTests {
|
||||
public abstract class MockMvcEndpointDocumentationTests extends AbstractEndpointDocumentationTests {
|
||||
|
||||
@Rule
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
@@ -51,9 +50,7 @@ public abstract class MockMvcEndpointDocumentationTests
|
||||
@Before
|
||||
public void before() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext)
|
||||
.apply(MockMvcRestDocumentation
|
||||
.documentationConfiguration(this.restDocumentation).uris())
|
||||
.build();
|
||||
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation).uris()).build();
|
||||
}
|
||||
|
||||
protected WebApplicationContext getApplicationContext() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,13 +36,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PrometheusScrapeEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class PrometheusScrapeEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void prometheus() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/prometheus")).andExpect(status().isOk())
|
||||
.andDo(document("prometheus"));
|
||||
this.mockMvc.perform(get("/actuator/prometheus")).andExpect(status().isOk()).andDo(document("prometheus"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -52,8 +50,8 @@ public class PrometheusScrapeEndpointDocumentationTests
|
||||
@Bean
|
||||
public PrometheusScrapeEndpoint endpoint() {
|
||||
CollectorRegistry collectorRegistry = new CollectorRegistry(true);
|
||||
PrometheusMeterRegistry meterRegistry = new PrometheusMeterRegistry(
|
||||
(key) -> null, collectorRegistry, Clock.SYSTEM);
|
||||
PrometheusMeterRegistry meterRegistry = new PrometheusMeterRegistry((key) -> null, collectorRegistry,
|
||||
Clock.SYSTEM);
|
||||
new JvmMemoryMetrics().bindTo(meterRegistry);
|
||||
return new PrometheusScrapeEndpoint(collectorRegistry);
|
||||
}
|
||||
|
||||
@@ -48,51 +48,40 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ScheduledTasksEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class ScheduledTasksEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void scheduledTasks() throws Exception {
|
||||
this.mockMvc.perform(get("/actuator/scheduledtasks")).andExpect(status().isOk())
|
||||
.andDo(document("scheduled-tasks",
|
||||
preprocessResponse(replacePattern(Pattern.compile(
|
||||
"org.*\\.ScheduledTasksEndpointDocumentationTests\\$"
|
||||
+ "TestConfiguration"),
|
||||
"com.example.Processor")),
|
||||
responseFields(
|
||||
fieldWithPath("cron").description("Cron tasks, if any."),
|
||||
targetFieldWithPrefix("cron.[]."),
|
||||
fieldWithPath("cron.[].expression")
|
||||
.description("Cron expression."),
|
||||
fieldWithPath("fixedDelay")
|
||||
.description("Fixed delay tasks, if any."),
|
||||
targetFieldWithPrefix("fixedDelay.[]."),
|
||||
initialDelayWithPrefix("fixedDelay.[]."),
|
||||
fieldWithPath("fixedDelay.[].interval").description(
|
||||
"Interval, in milliseconds, between the end of the last"
|
||||
+ " execution and the start of the next."),
|
||||
fieldWithPath("fixedRate")
|
||||
.description("Fixed rate tasks, if any."),
|
||||
targetFieldWithPrefix("fixedRate.[]."),
|
||||
fieldWithPath("fixedRate.[].interval").description(
|
||||
"Interval, in milliseconds, between the start of each execution."),
|
||||
initialDelayWithPrefix("fixedRate.[]."),
|
||||
fieldWithPath("custom").description(
|
||||
"Tasks with custom triggers, if any."),
|
||||
targetFieldWithPrefix("custom.[]."),
|
||||
fieldWithPath("custom.[].trigger")
|
||||
.description("Trigger for the task."))))
|
||||
this.mockMvc.perform(get("/actuator/scheduledtasks")).andExpect(status().isOk()).andDo(document(
|
||||
"scheduled-tasks",
|
||||
preprocessResponse(replacePattern(
|
||||
Pattern.compile("org.*\\.ScheduledTasksEndpointDocumentationTests\\$" + "TestConfiguration"),
|
||||
"com.example.Processor")),
|
||||
responseFields(fieldWithPath("cron").description("Cron tasks, if any."),
|
||||
targetFieldWithPrefix("cron.[]."),
|
||||
fieldWithPath("cron.[].expression").description("Cron expression."),
|
||||
fieldWithPath("fixedDelay").description("Fixed delay tasks, if any."),
|
||||
targetFieldWithPrefix("fixedDelay.[]."), initialDelayWithPrefix("fixedDelay.[]."),
|
||||
fieldWithPath("fixedDelay.[].interval")
|
||||
.description("Interval, in milliseconds, between the end of the last"
|
||||
+ " execution and the start of the next."),
|
||||
fieldWithPath("fixedRate").description("Fixed rate tasks, if any."),
|
||||
targetFieldWithPrefix("fixedRate.[]."),
|
||||
fieldWithPath("fixedRate.[].interval")
|
||||
.description("Interval, in milliseconds, between the start of each execution."),
|
||||
initialDelayWithPrefix("fixedRate.[]."),
|
||||
fieldWithPath("custom").description("Tasks with custom triggers, if any."),
|
||||
targetFieldWithPrefix("custom.[]."),
|
||||
fieldWithPath("custom.[].trigger").description("Trigger for the task."))))
|
||||
.andDo(MockMvcResultHandlers.print());
|
||||
}
|
||||
|
||||
private FieldDescriptor targetFieldWithPrefix(String prefix) {
|
||||
return fieldWithPath(prefix + "runnable.target")
|
||||
.description("Target that will be executed.");
|
||||
return fieldWithPath(prefix + "runnable.target").description("Target that will be executed.");
|
||||
}
|
||||
|
||||
private FieldDescriptor initialDelayWithPrefix(String prefix) {
|
||||
return fieldWithPath(prefix + "initialDelay")
|
||||
.description("Delay, in milliseconds, before first execution.");
|
||||
return fieldWithPath(prefix + "initialDelay").description("Delay, in milliseconds, before first execution.");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -122,8 +111,7 @@ public class ScheduledTasksEndpointDocumentationTests
|
||||
|
||||
@Bean
|
||||
public SchedulingConfigurer schedulingConfigurer() {
|
||||
return (registrar) -> registrar.addTriggerTask(new CustomTriggeredRunnable(),
|
||||
new CustomTrigger());
|
||||
return (registrar) -> registrar.addTriggerTask(new CustomTriggeredRunnable(), new CustomTrigger());
|
||||
}
|
||||
|
||||
static class CustomTrigger implements Trigger {
|
||||
|
||||
@@ -53,32 +53,25 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@TestPropertySource(
|
||||
properties = "spring.jackson.serialization.write-dates-as-timestamps=false")
|
||||
public class SessionsEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
@TestPropertySource(properties = "spring.jackson.serialization.write-dates-as-timestamps=false")
|
||||
public class SessionsEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
private static final Session sessionOne = createSession(
|
||||
Instant.now().minusSeconds(60 * 60 * 12), Instant.now().minusSeconds(45));
|
||||
private static final Session sessionOne = createSession(Instant.now().minusSeconds(60 * 60 * 12),
|
||||
Instant.now().minusSeconds(45));
|
||||
|
||||
private static final Session sessionTwo = createSession(
|
||||
"4db5efcc-99cb-4d05-a52c-b49acfbb7ea9",
|
||||
private static final Session sessionTwo = createSession("4db5efcc-99cb-4d05-a52c-b49acfbb7ea9",
|
||||
Instant.now().minusSeconds(60 * 60 * 5), Instant.now().minusSeconds(37));
|
||||
|
||||
private static final Session sessionThree = createSession(
|
||||
Instant.now().minusSeconds(60 * 60 * 2), Instant.now().minusSeconds(12));
|
||||
private static final Session sessionThree = createSession(Instant.now().minusSeconds(60 * 60 * 2),
|
||||
Instant.now().minusSeconds(12));
|
||||
|
||||
private static final List<FieldDescriptor> sessionFields = Arrays.asList(
|
||||
fieldWithPath("id").description("ID of the session."),
|
||||
fieldWithPath("attributeNames")
|
||||
.description("Names of the attributes stored in the session."),
|
||||
fieldWithPath("creationTime")
|
||||
.description("Timestamp of when the session was created."),
|
||||
fieldWithPath("lastAccessedTime")
|
||||
.description("Timestamp of when the session was last accessed."),
|
||||
fieldWithPath("maxInactiveInterval")
|
||||
.description("Maximum permitted period of inactivity, in seconds, "
|
||||
+ "before the session will expire."),
|
||||
fieldWithPath("attributeNames").description("Names of the attributes stored in the session."),
|
||||
fieldWithPath("creationTime").description("Timestamp of when the session was created."),
|
||||
fieldWithPath("lastAccessedTime").description("Timestamp of when the session was last accessed."),
|
||||
fieldWithPath("maxInactiveInterval").description(
|
||||
"Maximum permitted period of inactivity, in seconds, " + "before the session will expire."),
|
||||
fieldWithPath("expired").description("Whether the session has expired."));
|
||||
|
||||
@MockBean
|
||||
@@ -91,14 +84,11 @@ public class SessionsEndpointDocumentationTests
|
||||
sessions.put(sessionTwo.getId(), sessionTwo);
|
||||
sessions.put(sessionThree.getId(), sessionThree);
|
||||
given(this.sessionRepository.findByPrincipalName("alice")).willReturn(sessions);
|
||||
this.mockMvc.perform(get("/actuator/sessions").param("username", "alice"))
|
||||
.andExpect(status().isOk())
|
||||
this.mockMvc.perform(get("/actuator/sessions").param("username", "alice")).andExpect(status().isOk())
|
||||
.andDo(document("sessions/username",
|
||||
responseFields(fieldWithPath("sessions")
|
||||
.description("Sessions for the given username."))
|
||||
.andWithPrefix("sessions.[].", sessionFields),
|
||||
requestParameters(parameterWithName("username")
|
||||
.description("Name of the user."))));
|
||||
responseFields(fieldWithPath("sessions").description("Sessions for the given username."))
|
||||
.andWithPrefix("sessions.[].", sessionFields),
|
||||
requestParameters(parameterWithName("username").description("Name of the user."))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,26 +98,22 @@ public class SessionsEndpointDocumentationTests
|
||||
sessions.put(sessionTwo.getId(), sessionTwo);
|
||||
sessions.put(sessionThree.getId(), sessionThree);
|
||||
given(this.sessionRepository.findById(sessionTwo.getId())).willReturn(sessionTwo);
|
||||
this.mockMvc.perform(get("/actuator/sessions/{id}", sessionTwo.getId()))
|
||||
.andExpect(status().isOk())
|
||||
this.mockMvc.perform(get("/actuator/sessions/{id}", sessionTwo.getId())).andExpect(status().isOk())
|
||||
.andDo(document("sessions/id", responseFields(sessionFields)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteASession() throws Exception {
|
||||
this.mockMvc.perform(delete("/actuator/sessions/{id}", sessionTwo.getId()))
|
||||
.andExpect(status().isNoContent()).andDo(document("sessions/delete"));
|
||||
this.mockMvc.perform(delete("/actuator/sessions/{id}", sessionTwo.getId())).andExpect(status().isNoContent())
|
||||
.andDo(document("sessions/delete"));
|
||||
verify(this.sessionRepository).deleteById(sessionTwo.getId());
|
||||
}
|
||||
|
||||
private static MapSession createSession(Instant creationTime,
|
||||
Instant lastAccessedTime) {
|
||||
return createSession(UUID.randomUUID().toString(), creationTime,
|
||||
lastAccessedTime);
|
||||
private static MapSession createSession(Instant creationTime, Instant lastAccessedTime) {
|
||||
return createSession(UUID.randomUUID().toString(), creationTime, lastAccessedTime);
|
||||
}
|
||||
|
||||
private static MapSession createSession(String id, Instant creationTime,
|
||||
Instant lastAccessedTime) {
|
||||
private static MapSession createSession(String id, Instant creationTime, Instant lastAccessedTime) {
|
||||
MapSession session = new MapSession(id);
|
||||
session.setCreationTime(creationTime);
|
||||
session.setLastAccessedTime(lastAccessedTime);
|
||||
@@ -139,8 +125,7 @@ public class SessionsEndpointDocumentationTests
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public SessionsEndpoint endpoint(
|
||||
FindByIndexNameSessionRepository<?> sessionRepository) {
|
||||
public SessionsEndpoint endpoint(FindByIndexNameSessionRepository<?> sessionRepository) {
|
||||
return new SessionsEndpoint(sessionRepository);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,15 +36,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ShutdownEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class ShutdownEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void shutdown() throws Exception {
|
||||
this.mockMvc.perform(post("/actuator/shutdown")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("shutdown",
|
||||
responseFields(fieldWithPath("message").description(
|
||||
"Message describing the result of the request."))));
|
||||
.andDo(MockMvcRestDocumentation.document("shutdown", responseFields(
|
||||
fieldWithPath("message").description("Message describing the result of the request."))));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -40,8 +40,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ThreadDumpEndpointDocumentationTests
|
||||
extends MockMvcEndpointDocumentationTests {
|
||||
public class ThreadDumpEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void threadDump() throws Exception {
|
||||
@@ -62,151 +61,102 @@ public class ThreadDumpEndpointDocumentationTests
|
||||
}
|
||||
}).start();
|
||||
this.mockMvc.perform(get("/actuator/threaddump")).andExpect(status().isOk())
|
||||
.andDo(MockMvcRestDocumentation.document("threaddump",
|
||||
preprocessResponse(limit("threads")),
|
||||
responseFields(
|
||||
fieldWithPath("threads").description("JVM's threads."),
|
||||
fieldWithPath("threads.[].blockedCount").description(
|
||||
"Total number of times that the thread has been "
|
||||
+ "blocked."),
|
||||
fieldWithPath("threads.[].blockedTime").description(
|
||||
"Time in milliseconds that the thread has spent "
|
||||
+ "blocked. -1 if thread contention "
|
||||
+ "monitoring is disabled."),
|
||||
.andDo(MockMvcRestDocumentation.document("threaddump", preprocessResponse(limit("threads")),
|
||||
responseFields(fieldWithPath("threads").description("JVM's threads."),
|
||||
fieldWithPath("threads.[].blockedCount")
|
||||
.description("Total number of times that the thread has been " + "blocked."),
|
||||
fieldWithPath("threads.[].blockedTime")
|
||||
.description("Time in milliseconds that the thread has spent "
|
||||
+ "blocked. -1 if thread contention " + "monitoring is disabled."),
|
||||
fieldWithPath("threads.[].daemon")
|
||||
.description("Whether the thread is a daemon "
|
||||
+ "thread. Only available on Java 9 or "
|
||||
+ "later.")
|
||||
+ "thread. Only available on Java 9 or " + "later.")
|
||||
.optional().type(JsonFieldType.BOOLEAN),
|
||||
fieldWithPath("threads.[].inNative").description(
|
||||
"Whether the thread is executing native code."),
|
||||
fieldWithPath("threads.[].lockName")
|
||||
.description(
|
||||
"Description of the object on which the "
|
||||
+ "thread is blocked, if any.")
|
||||
fieldWithPath("threads.[].inNative")
|
||||
.description("Whether the thread is executing native code."),
|
||||
fieldWithPath("threads.[].lockName").description(
|
||||
"Description of the object on which the " + "thread is blocked, if any.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].lockInfo")
|
||||
.description(
|
||||
"Object for which the thread is blocked "
|
||||
+ "waiting.")
|
||||
.optional().type(JsonFieldType.OBJECT),
|
||||
.description("Object for which the thread is blocked " + "waiting.").optional()
|
||||
.type(JsonFieldType.OBJECT),
|
||||
fieldWithPath("threads.[].lockInfo.className")
|
||||
.description(
|
||||
"Fully qualified class name of the lock"
|
||||
+ " object.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
.description("Fully qualified class name of the lock" + " object.").optional()
|
||||
.type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].lockInfo.identityHashCode")
|
||||
.description(
|
||||
"Identity hash code of the lock object.")
|
||||
.optional().type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("threads.[].lockedMonitors").description(
|
||||
"Monitors locked by this thread, if any"),
|
||||
.description("Identity hash code of the lock object.").optional()
|
||||
.type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("threads.[].lockedMonitors")
|
||||
.description("Monitors locked by this thread, if any"),
|
||||
fieldWithPath("threads.[].lockedMonitors.[].className")
|
||||
.description("Class name of the lock object.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath(
|
||||
"threads.[].lockedMonitors.[].identityHashCode")
|
||||
.description(
|
||||
"Identity hash code of the lock "
|
||||
+ "object.")
|
||||
.optional().type(JsonFieldType.NUMBER),
|
||||
fieldWithPath(
|
||||
"threads.[].lockedMonitors.[].lockedStackDepth")
|
||||
.description(
|
||||
"Stack depth where the monitor "
|
||||
+ "was locked.")
|
||||
.optional().type(JsonFieldType.NUMBER),
|
||||
subsectionWithPath(
|
||||
"threads.[].lockedMonitors.[].lockedStackFrame")
|
||||
.description(
|
||||
"Stack frame that locked the "
|
||||
+ "monitor.")
|
||||
.optional().type(JsonFieldType.OBJECT),
|
||||
.description("Class name of the lock object.").optional()
|
||||
.type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].lockedMonitors.[].identityHashCode")
|
||||
.description("Identity hash code of the lock " + "object.").optional()
|
||||
.type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("threads.[].lockedMonitors.[].lockedStackDepth")
|
||||
.description("Stack depth where the monitor " + "was locked.").optional()
|
||||
.type(JsonFieldType.NUMBER),
|
||||
subsectionWithPath("threads.[].lockedMonitors.[].lockedStackFrame")
|
||||
.description("Stack frame that locked the " + "monitor.").optional()
|
||||
.type(JsonFieldType.OBJECT),
|
||||
fieldWithPath("threads.[].lockedSynchronizers")
|
||||
.description(
|
||||
"Synchronizers locked by this thread."),
|
||||
fieldWithPath(
|
||||
"threads.[].lockedSynchronizers.[].className")
|
||||
.description("Class name of the locked "
|
||||
+ "synchronizer.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath(
|
||||
"threads.[].lockedSynchronizers.[].identityHashCode")
|
||||
.description(
|
||||
"Identity hash code of the locked "
|
||||
+ "synchronizer.")
|
||||
.optional().type(JsonFieldType.NUMBER),
|
||||
.description("Synchronizers locked by this thread."),
|
||||
fieldWithPath("threads.[].lockedSynchronizers.[].className").description(
|
||||
"Class name of the locked " + "synchronizer.").optional()
|
||||
.type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].lockedSynchronizers.[].identityHashCode").description(
|
||||
"Identity hash code of the locked " + "synchronizer.").optional()
|
||||
.type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("threads.[].lockOwnerId").description(
|
||||
"ID of the thread that owns the object on which "
|
||||
+ "the thread is blocked. `-1` if the "
|
||||
+ "thread is not blocked."),
|
||||
+ "the thread is blocked. `-1` if the " + "thread is not blocked."),
|
||||
fieldWithPath("threads.[].lockOwnerName")
|
||||
.description("Name of the thread that owns the "
|
||||
+ "object on which the thread is "
|
||||
+ "blocked, if any.")
|
||||
+ "object on which the thread is " + "blocked, if any.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].priority")
|
||||
.description("Priority of the thread. Only "
|
||||
+ "available on Java 9 or later.")
|
||||
.description("Priority of the thread. Only " + "available on Java 9 or later.")
|
||||
.optional().type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("threads.[].stackTrace")
|
||||
.description("Stack trace of the thread."),
|
||||
fieldWithPath("threads.[].stackTrace.[].classLoaderName")
|
||||
.description("Name of the class loader of the "
|
||||
+ "class that contains the execution "
|
||||
fieldWithPath("threads.[].stackTrace").description("Stack trace of the thread."),
|
||||
fieldWithPath("threads.[].stackTrace.[].classLoaderName").description(
|
||||
"Name of the class loader of the " + "class that contains the execution "
|
||||
+ "point identified by this entry, if "
|
||||
+ "any. Only available on Java 9 or "
|
||||
+ "later.")
|
||||
+ "any. Only available on Java 9 or " + "later.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].stackTrace.[].className")
|
||||
.description(
|
||||
"Name of the class that contains the "
|
||||
+ "execution point identified "
|
||||
+ "by this entry."),
|
||||
fieldWithPath("threads.[].stackTrace.[].className").description(
|
||||
"Name of the class that contains the " + "execution point identified "
|
||||
+ "by this entry."),
|
||||
fieldWithPath("threads.[].stackTrace.[].fileName")
|
||||
.description("Name of the source file that "
|
||||
+ "contains the execution point "
|
||||
.description("Name of the source file that " + "contains the execution point "
|
||||
+ "identified by this entry, if any.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].stackTrace.[].lineNumber")
|
||||
.description("Line number of the execution "
|
||||
+ "point identified by this entry. "
|
||||
+ "Negative if unknown."),
|
||||
fieldWithPath("threads.[].stackTrace.[].methodName")
|
||||
.description("Name of the method."),
|
||||
+ "point identified by this entry. " + "Negative if unknown."),
|
||||
fieldWithPath("threads.[].stackTrace.[].methodName").description("Name of the method."),
|
||||
fieldWithPath("threads.[].stackTrace.[].moduleName")
|
||||
.description("Name of the module that contains "
|
||||
+ "the execution point identified by "
|
||||
+ "this entry, if any. Only available "
|
||||
+ "on Java 9 or later.")
|
||||
+ "this entry, if any. Only available " + "on Java 9 or later.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].stackTrace.[].moduleVersion")
|
||||
.description("Version of the module that "
|
||||
+ "contains the execution point "
|
||||
.description("Version of the module that " + "contains the execution point "
|
||||
+ "identified by this entry, if any. "
|
||||
+ "Only available on Java 9 or later.")
|
||||
.optional().type(JsonFieldType.STRING),
|
||||
fieldWithPath("threads.[].stackTrace.[].nativeMethod")
|
||||
.description(
|
||||
"Whether the execution point is a native "
|
||||
+ "method."),
|
||||
fieldWithPath("threads.[].suspended")
|
||||
.description("Whether the thread is suspended."),
|
||||
fieldWithPath("threads.[].threadId")
|
||||
.description("ID of the thread."),
|
||||
fieldWithPath("threads.[].threadName")
|
||||
.description("Name of the thread."),
|
||||
fieldWithPath("threads.[].threadState")
|
||||
.description("State of the thread ("
|
||||
+ describeEnumValues(Thread.State.class)
|
||||
+ ")."),
|
||||
.description("Whether the execution point is a native " + "method."),
|
||||
fieldWithPath("threads.[].suspended").description("Whether the thread is suspended."),
|
||||
fieldWithPath("threads.[].threadId").description("ID of the thread."),
|
||||
fieldWithPath("threads.[].threadName").description("Name of the thread."),
|
||||
fieldWithPath("threads.[].threadState").description(
|
||||
"State of the thread (" + describeEnumValues(Thread.State.class) + ")."),
|
||||
fieldWithPath("threads.[].waitedCount").description(
|
||||
"Total number of times that the thread has waited"
|
||||
+ " for notification."),
|
||||
fieldWithPath("threads.[].waitedTime").description(
|
||||
"Time in milliseconds that the thread has spent "
|
||||
+ "waiting. -1 if thread contention "
|
||||
+ "monitoring is disabled"))));
|
||||
"Total number of times that the thread has waited" + " for notification."),
|
||||
fieldWithPath("threads.[].waitedTime")
|
||||
.description("Time in milliseconds that the thread has spent "
|
||||
+ "waiting. -1 if thread contention " + "monitoring is disabled"))));
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,24 +49,21 @@ public class JerseyWebEndpointManagementContextConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void resourceConfigCustomizerForEndpointsIsAutoConfigured() {
|
||||
this.runner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ResourceConfigCustomizer.class));
|
||||
this.runner.run((context) -> assertThat(context).hasSingleBean(ResourceConfigCustomizer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationIsConditionalOnServletWebApplication() {
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations
|
||||
.of(JerseySameManagementContextConfiguration.class));
|
||||
contextRunner.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(JerseySameManagementContextConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(JerseySameManagementContextConfiguration.class));
|
||||
contextRunner
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JerseySameManagementContextConfiguration.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationIsConditionalOnClassResourceConfig() {
|
||||
this.runner.withClassLoader(new FilteredClassLoader(ResourceConfig.class))
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(JerseySameManagementContextConfiguration.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JerseySameManagementContextConfiguration.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,8 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class EnvironmentEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(EnvironmentEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(EnvironmentEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
@@ -51,8 +50,7 @@ public class EnvironmentEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.env.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(EnvironmentEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(EnvironmentEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -62,24 +60,20 @@ public class EnvironmentEndpointAutoConfigurationTests {
|
||||
.run(validateSystemProperties("******", "123456"));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableApplicationContext> validateSystemProperties(
|
||||
String dbPassword, String apiKey) {
|
||||
private ContextConsumer<AssertableApplicationContext> validateSystemProperties(String dbPassword, String apiKey) {
|
||||
return (context) -> {
|
||||
assertThat(context).hasSingleBean(EnvironmentEndpoint.class);
|
||||
EnvironmentEndpoint endpoint = context.getBean(EnvironmentEndpoint.class);
|
||||
EnvironmentDescriptor env = endpoint.environment(null);
|
||||
Map<String, PropertyValueDescriptor> systemProperties = getSource(
|
||||
"systemProperties", env).getProperties();
|
||||
assertThat(systemProperties.get("dbPassword").getValue())
|
||||
.isEqualTo(dbPassword);
|
||||
Map<String, PropertyValueDescriptor> systemProperties = getSource("systemProperties", env).getProperties();
|
||||
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo(dbPassword);
|
||||
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo(apiKey);
|
||||
};
|
||||
}
|
||||
|
||||
private PropertySourceDescriptor getSource(String name,
|
||||
EnvironmentDescriptor descriptor) {
|
||||
return descriptor.getPropertySources().stream()
|
||||
.filter((source) -> name.equals(source.getName())).findFirst().get();
|
||||
private PropertySourceDescriptor getSource(String name, EnvironmentDescriptor descriptor) {
|
||||
return descriptor.getPropertySources().stream().filter((source) -> name.equals(source.getName())).findFirst()
|
||||
.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,21 +36,18 @@ import static org.mockito.Mockito.mock;
|
||||
public class FlywayEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(FlywayEndpointAutoConfiguration.class))
|
||||
.withConfiguration(AutoConfigurations.of(FlywayEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(FlywayConfiguration.class);
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(FlywayEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(FlywayEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.flyway.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(FlywayEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(FlywayEndpoint.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,34 +44,28 @@ import static org.mockito.Mockito.verify;
|
||||
*/
|
||||
public class HealthEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class));
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void healthEndpointShowDetailsDefault() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class)
|
||||
.run((context) -> {
|
||||
ReactiveHealthIndicator indicator = context.getBean(
|
||||
"reactiveHealthIndicator", ReactiveHealthIndicator.class);
|
||||
verify(indicator, never()).health();
|
||||
Health health = context.getBean(HealthEndpoint.class).health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(health.getDetails()).isNotEmpty();
|
||||
verify(indicator, times(1)).health();
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class).run((context) -> {
|
||||
ReactiveHealthIndicator indicator = context.getBean("reactiveHealthIndicator",
|
||||
ReactiveHealthIndicator.class);
|
||||
verify(indicator, never()).health();
|
||||
Health health = context.getBean(HealthEndpoint.class).health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(health.getDetails()).isNotEmpty();
|
||||
verify(indicator, times(1)).health();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthEndpointAdaptReactiveHealthIndicator() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class)
|
||||
.run((context) -> {
|
||||
ReactiveHealthIndicator indicator = context.getBean(
|
||||
"reactiveHealthIndicator", ReactiveHealthIndicator.class);
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class).run((context) -> {
|
||||
ReactiveHealthIndicator indicator = context.getBean("reactiveHealthIndicator",
|
||||
ReactiveHealthIndicator.class);
|
||||
verify(indicator, never()).health();
|
||||
Health health = context.getBean(HealthEndpoint.class).health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
@@ -82,21 +76,17 @@ public class HealthEndpointAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void healthEndpointMergeRegularAndReactive() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.withUserConfiguration(HealthIndicatorConfiguration.class,
|
||||
ReactiveHealthIndicatorConfiguration.class)
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.withUserConfiguration(HealthIndicatorConfiguration.class, ReactiveHealthIndicatorConfiguration.class)
|
||||
.run((context) -> {
|
||||
HealthIndicator indicator = context.getBean("simpleHealthIndicator",
|
||||
HealthIndicator.class);
|
||||
ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
|
||||
"reactiveHealthIndicator", ReactiveHealthIndicator.class);
|
||||
HealthIndicator indicator = context.getBean("simpleHealthIndicator", HealthIndicator.class);
|
||||
ReactiveHealthIndicator reactiveHealthIndicator = context.getBean("reactiveHealthIndicator",
|
||||
ReactiveHealthIndicator.class);
|
||||
verify(indicator, never()).health();
|
||||
verify(reactiveHealthIndicator, never()).health();
|
||||
Health health = context.getBean(HealthEndpoint.class).health();
|
||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
||||
assertThat(health.getDetails()).containsOnlyKeys("simple",
|
||||
"reactive");
|
||||
assertThat(health.getDetails()).containsOnlyKeys("simple", "reactive");
|
||||
verify(indicator, times(1)).health();
|
||||
verify(reactiveHealthIndicator, times(1)).health();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,347 +52,258 @@ import static org.mockito.Mockito.mock;
|
||||
public class HealthEndpointWebExtensionTests {
|
||||
|
||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withUserConfiguration(HealthIndicatorsConfiguration.class).withConfiguration(
|
||||
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class));
|
||||
.withUserConfiguration(HealthIndicatorsConfiguration.class).withConfiguration(AutoConfigurations
|
||||
.of(HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateExtensionBeans() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(HealthEndpointWebExtension.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HealthEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenHealthEndpointIsDisabledShouldNotCreateExtensionBeans() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(HealthEndpointWebExtension.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(HealthEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWithCustomHealthMappingShouldMapStatusCode() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.health.status.http-mapping.CUSTOM=500")
|
||||
.run((context) -> {
|
||||
Object extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
|
||||
.getField(extension, "responseMapper");
|
||||
Class<SecurityContext> securityContext = SecurityContext.class;
|
||||
assertThat(responseMapper
|
||||
.map(Health.down().build(), mock(securityContext))
|
||||
.getStatus()).isEqualTo(503);
|
||||
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(),
|
||||
mock(securityContext)).getStatus()).isEqualTo(503);
|
||||
assertThat(responseMapper
|
||||
.map(Health.status("CUSTOM").build(), mock(securityContext))
|
||||
.getStatus()).isEqualTo(500);
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.health.status.http-mapping.CUSTOM=500").run((context) -> {
|
||||
Object extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
|
||||
.getField(extension, "responseMapper");
|
||||
Class<SecurityContext> securityContext = SecurityContext.class;
|
||||
assertThat(responseMapper.map(Health.down().build(), mock(securityContext)).getStatus()).isEqualTo(503);
|
||||
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(), mock(securityContext)).getStatus())
|
||||
.isEqualTo(503);
|
||||
assertThat(responseMapper.map(Health.status("CUSTOM").build(), mock(securityContext)).getStatus())
|
||||
.isEqualTo(500);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersAreNotShownDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertThat(
|
||||
extension.health(mock(SecurityContext.class)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(mock(SecurityContext.class)).getBody().getDetails()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersAreNotShownDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertThat(extension.health(securityContext).getBody().getDetails())
|
||||
.isEmpty();
|
||||
assertThat(extension.health(securityContext).getBody().getDetails()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersWhenAuthorizedCanBeShownDetails() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized")
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
assertThat(extension.health(securityContext).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertThat(extension.health(securityContext).getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersCanBeShownDetails() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(null).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(null).getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detailsCanBeHiddenFromAuthenticatedUsers() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=never")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(mock(SecurityContext.class)).getBody()
|
||||
.getDetails()).isEmpty();
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(mock(SecurityContext.class)).getBody().getDetails()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detailsCanBeHiddenFromUnauthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
|
||||
assertThat(extension.health(securityContext).getBody().getDetails())
|
||||
.isEmpty();
|
||||
assertThat(extension.health(securityContext).getBody().getDetails()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detailsCanBeShownToAuthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
|
||||
assertThat(extension.health(securityContext).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
assertThat(extension.health(securityContext).getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersAreNotShownComponentByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(
|
||||
extension.healthForComponent(mock(SecurityContext.class), "simple"));
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponent(mock(SecurityContext.class), "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersAreNotShownComponentByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertDetailsNotFound(
|
||||
extension.healthForComponent(securityContext, "simple"));
|
||||
assertDetailsNotFound(extension.healthForComponent(securityContext, "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersWhenAuthorizedCanBeShownComponent() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized")
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
assertSimpleComponent(
|
||||
extension.healthForComponent(securityContext, "simple"));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertSimpleComponent(extension.healthForComponent(securityContext, "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersCanBeShownComponent() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertSimpleComponent(extension.healthForComponent(null, "simple"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertSimpleComponent(extension.healthForComponent(null, "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentCanBeHiddenFromAuthenticatedUsers() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=never")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension
|
||||
.healthForComponent(mock(SecurityContext.class), "simple"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponent(mock(SecurityContext.class), "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentCanBeHiddenFromUnauthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
|
||||
assertDetailsNotFound(
|
||||
extension.healthForComponent(securityContext, "simple"));
|
||||
assertDetailsNotFound(extension.healthForComponent(securityContext, "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentCanBeShownToAuthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
|
||||
assertSimpleComponent(
|
||||
extension.healthForComponent(securityContext, "simple"));
|
||||
assertSimpleComponent(extension.healthForComponent(securityContext, "simple"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentThatDoesNotExistMapTo404() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(
|
||||
extension.healthForComponent(null, "does-not-exist"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponent(null, "does-not-exist"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersAreNotShownComponentInstanceByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(
|
||||
mock(SecurityContext.class), "composite", "one"));
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(
|
||||
extension.healthForComponentInstance(mock(SecurityContext.class), "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersAreNotShownComponentInstanceByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(securityContext,
|
||||
"composite", "one"));
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(securityContext, "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersWhenAuthorizedCanBeShownComponentInstance() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized")
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
assertSimpleComponent(extension.healthForComponentInstance(
|
||||
securityContext, "composite", "one"));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertSimpleComponent(extension.healthForComponentInstance(securityContext, "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersCanBeShownComponentInstance() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertSimpleComponent(extension.healthForComponentInstance(null,
|
||||
"composite", "one"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertSimpleComponent(extension.healthForComponentInstance(null, "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentInstanceCanBeHiddenFromAuthenticatedUsers() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=never")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(
|
||||
mock(SecurityContext.class), "composite", "one"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(
|
||||
extension.healthForComponentInstance(mock(SecurityContext.class), "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentInstanceCanBeHiddenFromUnauthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(
|
||||
securityContext, "composite", "one"));
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(securityContext, "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentInstanceCanBeShownToAuthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
|
||||
assertSimpleComponent(extension.healthForComponentInstance(
|
||||
securityContext, "composite", "one"));
|
||||
assertSimpleComponent(extension.healthForComponentInstance(securityContext, "composite", "one"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentInstanceThatDoesNotExistMapTo404() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(null,
|
||||
"composite", "does-not-exist"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
assertDetailsNotFound(extension.healthForComponentInstance(null, "composite", "does-not-exist"));
|
||||
});
|
||||
}
|
||||
|
||||
private void assertDetailsNotFound(WebEndpointResponse<?> response) {
|
||||
@@ -407,17 +318,13 @@ public class HealthEndpointWebExtensionTests {
|
||||
|
||||
@Test
|
||||
public void roleCanBeCustomized() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ADMIN").run((context) -> {
|
||||
HealthEndpointWebExtension extension = context
|
||||
.getBean(HealthEndpointWebExtension.class);
|
||||
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ADMIN")).willReturn(true);
|
||||
assertThat(extension.health(securityContext).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
assertThat(extension.health(securityContext).getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -434,8 +341,7 @@ public class HealthEndpointWebExtensionTests {
|
||||
Map<String, HealthIndicator> nestedIndicators = new HashMap<>();
|
||||
nestedIndicators.put("one", simpleHealthIndicator());
|
||||
nestedIndicators.put("two", () -> Health.up().build());
|
||||
return new CompositeHealthIndicator(new OrderedHealthAggregator(),
|
||||
nestedIndicators);
|
||||
return new CompositeHealthIndicator(new OrderedHealthAggregator(), nestedIndicators);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,14 +43,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class HealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runWhenNoOtherIndicatorsShouldCreateDefaultApplicationHealthIndicator() {
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).getBean(HealthIndicator.class)
|
||||
.isInstanceOf(ApplicationHealthIndicator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).getBean(HealthIndicator.class)
|
||||
.isInstanceOf(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,17 +61,15 @@ public class HealthIndicatorAutoConfigurationTests {
|
||||
@Test
|
||||
public void runWhenHasDefaultsDisabledAndNoSingleIndicatorEnabledShouldCreateDefaultApplicationHealthIndicator() {
|
||||
this.contextRunner.withUserConfiguration(CustomHealthIndicatorConfiguration.class)
|
||||
.withPropertyValues("management.health.defaults.enabled:false")
|
||||
.run((context) -> assertThat(context).getBean(HealthIndicator.class)
|
||||
.isInstanceOf(ApplicationHealthIndicator.class));
|
||||
.withPropertyValues("management.health.defaults.enabled:false").run((context) -> assertThat(context)
|
||||
.getBean(HealthIndicator.class).isInstanceOf(ApplicationHealthIndicator.class));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenHasDefaultsDisabledAndSingleIndicatorEnabledShouldCreateEnabledIndicator() {
|
||||
this.contextRunner.withUserConfiguration(CustomHealthIndicatorConfiguration.class)
|
||||
.withPropertyValues("management.health.defaults.enabled:false",
|
||||
"management.health.custom.enabled:true")
|
||||
.withPropertyValues("management.health.defaults.enabled:false", "management.health.custom.enabled:true")
|
||||
.run((context) -> assertThat(context).getBean(HealthIndicator.class)
|
||||
.isInstanceOf(CustomHealthIndicator.class));
|
||||
|
||||
@@ -81,29 +77,25 @@ public class HealthIndicatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void runShouldCreateOrderedHealthAggregator() {
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).getBean(HealthAggregator.class)
|
||||
.isInstanceOf(OrderedHealthAggregator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).getBean(HealthAggregator.class)
|
||||
.isInstanceOf(OrderedHealthAggregator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenHasCustomOrderPropertyShouldCreateOrderedHealthAggregator() {
|
||||
this.contextRunner.withPropertyValues("management.health.status.order:UP,DOWN")
|
||||
.run((context) -> {
|
||||
OrderedHealthAggregator aggregator = context
|
||||
.getBean(OrderedHealthAggregator.class);
|
||||
Map<String, Health> healths = new LinkedHashMap<>();
|
||||
healths.put("foo", Health.up().build());
|
||||
healths.put("bar", Health.down().build());
|
||||
Health aggregate = aggregator.aggregate(healths);
|
||||
assertThat(aggregate.getStatus()).isEqualTo(Status.UP);
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.health.status.order:UP,DOWN").run((context) -> {
|
||||
OrderedHealthAggregator aggregator = context.getBean(OrderedHealthAggregator.class);
|
||||
Map<String, Health> healths = new LinkedHashMap<>();
|
||||
healths.put("foo", Health.up().build());
|
||||
healths.put("bar", Health.down().build());
|
||||
Health aggregate = aggregator.aggregate(healths);
|
||||
assertThat(aggregate.getStatus()).isEqualTo(Status.UP);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenHasCustomHealthAggregatorShouldNotCreateOrderedHealthAggregator() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomHealthAggregatorConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(CustomHealthAggregatorConfiguration.class)
|
||||
.run((context) -> assertThat(context).getBean(HealthAggregator.class)
|
||||
.isNotInstanceOf(OrderedHealthAggregator.class));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,196 +49,157 @@ import static org.mockito.Mockito.mock;
|
||||
public class ReactiveHealthEndpointWebExtensionTests {
|
||||
|
||||
private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withUserConfiguration(HealthIndicatorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class);
|
||||
.withUserConfiguration(HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class);
|
||||
|
||||
@Test
|
||||
public void runShouldCreateExtensionBeans() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ReactiveHealthEndpointWebExtension.class));
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveHealthEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenHealthEndpointIsDisabledShouldNotCreateExtensionBeans() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ReactiveHealthEndpointWebExtension.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveHealthEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWithCustomHealthMappingShouldMapStatusCode() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.health.status.http-mapping.CUSTOM=500")
|
||||
.run((context) -> {
|
||||
Object extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
|
||||
.getField(extension, "responseMapper");
|
||||
Class<SecurityContext> securityContext = SecurityContext.class;
|
||||
assertThat(responseMapper
|
||||
.map(Health.down().build(), mock(securityContext))
|
||||
.getStatus()).isEqualTo(503);
|
||||
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(),
|
||||
mock(securityContext)).getStatus()).isEqualTo(503);
|
||||
assertThat(responseMapper
|
||||
.map(Health.status("CUSTOM").build(), mock(securityContext))
|
||||
.getStatus()).isEqualTo(500);
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.health.status.http-mapping.CUSTOM=500").run((context) -> {
|
||||
Object extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
|
||||
.getField(extension, "responseMapper");
|
||||
Class<SecurityContext> securityContext = SecurityContext.class;
|
||||
assertThat(responseMapper.map(Health.down().build(), mock(securityContext)).getStatus()).isEqualTo(503);
|
||||
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(), mock(securityContext)).getStatus())
|
||||
.isEqualTo(503);
|
||||
assertThat(responseMapper.map(Health.status("CUSTOM").build(), mock(securityContext)).getStatus())
|
||||
.isEqualTo(500);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regularAndReactiveHealthIndicatorsMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.withUserConfiguration(HealthIndicatorsConfiguration.class)
|
||||
.run((context) -> {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.withUserConfiguration(HealthIndicatorsConfiguration.class).run((context) -> {
|
||||
HealthEndpoint endpoint = context.getBean(HealthEndpoint.class);
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
Health endpointHealth = endpoint.health();
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
Health extensionHealth = extension.health(securityContext)
|
||||
.block(Duration.ofSeconds(30)).getBody();
|
||||
assertThat(endpointHealth.getDetails())
|
||||
.containsOnlyKeys("application", "first", "second");
|
||||
assertThat(extensionHealth.getDetails())
|
||||
.containsOnlyKeys("application", "first", "second");
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
Health extensionHealth = extension.health(securityContext).block(Duration.ofSeconds(30)).getBody();
|
||||
assertThat(endpointHealth.getDetails()).containsOnlyKeys("application", "first", "second");
|
||||
assertThat(extensionHealth.getDetails()).containsOnlyKeys("application", "first", "second");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersAreNotShownDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(mock(SecurityContext.class))
|
||||
.block(Duration.ofSeconds(30)).getBody().getDetails()).isEmpty();
|
||||
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(
|
||||
extension.health(mock(SecurityContext.class)).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersAreNotShownDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30))
|
||||
.getBody().getDetails()).isEmpty();
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticatedUsersWhenAuthorizedCanBeShownDetails() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized")
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
|
||||
.run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
assertThat(extension.health(securityContext)
|
||||
.block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthenticatedUsersCanBeShownDetails() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(null).block(Duration.ofSeconds(30))
|
||||
.getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(null).block(Duration.ofSeconds(30)).getBody().getDetails()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detailsCanBeHiddenFromAuthenticatedUsers() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.health.show-details=never")
|
||||
.run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
assertThat(extension.health(securityContext)
|
||||
.block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detailsCanBeHiddenFromUnauthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
|
||||
assertThat(extension.health(securityContext)
|
||||
.block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detailsCanBeShownToAuthorizedUsers() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
|
||||
assertThat(extension.health(securityContext)
|
||||
.block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roleCanBeCustomized() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.health.show-details=when-authorized",
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
|
||||
"management.endpoint.health.roles=ADMIN").run((context) -> {
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
given(securityContext.getPrincipal())
|
||||
.willReturn(mock(Principal.class));
|
||||
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
|
||||
given(securityContext.isUserInRole("ADMIN")).willReturn(true);
|
||||
assertThat(extension.health(securityContext)
|
||||
.block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registryCanBeAltered() {
|
||||
this.contextRunner.withUserConfiguration(HealthIndicatorsConfiguration.class)
|
||||
.withPropertyValues("management.endpoint.health.show-details=always")
|
||||
.run((context) -> {
|
||||
ReactiveHealthIndicatorRegistry registry = context
|
||||
.getBean(ReactiveHealthIndicatorRegistry.class);
|
||||
.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
|
||||
ReactiveHealthIndicatorRegistry registry = context.getBean(ReactiveHealthIndicatorRegistry.class);
|
||||
ReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(ReactiveHealthEndpointWebExtension.class);
|
||||
assertThat(extension.health(null).block(Duration.ofSeconds(30))
|
||||
.getBody().getDetails()).containsOnlyKeys("application",
|
||||
"first", "second");
|
||||
assertThat(extension.health(null).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.containsOnlyKeys("application", "first", "second");
|
||||
assertThat(registry.unregister("second")).isNotNull();
|
||||
assertThat(extension.health(null).block(Duration.ofSeconds(30))
|
||||
.getBody().getDetails()).containsKeys("application", "first");
|
||||
assertThat(extension.health(null).block(Duration.ofSeconds(30)).getBody().getDetails())
|
||||
.containsKeys("application", "first");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,22 +38,19 @@ import static org.mockito.Mockito.mock;
|
||||
public class InfluxDbHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(InfluxDbConfiguration.class).withConfiguration(
|
||||
AutoConfigurations.of(InfluxDbHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
.withUserConfiguration(InfluxDbConfiguration.class).withConfiguration(AutoConfigurations
|
||||
.of(InfluxDbHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(InfluxDbHealthIndicator.class)
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(InfluxDbHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.influxdb.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(InfluxDbHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(InfluxDbHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,36 +54,30 @@ public class InfoContributorAutoConfigurationTests {
|
||||
@Test
|
||||
public void disableEnvContributor() {
|
||||
load("management.info.env.enabled:false");
|
||||
Map<String, InfoContributor> beans = this.context
|
||||
.getBeansOfType(InfoContributor.class);
|
||||
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
|
||||
assertThat(beans).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultInfoContributorsDisabled() {
|
||||
load("management.info.defaults.enabled:false");
|
||||
Map<String, InfoContributor> beans = this.context
|
||||
.getBeansOfType(InfoContributor.class);
|
||||
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
|
||||
assertThat(beans).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultInfoContributorsDisabledWithCustomOne() {
|
||||
load(CustomInfoContributorConfiguration.class,
|
||||
"management.info.defaults.enabled:false");
|
||||
Map<String, InfoContributor> beans = this.context
|
||||
.getBeansOfType(InfoContributor.class);
|
||||
load(CustomInfoContributorConfiguration.class, "management.info.defaults.enabled:false");
|
||||
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
|
||||
assertThat(beans).hasSize(1);
|
||||
assertThat(this.context.getBean("customInfoContributor"))
|
||||
.isSameAs(beans.values().iterator().next());
|
||||
assertThat(this.context.getBean("customInfoContributor")).isSameAs(beans.values().iterator().next());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void gitPropertiesDefaultMode() {
|
||||
load(GitPropertiesConfiguration.class);
|
||||
Map<String, InfoContributor> beans = this.context
|
||||
.getBeansOfType(InfoContributor.class);
|
||||
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
|
||||
assertThat(beans).containsKeys("gitInfoContributor");
|
||||
Map<String, Object> content = invokeContributor(
|
||||
this.context.getBean("gitInfoContributor", InfoContributor.class));
|
||||
@@ -117,8 +111,7 @@ public class InfoContributorAutoConfigurationTests {
|
||||
@Test
|
||||
public void buildProperties() {
|
||||
load(BuildPropertiesConfiguration.class);
|
||||
Map<String, InfoContributor> beans = this.context
|
||||
.getBeansOfType(InfoContributor.class);
|
||||
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
|
||||
assertThat(beans).containsKeys("buildInfoContributor");
|
||||
Map<String, Object> content = invokeContributor(
|
||||
this.context.getBean("buildInfoContributor", InfoContributor.class));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,8 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class InfoEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(InfoEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(InfoEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
@@ -51,8 +50,7 @@ public class InfoEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.info.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(InfoEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(InfoEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,31 +36,26 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class IntegrationGraphEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class,
|
||||
IntegrationAutoConfiguration.class,
|
||||
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, IntegrationAutoConfiguration.class,
|
||||
IntegrationGraphEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(IntegrationGraphEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(IntegrationGraphEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.integrationgraph.enabled:false")
|
||||
.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(IntegrationGraphEndpoint.class);
|
||||
assertThat(context).doesNotHaveBean(IntegrationGraphServer.class);
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.integrationgraph.enabled:false").run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(IntegrationGraphEndpoint.class);
|
||||
assertThat(context).doesNotHaveBean(IntegrationGraphServer.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenSpringIntegrationIsNotEnabledShouldNotHaveEndpointBean() {
|
||||
ApplicationContextRunner noSpringIntegrationRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations
|
||||
.of(IntegrationGraphEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(IntegrationGraphEndpointAutoConfiguration.class));
|
||||
noSpringIntegrationRunner.run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(IntegrationGraphEndpoint.class);
|
||||
assertThat(context).doesNotHaveBean(IntegrationGraphServer.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,25 +57,21 @@ public class ControllerEndpointWebFluxIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void endpointsCanBeAccessed() throws Exception {
|
||||
TestSecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||
TestSecurityContextHolder.getContext()
|
||||
.setAuthentication(new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||
this.context = new AnnotationConfigReactiveWebApplicationContext();
|
||||
this.context.register(DefaultConfiguration.class, ExampleController.class);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include=*")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include=*").applyTo(this.context);
|
||||
this.context.refresh();
|
||||
WebTestClient webClient = WebTestClient.bindToApplicationContext(this.context)
|
||||
.build();
|
||||
WebTestClient webClient = WebTestClient.bindToApplicationContext(this.context).build();
|
||||
webClient.get().uri("/actuator/example").exchange().expectStatus().isOk();
|
||||
}
|
||||
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
ReactiveManagementContextAutoConfiguration.class,
|
||||
AuditAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class })
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ReactiveManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class })
|
||||
static class DefaultConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,13 +79,12 @@ public class ControllerEndpointWebMvcIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void endpointsCanBeAccessed() throws Exception {
|
||||
TestSecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||
TestSecurityContextHolder.getContext()
|
||||
.setAuthentication(new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(SecureConfiguration.class, ExampleController.class);
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.base-path:/management",
|
||||
"management.endpoints.web.exposure.include=*")
|
||||
.of("management.endpoints.web.base-path:/management", "management.endpoints.web.exposure.include=*")
|
||||
.applyTo(this.context);
|
||||
MockMvc mockMvc = createSecureMockMvc();
|
||||
mockMvc.perform(get("/management/example")).andExpect(status().isOk());
|
||||
@@ -105,13 +104,11 @@ public class ControllerEndpointWebMvcIntegrationTests {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class })
|
||||
static class DefaultConfiguration {
|
||||
|
||||
|
||||
@@ -47,8 +47,7 @@ public class JerseyEndpointIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void linksAreProvidedToAllEndpointTypes() {
|
||||
testJerseyEndpoints(new Class[] { EndpointsConfiguration.class,
|
||||
ResourceConfigConfiguration.class });
|
||||
testJerseyEndpoints(new Class[] { EndpointsConfiguration.class, ResourceConfigConfiguration.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,33 +56,23 @@ public class JerseyEndpointIntegrationTests {
|
||||
}
|
||||
|
||||
protected void testJerseyEndpoints(Class<?>[] userConfigurations) {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(
|
||||
DispatcherServlet.class);
|
||||
new WebApplicationContextRunner(
|
||||
AnnotationConfigServletWebServerApplicationContext::new)
|
||||
.withClassLoader(classLoader)
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(JacksonAutoConfiguration.class,
|
||||
JerseyAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class,
|
||||
ServletWebServerFactoryAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(userConfigurations)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*",
|
||||
"server.port:0")
|
||||
.run((context) -> {
|
||||
int port = context.getSourceApplicationContext(
|
||||
AnnotationConfigServletWebServerApplicationContext.class)
|
||||
.getWebServer().getPort();
|
||||
WebTestClient client = WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + port).build();
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.beans").isNotEmpty()
|
||||
.jsonPath("_links.restcontroller").doesNotExist()
|
||||
.jsonPath("_links.controller").doesNotExist();
|
||||
});
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(DispatcherServlet.class);
|
||||
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
|
||||
.withClassLoader(classLoader)
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, JerseyAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(userConfigurations)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*", "server.port:0").run((context) -> {
|
||||
int port = context
|
||||
.getSourceApplicationContext(AnnotationConfigServletWebServerApplicationContext.class)
|
||||
.getWebServer().getPort();
|
||||
WebTestClient client = WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
|
||||
.isNotEmpty().jsonPath("_links.restcontroller").doesNotExist().jsonPath("_links.controller")
|
||||
.doesNotExist();
|
||||
});
|
||||
}
|
||||
|
||||
@ControllerEndpoint(id = "controller")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,52 +46,40 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class JmxEndpointIntegrationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, JmxEndpointAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class,
|
||||
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
JmxEndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class,
|
||||
HttpTraceAutoConfiguration.class))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL));
|
||||
.withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL));
|
||||
|
||||
@Test
|
||||
public void jmxEndpointsAreExposed() {
|
||||
this.contextRunner.run((context) -> {
|
||||
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
|
||||
checkEndpointMBeans(mBeanServer,
|
||||
new String[] { "beans", "conditions", "configprops", "env", "health",
|
||||
"info", "mappings", "threaddump", "httptrace" },
|
||||
new String[] { "shutdown" });
|
||||
checkEndpointMBeans(mBeanServer, new String[] { "beans", "conditions", "configprops", "env", "health",
|
||||
"info", "mappings", "threaddump", "httptrace" }, new String[] { "shutdown" });
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jmxEndpointsCanBeExcluded() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.jmx.exposure.exclude:*")
|
||||
.run((context) -> {
|
||||
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
|
||||
checkEndpointMBeans(mBeanServer, new String[0],
|
||||
new String[] { "beans", "conditions", "configprops", "env",
|
||||
"health", "mappings", "shutdown", "threaddump",
|
||||
"httptrace" });
|
||||
this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.exclude:*").run((context) -> {
|
||||
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
|
||||
checkEndpointMBeans(mBeanServer, new String[0], new String[] { "beans", "conditions", "configprops", "env",
|
||||
"health", "mappings", "shutdown", "threaddump", "httptrace" });
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleJmxEndpointCanBeExposed() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.jmx.exposure.include=beans")
|
||||
.run((context) -> {
|
||||
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
|
||||
checkEndpointMBeans(mBeanServer, new String[] { "beans" },
|
||||
new String[] { "conditions", "configprops", "env", "health",
|
||||
"mappings", "shutdown", "threaddump", "httptrace" });
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.include=beans").run((context) -> {
|
||||
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
|
||||
checkEndpointMBeans(mBeanServer, new String[] { "beans" }, new String[] { "conditions", "configprops",
|
||||
"env", "health", "mappings", "shutdown", "threaddump", "httptrace" });
|
||||
});
|
||||
}
|
||||
|
||||
private void checkEndpointMBeans(MBeanServer mBeanServer, String[] enabledEndpoints,
|
||||
String[] disabledEndpoints) {
|
||||
private void checkEndpointMBeans(MBeanServer mBeanServer, String[] enabledEndpoints, String[] disabledEndpoints) {
|
||||
for (String enabledEndpoint : enabledEndpoints) {
|
||||
assertThat(isRegistered(mBeanServer, getDefaultObjectName(enabledEndpoint)))
|
||||
.as(String.format("Endpoint %s", enabledEndpoint)).isTrue();
|
||||
@@ -112,14 +100,12 @@ public class JmxEndpointIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
private MBeanInfo getMBeanInfo(MBeanServer mBeanServer, ObjectName objectName)
|
||||
throws InstanceNotFoundException {
|
||||
private MBeanInfo getMBeanInfo(MBeanServer mBeanServer, ObjectName objectName) throws InstanceNotFoundException {
|
||||
try {
|
||||
return mBeanServer.getMBeanInfo(objectName);
|
||||
}
|
||||
catch (ReflectionException | IntrospectionException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to retrieve MBeanInfo for ObjectName " + objectName, ex);
|
||||
throw new IllegalStateException("Failed to retrieve MBeanInfo for ObjectName " + objectName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +115,8 @@ public class JmxEndpointIntegrationTests {
|
||||
|
||||
private ObjectName getObjectName(String domain, String endpointId) {
|
||||
try {
|
||||
return new ObjectName(String.format("%s:type=Endpoint,name=%s", domain,
|
||||
StringUtils.capitalize(endpointId)));
|
||||
return new ObjectName(
|
||||
String.format("%s:type=Endpoint,name=%s", domain, StringUtils.capitalize(endpointId)));
|
||||
}
|
||||
catch (MalformedObjectNameException ex) {
|
||||
throw new IllegalStateException("Invalid object name", ex);
|
||||
|
||||
@@ -68,8 +68,7 @@ public class JolokiaEndpointAutoConfigurationIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void jolokiaIsExposed() {
|
||||
ResponseEntity<String> response = this.restTemplate
|
||||
.getForEntity("/actuator/jolokia", String.class);
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity("/actuator/jolokia", String.class);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).contains("\"agent\"");
|
||||
assertThat(response.getBody()).contains("\"request\":{\"type\"");
|
||||
@@ -77,36 +76,33 @@ public class JolokiaEndpointAutoConfigurationIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void search() {
|
||||
ResponseEntity<String> response = this.restTemplate
|
||||
.getForEntity("/actuator/jolokia/search/java.lang:*", String.class);
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity("/actuator/jolokia/search/java.lang:*",
|
||||
String.class);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).contains("GarbageCollector");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void read() {
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity(
|
||||
"/actuator/jolokia/read/java.lang:type=Memory", String.class);
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity("/actuator/jolokia/read/java.lang:type=Memory",
|
||||
String.class);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).contains("NonHeapMemoryUsage");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() {
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity(
|
||||
"/actuator/jolokia/list/java.lang/type=Memory/attr", String.class);
|
||||
ResponseEntity<String> response = this.restTemplate
|
||||
.getForEntity("/actuator/jolokia/list/java.lang/type=Memory/attr", String.class);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(response.getBody()).contains("NonHeapMemoryUsage");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@MinimalWebConfiguration
|
||||
@Import({ JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
JolokiaEndpointAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
@Import({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
JolokiaEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletEndpointManagementContextConfiguration.class })
|
||||
protected static class Application {
|
||||
|
||||
@@ -115,9 +111,8 @@ public class JolokiaEndpointAutoConfigurationIntegrationTests {
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
@Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
ValidationAutoConfiguration.class, WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
|
||||
protected @interface MinimalWebConfiguration {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,40 +57,34 @@ public class WebEndpointsAutoConfigurationIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void healthEndpointWebExtensionIsAutoConfigured() {
|
||||
servletWebRunner()
|
||||
.run((context) -> context.getBean(WebEndpointTestApplication.class));
|
||||
servletWebRunner().run((context) -> assertThat(context)
|
||||
.hasSingleBean(HealthEndpointWebExtension.class));
|
||||
servletWebRunner().run((context) -> context.getBean(WebEndpointTestApplication.class));
|
||||
servletWebRunner().run((context) -> assertThat(context).hasSingleBean(HealthEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthEndpointReactiveWebExtensionIsAutoConfigured() {
|
||||
reactiveWebRunner().run((context) -> assertThat(context)
|
||||
.hasSingleBean(ReactiveHealthEndpointWebExtension.class));
|
||||
reactiveWebRunner()
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveHealthEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
private WebApplicationContextRunner servletWebRunner() {
|
||||
return new WebApplicationContextRunner().withConfiguration(
|
||||
UserConfigurations.of(WebEndpointTestApplication.class));
|
||||
return new WebApplicationContextRunner()
|
||||
.withConfiguration(UserConfigurations.of(WebEndpointTestApplication.class));
|
||||
}
|
||||
|
||||
private ReactiveWebApplicationContextRunner reactiveWebRunner() {
|
||||
return new ReactiveWebApplicationContextRunner().withConfiguration(
|
||||
UserConfigurations.of(WebEndpointTestApplication.class));
|
||||
return new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(UserConfigurations.of(WebEndpointTestApplication.class));
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration(exclude = { FlywayAutoConfiguration.class,
|
||||
LiquibaseAutoConfiguration.class, CassandraAutoConfiguration.class,
|
||||
CassandraDataAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
|
||||
Neo4jRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class,
|
||||
@EnableAutoConfiguration(exclude = { FlywayAutoConfiguration.class, LiquibaseAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
|
||||
Neo4jRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
RepositoryRestMvcAutoConfiguration.class, HazelcastAutoConfiguration.class,
|
||||
ElasticsearchAutoConfiguration.class,
|
||||
ElasticsearchDataAutoConfiguration.class, JestAutoConfiguration.class,
|
||||
SolrRepositoriesAutoConfiguration.class, SolrAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
|
||||
MetricsAutoConfiguration.class })
|
||||
ElasticsearchAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class, JestAutoConfiguration.class,
|
||||
SolrRepositoriesAutoConfiguration.class, SolrAutoConfiguration.class, RedisAutoConfiguration.class,
|
||||
RedisRepositoriesAutoConfiguration.class, MetricsAutoConfiguration.class })
|
||||
@SpringBootConfiguration
|
||||
public static class WebEndpointTestApplication {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,123 +47,89 @@ public class WebFluxEndpointCorsIntegrationTests {
|
||||
@Before
|
||||
public void createContext() {
|
||||
this.context = new AnnotationConfigReactiveWebApplicationContext();
|
||||
this.context.register(JacksonAutoConfiguration.class,
|
||||
CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ReactiveManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include:*")
|
||||
.applyTo(this.context);
|
||||
this.context.register(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include:*").applyTo(this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void corsIsDisabledByDefault() {
|
||||
createWebTestClient().options().uri("/actuator/beans")
|
||||
.header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange()
|
||||
.expectStatus().isForbidden().expectHeader()
|
||||
.doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectStatus().isForbidden()
|
||||
.expectHeader().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingAllowedOriginsEnablesCors() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
|
||||
.applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans")
|
||||
.header("Origin", "test.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans").header("Origin", "test.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectStatus().isForbidden();
|
||||
performAcceptedCorsRequest("/actuator/beans");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAgeDefaultsTo30Minutes() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
|
||||
.applyTo(this.context);
|
||||
performAcceptedCorsRequest("/actuator/beans").expectHeader()
|
||||
.valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800");
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
|
||||
performAcceptedCorsRequest("/actuator/beans").expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE,
|
||||
"1800");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAgeCanBeConfigured() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.max-age: 2400")
|
||||
.applyTo(this.context);
|
||||
performAcceptedCorsRequest("/actuator/beans").expectHeader()
|
||||
.valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "2400");
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.max-age: 2400").applyTo(this.context);
|
||||
performAcceptedCorsRequest("/actuator/beans").expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE,
|
||||
"2400");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestsWithDisallowedHeadersAreRejected() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
|
||||
.applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans")
|
||||
.header("Origin", "spring.example.org")
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange().expectStatus().isForbidden();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowedHeadersCanBeConfigured() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo")
|
||||
.applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans")
|
||||
.header("Origin", "spring.example.org")
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo").applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange()
|
||||
.expectStatus().isOk().expectHeader()
|
||||
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha");
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange().expectStatus().isOk()
|
||||
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestsWithDisallowedMethodsAreRejected() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
|
||||
.applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans")
|
||||
.header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH").exchange()
|
||||
.expectStatus().isForbidden();
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH").exchange().expectStatus().isForbidden();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowedMethodsCanBeConfigured() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allowed-methods:GET,HEAD")
|
||||
.applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans")
|
||||
.header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD").exchange()
|
||||
.expectStatus().isOk().expectHeader()
|
||||
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD");
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allowed-methods:GET,HEAD").applyTo(this.context);
|
||||
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD").exchange().expectStatus().isOk()
|
||||
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsCanBeAllowed() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allow-credentials:true")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allow-credentials:true").applyTo(this.context);
|
||||
performAcceptedCorsRequest("/actuator/beans").expectHeader()
|
||||
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsCanBeDisabled() {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allow-credentials:false")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
|
||||
"management.endpoints.web.cors.allow-credentials:false").applyTo(this.context);
|
||||
performAcceptedCorsRequest("/actuator/beans").expectHeader()
|
||||
.doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS);
|
||||
}
|
||||
@@ -175,12 +141,9 @@ public class WebFluxEndpointCorsIntegrationTests {
|
||||
}
|
||||
|
||||
private WebTestClient.ResponseSpec performAcceptedCorsRequest(String url) {
|
||||
return createWebTestClient().options().uri(url)
|
||||
.header(HttpHeaders.ORIGIN, "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange()
|
||||
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,
|
||||
"spring.example.org")
|
||||
.expectStatus().isOk();
|
||||
return createWebTestClient().options().uri(url).header(HttpHeaders.ORIGIN, "spring.example.org")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectHeader()
|
||||
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "spring.example.org").expectStatus().isOk();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,28 +46,23 @@ public class WebFluxEndpointIntegrationTests {
|
||||
@Test
|
||||
public void linksAreProvidedToAllEndpointTypes() throws Exception {
|
||||
new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class,
|
||||
CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
HttpHandlerAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ReactiveManagementContextAutoConfiguration.class,
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class,
|
||||
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(EndpointsConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*")
|
||||
.run((context) -> {
|
||||
.withPropertyValues("management.endpoints.web.exposure.include:*").run((context) -> {
|
||||
WebTestClient client = createWebTestClient(context);
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.beans").isNotEmpty()
|
||||
.jsonPath("_links.restcontroller").isNotEmpty()
|
||||
.jsonPath("_links.controller").isNotEmpty();
|
||||
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
|
||||
.isNotEmpty().jsonPath("_links.restcontroller").isNotEmpty().jsonPath("_links.controller")
|
||||
.isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
private WebTestClient createWebTestClient(ApplicationContext context) {
|
||||
return WebTestClient.bindToApplicationContext(context).configureClient()
|
||||
.baseUrl("https://spring.example.org").build();
|
||||
return WebTestClient.bindToApplicationContext(context).configureClient().baseUrl("https://spring.example.org")
|
||||
.build();
|
||||
}
|
||||
|
||||
@ControllerEndpoint(id = "controller")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -55,15 +55,12 @@ public class WebMvcEndpointCorsIntegrationTests {
|
||||
public void createContext() {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.setServletContext(new MockServletContext());
|
||||
this.context.register(JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
this.context.register(JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include:*")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include:*").applyTo(this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,111 +68,80 @@ public class WebMvcEndpointCorsIntegrationTests {
|
||||
createMockMvc()
|
||||
.perform(options("/actuator/beans").header("Origin", "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
||||
.andExpect(
|
||||
header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
.andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingAllowedOriginsEnablesCors() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
|
||||
.applyTo(this.context);
|
||||
createMockMvc()
|
||||
.perform(options("/actuator/beans").header("Origin", "bar.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
||||
.andExpect(status().isForbidden());
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
|
||||
createMockMvc().perform(options("/actuator/beans").header("Origin", "bar.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")).andExpect(status().isForbidden());
|
||||
performAcceptedCorsRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAgeDefaultsTo30Minutes() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
|
||||
.applyTo(this.context);
|
||||
performAcceptedCorsRequest()
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800"));
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
|
||||
performAcceptedCorsRequest().andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxAgeCanBeConfigured() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.max-age: 2400")
|
||||
.applyTo(this.context);
|
||||
performAcceptedCorsRequest()
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "2400"));
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.max-age: 2400").applyTo(this.context);
|
||||
performAcceptedCorsRequest().andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "2400"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestsWithDisallowedHeadersAreRejected() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
|
||||
.applyTo(this.context);
|
||||
createMockMvc()
|
||||
.perform(options("/actuator/beans").header("Origin", "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha"))
|
||||
.andExpect(status().isForbidden());
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
|
||||
createMockMvc().perform(options("/actuator/beans").header("Origin", "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha")).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowedHeadersCanBeConfigured() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo").applyTo(this.context);
|
||||
createMockMvc()
|
||||
.perform(options("/actuator/beans").header("Origin", "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha"))
|
||||
.andExpect(status().isOk()).andExpect(header()
|
||||
.string(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha"));
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestsWithDisallowedMethodsAreRejected() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
|
||||
.applyTo(this.context);
|
||||
createMockMvc()
|
||||
.perform(options("/actuator/health")
|
||||
.header(HttpHeaders.ORIGIN, "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH"))
|
||||
.andExpect(status().isForbidden());
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
|
||||
createMockMvc().perform(options("/actuator/health").header(HttpHeaders.ORIGIN, "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH")).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowedMethodsCanBeConfigured() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allowed-methods:GET,HEAD")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allowed-methods:GET,HEAD").applyTo(this.context);
|
||||
createMockMvc()
|
||||
.perform(options("/actuator/beans")
|
||||
.header(HttpHeaders.ORIGIN, "foo.example.com")
|
||||
.perform(options("/actuator/beans").header(HttpHeaders.ORIGIN, "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD"))
|
||||
.andExpect(status().isOk()).andExpect(header()
|
||||
.string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD"));
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsCanBeAllowed() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allow-credentials:true")
|
||||
.applyTo(this.context);
|
||||
performAcceptedCorsRequest().andExpect(
|
||||
header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"));
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allow-credentials:true").applyTo(this.context);
|
||||
performAcceptedCorsRequest().andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsCanBeDisabled() throws Exception {
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allow-credentials:false")
|
||||
.applyTo(this.context);
|
||||
performAcceptedCorsRequest().andExpect(
|
||||
header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
|
||||
"management.endpoints.web.cors.allow-credentials:false").applyTo(this.context);
|
||||
performAcceptedCorsRequest().andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
}
|
||||
|
||||
private MockMvc createMockMvc() {
|
||||
@@ -191,8 +157,7 @@ public class WebMvcEndpointCorsIntegrationTests {
|
||||
return createMockMvc()
|
||||
.perform(options(url).header(HttpHeaders.ORIGIN, "foo.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,
|
||||
"foo.example.com"))
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "foo.example.com"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -62,24 +62,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class WebMvcEndpointExposureIntegrationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner(
|
||||
AnnotationConfigServletWebServerApplicationContext::new).withConfiguration(
|
||||
AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
HttpTraceAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL))
|
||||
.withUserConfiguration(CustomMvcEndpoint.class,
|
||||
CustomServletEndpoint.class)
|
||||
AnnotationConfigServletWebServerApplicationContext::new)
|
||||
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
|
||||
HttpTraceAutoConfiguration.class, HealthIndicatorAutoConfiguration.class))
|
||||
.withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL))
|
||||
.withUserConfiguration(CustomMvcEndpoint.class, CustomServletEndpoint.class)
|
||||
.withPropertyValues("server.port:0");
|
||||
|
||||
@Test
|
||||
@@ -146,8 +138,7 @@ public class WebMvcEndpointExposureIntegrationTests {
|
||||
@Test
|
||||
public void singleWebEndpointCanBeExcluded() {
|
||||
WebApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
|
||||
"management.endpoints.web.exposure.include=*",
|
||||
"management.endpoints.web.exposure.exclude=shutdown");
|
||||
"management.endpoints.web.exposure.include=*", "management.endpoints.web.exposure.exclude=shutdown");
|
||||
contextRunner.run((context) -> {
|
||||
WebTestClient client = createClient(context);
|
||||
assertThat(isExposed(client, HttpMethod.GET, "beans")).isTrue();
|
||||
@@ -166,17 +157,14 @@ public class WebMvcEndpointExposureIntegrationTests {
|
||||
}
|
||||
|
||||
private WebTestClient createClient(AssertableWebApplicationContext context) {
|
||||
int port = context
|
||||
.getSourceApplicationContext(ServletWebServerApplicationContext.class)
|
||||
.getWebServer().getPort();
|
||||
int port = context.getSourceApplicationContext(ServletWebServerApplicationContext.class).getWebServer()
|
||||
.getPort();
|
||||
return WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
|
||||
}
|
||||
|
||||
private boolean isExposed(WebTestClient client, HttpMethod method, String path)
|
||||
throws Exception {
|
||||
private boolean isExposed(WebTestClient client, HttpMethod method, String path) throws Exception {
|
||||
path = "/actuator/" + path;
|
||||
EntityExchangeResult<byte[]> result = client.method(method).uri(path).exchange()
|
||||
.expectBody().returnResult();
|
||||
EntityExchangeResult<byte[]> result = client.method(method).uri(path).exchange().expectBody().returnResult();
|
||||
if (result.getStatus() == HttpStatus.OK) {
|
||||
return true;
|
||||
}
|
||||
@@ -184,8 +172,7 @@ public class WebMvcEndpointExposureIntegrationTests {
|
||||
return false;
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
String.format("Unexpected %s HTTP status for " + "endpoint %s",
|
||||
result.getStatus(), path));
|
||||
String.format("Unexpected %s HTTP status for " + "endpoint %s", result.getStatus(), path));
|
||||
}
|
||||
|
||||
@RestControllerEndpoint(id = "custommvc")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -83,16 +83,14 @@ public class WebMvcEndpointIntegrationTests {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(SecureConfiguration.class);
|
||||
MockMvc mockMvc = createSecureMockMvc();
|
||||
mockMvc.perform(get("/actuator/beans").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isUnauthorized());
|
||||
mockMvc.perform(get("/actuator/beans").accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsAreSecureByDefaultWithCustomBasePath() throws Exception {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(SecureConfiguration.class);
|
||||
TestPropertyValues.of("management.endpoints.web.base-path:/management")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.base-path:/management").applyTo(this.context);
|
||||
MockMvc mockMvc = createSecureMockMvc();
|
||||
mockMvc.perform(get("/management/beans").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isUnauthorized());
|
||||
@@ -100,13 +98,12 @@ public class WebMvcEndpointIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void endpointsAreSecureWithActuatorRoleWithCustomBasePath() throws Exception {
|
||||
TestSecurityContextHolder.getContext().setAuthentication(
|
||||
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||
TestSecurityContextHolder.getContext()
|
||||
.setAuthentication(new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(SecureConfiguration.class);
|
||||
TestPropertyValues
|
||||
.of("management.endpoints.web.base-path:/management",
|
||||
"management.endpoints.web.exposure.include=*")
|
||||
.of("management.endpoints.web.base-path:/management", "management.endpoints.web.exposure.include=*")
|
||||
.applyTo(this.context);
|
||||
MockMvc mockMvc = createSecureMockMvc();
|
||||
mockMvc.perform(get("/management/beans")).andExpect(status().isOk());
|
||||
@@ -116,12 +113,10 @@ public class WebMvcEndpointIntegrationTests {
|
||||
public void linksAreProvidedToAllEndpointTypes() throws Exception {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(DefaultConfiguration.class, EndpointsConfiguration.class);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include=*")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("management.endpoints.web.exposure.include=*").applyTo(this.context);
|
||||
MockMvc mockMvc = doCreateMockMvc();
|
||||
mockMvc.perform(get("/actuator").accept("*/*")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("_links", both(hasKey("beans")).and(hasKey("servlet"))
|
||||
.and(hasKey("restcontroller")).and(hasKey("controller"))));
|
||||
mockMvc.perform(get("/actuator").accept("*/*")).andExpect(status().isOk()).andExpect(jsonPath("_links",
|
||||
both(hasKey("beans")).and(hasKey("servlet")).and(hasKey("restcontroller")).and(hasKey("controller"))));
|
||||
}
|
||||
|
||||
private MockMvc createSecureMockMvc() {
|
||||
@@ -138,14 +133,12 @@ public class WebMvcEndpointIntegrationTests {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class,
|
||||
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class,
|
||||
BeansEndpointAutoConfiguration.class })
|
||||
DispatcherServletAutoConfiguration.class, BeansEndpointAutoConfiguration.class })
|
||||
static class DefaultConfiguration {
|
||||
|
||||
}
|
||||
@@ -157,8 +150,7 @@ public class WebMvcEndpointIntegrationTests {
|
||||
}
|
||||
|
||||
@Import(SecureConfiguration.class)
|
||||
@ImportAutoConfiguration({ HypermediaAutoConfiguration.class,
|
||||
RepositoryRestMvcAutoConfiguration.class })
|
||||
@ImportAutoConfiguration({ HypermediaAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
|
||||
static class SpringDataRestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,8 +49,7 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class,
|
||||
DataSourceHealthIndicatorAutoConfiguration.class))
|
||||
HealthIndicatorAutoConfiguration.class, DataSourceHealthIndicatorAutoConfiguration.class))
|
||||
.withPropertyValues("spring.datasource.initialization-mode=never");
|
||||
|
||||
@Test
|
||||
@@ -64,37 +63,28 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void runWhenMultipleDataSourceBeansShouldCreateCompositeIndicator() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
|
||||
DataSourceConfig.class).run((context) -> {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, DataSourceConfig.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(HealthIndicator.class);
|
||||
HealthIndicator indicator = context
|
||||
.getBean(CompositeHealthIndicator.class);
|
||||
assertThat(indicator.health().getDetails())
|
||||
.containsOnlyKeys("dataSource", "testDataSource");
|
||||
HealthIndicator indicator = context.getBean(CompositeHealthIndicator.class);
|
||||
assertThat(indicator.health().getDetails()).containsOnlyKeys("dataSource", "testDataSource");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runShouldFilterRoutingDataSource() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
|
||||
RoutingDatasourceConfig.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(DataSourceHealthIndicator.class)
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, RoutingDatasourceConfig.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(DataSourceHealthIndicator.class)
|
||||
.doesNotHaveBean(CompositeHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWithValidationQueryPropertyShouldUseCustomQuery() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(DataSourceConfig.class,
|
||||
DataSourcePoolMetadataProvidersConfiguration.class)
|
||||
.withPropertyValues(
|
||||
"spring.datasource.test.validation-query:SELECT from FOOBAR")
|
||||
.run((context) -> {
|
||||
.withUserConfiguration(DataSourceConfig.class, DataSourcePoolMetadataProvidersConfiguration.class)
|
||||
.withPropertyValues("spring.datasource.test.validation-query:SELECT from FOOBAR").run((context) -> {
|
||||
assertThat(context).hasSingleBean(HealthIndicator.class);
|
||||
DataSourceHealthIndicator indicator = context
|
||||
.getBean(DataSourceHealthIndicator.class);
|
||||
DataSourceHealthIndicator indicator = context.getBean(DataSourceHealthIndicator.class);
|
||||
assertThat(indicator.getQuery()).isEqualTo("SELECT from FOOBAR");
|
||||
});
|
||||
}
|
||||
@@ -103,8 +93,7 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
.withPropertyValues("management.health.db.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(DataSourceHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(DataSourceHealthIndicator.class)
|
||||
.doesNotHaveBean(CompositeHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
@@ -116,10 +105,8 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.test")
|
||||
public DataSource testDataSource() {
|
||||
return DataSourceBuilder.create()
|
||||
.type(org.apache.tomcat.jdbc.pool.DataSource.class)
|
||||
.driverClassName("org.hsqldb.jdbc.JDBCDriver")
|
||||
.url("jdbc:hsqldb:mem:test").username("sa").build();
|
||||
return DataSourceBuilder.create().type(org.apache.tomcat.jdbc.pool.DataSource.class)
|
||||
.driverClassName("org.hsqldb.jdbc.JDBCDriver").url("jdbc:hsqldb:mem:test").username("sa").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,21 +37,18 @@ public class JmsHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ActiveMQAutoConfiguration.class,
|
||||
JmsHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
JmsHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(JmsHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(JmsHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.jms.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(LdapHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(LdapHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,49 +49,41 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class JolokiaEndpointAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
DispatcherServletAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class,
|
||||
ServletEndpointManagementContextConfiguration.class,
|
||||
JolokiaEndpointAutoConfiguration.class, TestConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(DispatcherServletAutoConfiguration.class,
|
||||
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
|
||||
ServletEndpointManagementContextConfiguration.class, JolokiaEndpointAutoConfiguration.class,
|
||||
TestConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void jolokiaServletShouldBeEnabledByDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
ExposableServletEndpoint endpoint = getEndpoint(context);
|
||||
assertThat(endpoint.getRootPath()).isEqualTo("jolokia");
|
||||
Object servlet = ReflectionTestUtils.getField(endpoint.getEndpointServlet(),
|
||||
"servlet");
|
||||
Object servlet = ReflectionTestUtils.getField(endpoint.getEndpointServlet(), "servlet");
|
||||
assertThat(servlet).isInstanceOf(AgentServlet.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jolokiaServletWhenDisabledShouldNotBeDiscovered() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.jolokia.enabled=false")
|
||||
.run((context) -> {
|
||||
Collection<ExposableServletEndpoint> endpoints = context
|
||||
.getBean(ServletEndpointsSupplier.class).getEndpoints();
|
||||
assertThat(endpoints).isEmpty();
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.jolokia.enabled=false").run((context) -> {
|
||||
Collection<ExposableServletEndpoint> endpoints = context.getBean(ServletEndpointsSupplier.class)
|
||||
.getEndpoints();
|
||||
assertThat(endpoints).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jolokiaServletWhenHasCustomConfigShouldApplyInitParams() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.jolokia.config.debug=true")
|
||||
.run((context) -> {
|
||||
ExposableServletEndpoint endpoint = getEndpoint(context);
|
||||
assertThat(endpoint.getEndpointServlet()).extracting("initParameters")
|
||||
.containsOnly(Collections.singletonMap("debug", "true"));
|
||||
});
|
||||
this.contextRunner.withPropertyValues("management.endpoint.jolokia.config.debug=true").run((context) -> {
|
||||
ExposableServletEndpoint endpoint = getEndpoint(context);
|
||||
assertThat(endpoint.getEndpointServlet()).extracting("initParameters")
|
||||
.containsOnly(Collections.singletonMap("debug", "true"));
|
||||
});
|
||||
}
|
||||
|
||||
private ExposableServletEndpoint getEndpoint(
|
||||
AssertableWebApplicationContext context) {
|
||||
Collection<ExposableServletEndpoint> endpoints = context
|
||||
.getBean(ServletEndpointsSupplier.class).getEndpoints();
|
||||
private ExposableServletEndpoint getEndpoint(AssertableWebApplicationContext context) {
|
||||
Collection<ExposableServletEndpoint> endpoints = context.getBean(ServletEndpointsSupplier.class).getEndpoints();
|
||||
return endpoints.iterator().next();
|
||||
}
|
||||
|
||||
@@ -99,10 +91,8 @@ public class JolokiaEndpointAutoConfigurationTests {
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public ServletEndpointDiscoverer servletEndpointDiscoverer(
|
||||
ApplicationContext applicationContext) {
|
||||
return new ServletEndpointDiscoverer(applicationContext, null,
|
||||
Collections.emptyList());
|
||||
public ServletEndpointDiscoverer servletEndpointDiscoverer(ApplicationContext applicationContext) {
|
||||
return new ServletEndpointDiscoverer(applicationContext, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,22 +40,19 @@ import static org.mockito.Mockito.mock;
|
||||
public class LdapHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(LdapConfiguration.class).withConfiguration(
|
||||
AutoConfigurations.of(LdapHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class));
|
||||
.withUserConfiguration(LdapConfiguration.class).withConfiguration(AutoConfigurations
|
||||
.of(LdapHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(LdapHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(LdapHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.ldap.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(LdapHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(LdapHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,46 +38,37 @@ import static org.mockito.Mockito.mock;
|
||||
public class LiquibaseEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(LiquibaseEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(LiquibaseEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withUserConfiguration(LiquibaseConfiguration.class).run(
|
||||
(context) -> assertThat(context).hasSingleBean(LiquibaseEndpoint.class));
|
||||
this.contextRunner.withUserConfiguration(LiquibaseConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(LiquibaseEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withUserConfiguration(LiquibaseConfiguration.class)
|
||||
.withPropertyValues("management.endpoint.liquibase.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(LiquibaseEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(LiquibaseEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disablesCloseOfDataSourceWhenEndpointIsEnabled() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(LiquibaseEndpoint.class);
|
||||
assertThat(context.getBean(DataSourceClosingSpringLiquibase.class))
|
||||
.hasFieldOrPropertyWithValue("closeDataSourceOnceMigrated",
|
||||
false);
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(LiquibaseEndpoint.class);
|
||||
assertThat(context.getBean(DataSourceClosingSpringLiquibase.class))
|
||||
.hasFieldOrPropertyWithValue("closeDataSourceOnceMigrated", false);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotDisableCloseOfDataSourceWhenEndpointIsDisabled() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class)
|
||||
.withPropertyValues("management.endpoint.liquibase.enabled:false")
|
||||
.run((context) -> {
|
||||
this.contextRunner.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class)
|
||||
.withPropertyValues("management.endpoint.liquibase.enabled:false").run((context) -> {
|
||||
assertThat(context).doesNotHaveBean(LiquibaseEndpoint.class);
|
||||
DataSourceClosingSpringLiquibase bean = context
|
||||
.getBean(DataSourceClosingSpringLiquibase.class);
|
||||
assertThat(bean).hasFieldOrPropertyWithValue(
|
||||
"closeDataSourceOnceMigrated", true);
|
||||
DataSourceClosingSpringLiquibase bean = context.getBean(DataSourceClosingSpringLiquibase.class);
|
||||
assertThat(bean).hasFieldOrPropertyWithValue("closeDataSourceOnceMigrated", true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -101,11 +92,10 @@ public class LiquibaseEndpointAutoConfigurationTests {
|
||||
private boolean propertiesSet = false;
|
||||
|
||||
@Override
|
||||
public void setCloseDataSourceOnceMigrated(
|
||||
boolean closeDataSourceOnceMigrated) {
|
||||
public void setCloseDataSourceOnceMigrated(boolean closeDataSourceOnceMigrated) {
|
||||
if (this.propertiesSet) {
|
||||
throw new IllegalStateException("setCloseDataSourceOnceMigrated "
|
||||
+ "invoked after afterPropertiesSet");
|
||||
throw new IllegalStateException(
|
||||
"setCloseDataSourceOnceMigrated " + "invoked after afterPropertiesSet");
|
||||
}
|
||||
super.setCloseDataSourceOnceMigrated(closeDataSourceOnceMigrated);
|
||||
}
|
||||
|
||||
@@ -49,48 +49,40 @@ public class LogFileWebEndpointAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void logFileWebEndpointIsAutoConfiguredWhenLoggingFileIsSet() {
|
||||
this.contextRunner.withPropertyValues("logging.file:test.log").run(
|
||||
(context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("logging.file:test.log")
|
||||
.run((context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logFileWebEndpointIsAutoConfiguredWhenLoggingPathIsSet() {
|
||||
this.contextRunner.withPropertyValues("logging.path:test/logs").run(
|
||||
(context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("logging.path:test/logs")
|
||||
.run((context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logFileWebEndpointIsAutoConfiguredWhenExternalFileIsSet() {
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"management.endpoint.logfile.external-file:external.log")
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(LogFileWebEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.logfile.external-file:external.log")
|
||||
.run((context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logFileWebEndpointCanBeDisabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("logging.file:test.log",
|
||||
"management.endpoint.logfile.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(LogFileWebEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("logging.file:test.log", "management.endpoint.logfile.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(LogFileWebEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logFileWebEndpointUsesConfiguredExternalFile() throws IOException {
|
||||
File file = this.temp.newFile("logfile");
|
||||
FileCopyUtils.copy("--TEST--".getBytes(), file);
|
||||
this.contextRunner.withPropertyValues(
|
||||
"management.endpoint.logfile.external-file:" + file.getAbsolutePath())
|
||||
this.contextRunner.withPropertyValues("management.endpoint.logfile.external-file:" + file.getAbsolutePath())
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(LogFileWebEndpoint.class);
|
||||
LogFileWebEndpoint endpoint = context
|
||||
.getBean(LogFileWebEndpoint.class);
|
||||
LogFileWebEndpoint endpoint = context.getBean(LogFileWebEndpoint.class);
|
||||
Resource resource = endpoint.logFile();
|
||||
assertThat(resource).isNotNull();
|
||||
assertThat(StreamUtils.copyToString(resource.getInputStream(),
|
||||
StandardCharsets.UTF_8)).isEqualTo("--TEST--");
|
||||
assertThat(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8))
|
||||
.isEqualTo("--TEST--");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,30 +36,24 @@ import static org.mockito.Mockito.mock;
|
||||
public class LoggersEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(LoggersEndpointAutoConfiguration.class))
|
||||
.withConfiguration(AutoConfigurations.of(LoggersEndpointAutoConfiguration.class))
|
||||
.withUserConfiguration(LoggingConfiguration.class);
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(LoggersEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(LoggersEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.loggers.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(LoggersEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(LoggersEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWithNoneLoggingSystemShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.withSystemProperties(
|
||||
"org.springframework.boot.logging.LoggingSystem=none")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(LoggersEndpoint.class));
|
||||
this.contextRunner.withSystemProperties("org.springframework.boot.logging.LoggingSystem=none")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(LoggersEndpoint.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,22 +36,19 @@ public class MailHealthIndicatorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class,
|
||||
MailHealthIndicatorAutoConfiguration.class,
|
||||
HealthIndicatorAutoConfiguration.class))
|
||||
MailHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class))
|
||||
.withPropertyValues("spring.mail.host:smtp.example.com");
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(MailHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(MailHealthIndicator.class)
|
||||
.doesNotHaveBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.mail.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(MailHealthIndicator.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MailHealthIndicator.class)
|
||||
.hasSingleBean(ApplicationHealthIndicator.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,16 +36,13 @@ public class HeapDumpWebEndpointAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(HeapDumpWebEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HeapDumpWebEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.heapdump.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(HeapDumpWebEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.heapdump.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(HeapDumpWebEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,21 +32,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class ThreadDumpEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(ThreadDumpEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ThreadDumpEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(ThreadDumpEndpoint.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ThreadDumpEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoint.threaddump.enabled:false")
|
||||
.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(ThreadDumpEndpoint.class));
|
||||
this.contextRunner.withPropertyValues("management.endpoint.threaddump.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ThreadDumpEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,55 +42,47 @@ public class CompositeMeterRegistryAutoConfigurationTests {
|
||||
private static final String COMPOSITE_NAME = "compositeMeterRegistry";
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(BaseConfig.class).withConfiguration(
|
||||
AutoConfigurations.of(CompositeMeterRegistryAutoConfiguration.class));
|
||||
.withUserConfiguration(BaseConfig.class)
|
||||
.withConfiguration(AutoConfigurations.of(CompositeMeterRegistryAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void registerWhenHasNoMeterRegistryShouldRegisterEmptyNoOpComposite() {
|
||||
this.contextRunner.withUserConfiguration(NoMeterRegistryConfig.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(MeterRegistry.class);
|
||||
CompositeMeterRegistry registry = context.getBean("noOpMeterRegistry",
|
||||
CompositeMeterRegistry.class);
|
||||
assertThat(registry.getRegistries()).isEmpty();
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(NoMeterRegistryConfig.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(MeterRegistry.class);
|
||||
CompositeMeterRegistry registry = context.getBean("noOpMeterRegistry", CompositeMeterRegistry.class);
|
||||
assertThat(registry.getRegistries()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerWhenHasSingleMeterRegistryShouldDoNothing() {
|
||||
this.contextRunner.withUserConfiguration(SingleMeterRegistryConfig.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(MeterRegistry.class);
|
||||
MeterRegistry registry = context.getBean(MeterRegistry.class);
|
||||
assertThat(registry).isInstanceOf(TestMeterRegistry.class);
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(SingleMeterRegistryConfig.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(MeterRegistry.class);
|
||||
MeterRegistry registry = context.getBean(MeterRegistry.class);
|
||||
assertThat(registry).isInstanceOf(TestMeterRegistry.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerWhenHasMultipleMeterRegistriesShouldAddPrimaryComposite() {
|
||||
this.contextRunner.withUserConfiguration(MultipleMeterRegistriesConfig.class)
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(3)
|
||||
.containsKeys("meterRegistryOne", "meterRegistryTwo",
|
||||
COMPOSITE_NAME);
|
||||
MeterRegistry primary = context.getBean(MeterRegistry.class);
|
||||
assertThat(primary).isInstanceOf(CompositeMeterRegistry.class);
|
||||
assertThat(((CompositeMeterRegistry) primary).getRegistries())
|
||||
.hasSize(2);
|
||||
assertThat(primary.config().clock()).isNotNull();
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(MultipleMeterRegistriesConfig.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(3).containsKeys("meterRegistryOne",
|
||||
"meterRegistryTwo", COMPOSITE_NAME);
|
||||
MeterRegistry primary = context.getBean(MeterRegistry.class);
|
||||
assertThat(primary).isInstanceOf(CompositeMeterRegistry.class);
|
||||
assertThat(((CompositeMeterRegistry) primary).getRegistries()).hasSize(2);
|
||||
assertThat(primary.config().clock()).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerWhenHasMultipleRegistriesAndOneIsPrimaryShouldDoNothing() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(MultipleMeterRegistriesWithOnePrimaryConfig.class)
|
||||
.run((context) -> {
|
||||
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(2)
|
||||
.containsKeys("meterRegistryOne", "meterRegistryTwo");
|
||||
MeterRegistry primary = context.getBean(MeterRegistry.class);
|
||||
assertThat(primary).isInstanceOf(TestMeterRegistry.class);
|
||||
});
|
||||
this.contextRunner.withUserConfiguration(MultipleMeterRegistriesWithOnePrimaryConfig.class).run((context) -> {
|
||||
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(2).containsKeys("meterRegistryOne",
|
||||
"meterRegistryTwo");
|
||||
MeterRegistry primary = context.getBean(MeterRegistry.class);
|
||||
assertThat(primary).isInstanceOf(TestMeterRegistry.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,70 +38,55 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class JvmMetricsAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.with(MetricsRun.simple())
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
|
||||
.withConfiguration(AutoConfigurations.of(JvmMetricsAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void autoConfiguresJvmMetrics() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(JvmGcMetrics.class).hasSingleBean(JvmMemoryMetrics.class)
|
||||
.hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class));
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class).hasSingleBean(JvmMemoryMetrics.class)
|
||||
.hasSingleBean(JvmThreadMetrics.class).hasSingleBean(ClassLoaderMetrics.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
public void allowsJvmMetricsToBeDisabled() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.metrics.binders.jvm.enabled=false")
|
||||
this.contextRunner.withPropertyValues("management.metrics.binders.jvm.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JvmGcMetrics.class)
|
||||
.doesNotHaveBean(JvmMemoryMetrics.class)
|
||||
.doesNotHaveBean(JvmThreadMetrics.class)
|
||||
.doesNotHaveBean(JvmMemoryMetrics.class).doesNotHaveBean(JvmThreadMetrics.class)
|
||||
.doesNotHaveBean(ClassLoaderMetrics.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsCustomJvmGcMetricsToBeUsed() {
|
||||
this.contextRunner.withUserConfiguration(CustomJvmGcMetricsConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
|
||||
.hasBean("customJvmGcMetrics")
|
||||
.hasSingleBean(JvmMemoryMetrics.class)
|
||||
.hasSingleBean(JvmThreadMetrics.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class).hasBean("customJvmGcMetrics")
|
||||
.hasSingleBean(JvmMemoryMetrics.class).hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsCustomJvmMemoryMetricsToBeUsed() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomJvmMemoryMetricsConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(CustomJvmMemoryMetricsConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
|
||||
.hasSingleBean(JvmMemoryMetrics.class)
|
||||
.hasBean("customJvmMemoryMetrics")
|
||||
.hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class));
|
||||
.hasSingleBean(JvmMemoryMetrics.class).hasBean("customJvmMemoryMetrics")
|
||||
.hasSingleBean(JvmThreadMetrics.class).hasSingleBean(ClassLoaderMetrics.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsCustomJvmThreadMetricsToBeUsed() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomJvmThreadMetricsConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(CustomJvmThreadMetricsConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
|
||||
.hasSingleBean(JvmMemoryMetrics.class)
|
||||
.hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class)
|
||||
.hasBean("customJvmThreadMetrics"));
|
||||
.hasSingleBean(JvmMemoryMetrics.class).hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class).hasBean("customJvmThreadMetrics"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsCustomClassLoaderMetricsToBeUsed() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(CustomClassLoaderMetricsConfiguration.class)
|
||||
this.contextRunner.withUserConfiguration(CustomClassLoaderMetricsConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
|
||||
.hasSingleBean(JvmMemoryMetrics.class)
|
||||
.hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class)
|
||||
.hasBean("customClassLoaderMetrics"));
|
||||
.hasSingleBean(JvmMemoryMetrics.class).hasSingleBean(JvmThreadMetrics.class)
|
||||
.hasSingleBean(ClassLoaderMetrics.class).hasBean("customClassLoaderMetrics"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,31 +35,25 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class KafkaMetricsAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.with(MetricsRun.simple()).withConfiguration(
|
||||
AutoConfigurations.of(KafkaMetricsAutoConfiguration.class));
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
|
||||
.withConfiguration(AutoConfigurations.of(KafkaMetricsAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void whenThereIsNoMBeanServerAutoConfigurationBacksOff() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.doesNotHaveBean(KafkaConsumerMetrics.class));
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(KafkaConsumerMetrics.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenThereIsAnMBeanServerKafkaConsumerMetricsIsConfigured() {
|
||||
this.contextRunner
|
||||
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(KafkaConsumerMetrics.class));
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(KafkaConsumerMetrics.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsCustomKafkaConsumerMetricsToBeUsed() {
|
||||
this.contextRunner
|
||||
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
|
||||
.withUserConfiguration(CustomKafkaConsumerMetricsConfiguration.class)
|
||||
.run((context) -> assertThat(context)
|
||||
.hasSingleBean(KafkaConsumerMetrics.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(KafkaConsumerMetrics.class)
|
||||
.hasBean("customKafkaConsumerMetrics"));
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user