This commit is contained in:
Phillip Webb
2017-08-28 15:29:36 -07:00
parent b02edd2e81
commit 2c97d3a5e9
143 changed files with 689 additions and 655 deletions

View File

@@ -26,6 +26,8 @@ import org.springframework.context.annotation.Conditional;
/**
* {@link Conditional} that matches based on the configuration of the management port.
*
* @since 2.0.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })

View File

@@ -35,6 +35,10 @@ import org.springframework.context.annotation.Import;
@Import(ManagementContextConfigurationImportSelector.class)
@interface EnableManagementContext {
/**
* The management context type that should be enabled.
* @return the management context type
*/
ManagementContextType value();
}

View File

@@ -37,6 +37,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.util.Assert;
import org.springframework.web.context.ConfigurableWebApplicationContext;
/**
@@ -58,7 +59,7 @@ public class ManagementContextAutoConfiguration {
@Bean
public ManagementServletContext managementServletContext(
final ManagementServerProperties properties) {
ManagementServerProperties properties) {
return () -> properties.getContextPath();
}
@@ -86,12 +87,11 @@ public class ManagementContextAutoConfiguration {
}
private void verifySslConfiguration() {
if (this.environment.getProperty("management.ssl.enabled", Boolean.class,
false)) {
throw new IllegalStateException(
"Management-specific SSL cannot be configured as the management "
+ "server is not listening on a separate port");
}
Boolean enabled = this.environment.getProperty("management.ssl.enabled",
Boolean.class, false);
Assert.state(!enabled,
"Management-specific SSL cannot be configured as the management "
+ "server is not listening on a separate port");
}
private void verifyContextPathConfiguration() {
@@ -112,6 +112,7 @@ public class ManagementContextAutoConfiguration {
ConfigurableEnvironment environment) {
environment.getPropertySources()
.addLast(new PropertySource<Object>("Management Server") {
@Override
public Object getProperty(String name) {
if ("local.management.port".equals(name)) {
@@ -119,6 +120,7 @@ public class ManagementContextAutoConfiguration {
}
return null;
}
});
}

View File

@@ -122,8 +122,8 @@ class ManagementContextConfigurationImportSelector
Map<String, Object> annotationAttributes = annotationMetadata
.getAnnotationAttributes(
ManagementContextConfiguration.class.getName());
return annotationAttributes == null ? ManagementContextType.ANY
: (ManagementContextType) annotationAttributes.get("value");
return (annotationAttributes == null ? ManagementContextType.ANY
: (ManagementContextType) annotationAttributes.get("value"));
}
private int readOrder(AnnotationMetadata annotationMetadata) {

View File

@@ -27,7 +27,13 @@ import org.springframework.context.ConfigurableApplicationContext;
*/
interface ManagementContextFactory {
/**
* Create the management application context.
* @param parent the parent context
* @param configurationClasses the configuration classes
* @return a configured application context
*/
ConfigurableApplicationContext createManagementContext(ApplicationContext parent,
Class<?>... configClasses);
Class<?>... configurationClasses);
}

View File

@@ -18,6 +18,12 @@ package org.springframework.boot.actuate.autoconfigure;
import org.springframework.core.env.Environment;
/**
* Port types that can be used to control how the management server is started.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
public enum ManagementPortType {
/**

View File

@@ -78,8 +78,8 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
* @author Eddú Meléndez
* @author Meang Akira Tanaka
* @author Ben Hale
* @since 2.0.0
* @author Andy Wilkinson
* @since 2.0.0
*/
@Configuration
@AutoConfigureAfter({ FlywayAutoConfiguration.class, LiquibaseAutoConfiguration.class })

View File

@@ -20,8 +20,8 @@ import org.springframework.boot.actuate.autoconfigure.web.ManagementServerProper
import org.springframework.boot.endpoint.EndpointPathResolver;
/**
* {@link EndpointPathResolver} implementation for resolving
* actuator endpoint paths based on the endpoint id and management.context-path.
* {@link EndpointPathResolver} implementation for resolving actuator endpoint paths based
* on the endpoint id and management.context-path.
*
* @author Madhura Bhave
* @since 2.0.0
@@ -38,5 +38,5 @@ public class ManagementEndpointPathResolver implements EndpointPathResolver {
public String resolvePath(String endpointId) {
return this.contextPath + "/" + endpointId;
}
}
}

View File

@@ -51,9 +51,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory {
@Override
public ObjectName generate(EndpointMBean mBean) throws MalformedObjectNameException {
String baseObjectName = this.properties.getDomain() +
":type=Endpoint" +
",name=" + StringUtils.capitalize(mBean.getEndpointId());
String baseObjectName = this.properties.getDomain() + ":type=Endpoint" + ",name="
+ StringUtils.capitalize(mBean.getEndpointId());
StringBuilder builder = new StringBuilder(baseObjectName);
if (this.mBeanServer != null && hasMBean(baseObjectName)) {
builder.append(",context=").append(this.contextId);
@@ -76,7 +75,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory {
}
StringBuilder builder = new StringBuilder();
for (Map.Entry<Object, Object> name : this.properties.getStaticNames().entrySet()) {
for (Map.Entry<Object, Object> name : this.properties.getStaticNames()
.entrySet()) {
builder.append(",").append(name.getKey()).append("=").append(name.getValue());
}
return builder.toString();

View File

@@ -71,17 +71,20 @@ public class EndpointInfrastructureAutoConfiguration {
@Bean
public OperationParameterMapper operationParameterMapper() {
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(String.class, Date.class, (string) -> {
if (StringUtils.hasLength(string)) {
OffsetDateTime offsetDateTime = OffsetDateTime.parse(string,
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return new Date(offsetDateTime.toEpochSecond() * 1000);
}
return null;
});
conversionService.addConverter(String.class, Date.class, this::convertToDate);
return new ConversionServiceOperationParameterMapper(conversionService);
}
private Date convertToDate(String value) {
if (StringUtils.hasLength(value)) {
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value,
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return new Date(offsetDateTime.toEpochSecond() * 1000);
}
return null;
}
@Bean
public CachingConfigurationFactory cacheConfigurationFactory() {
return new CachingConfigurationFactory(this.applicationContext.getEnvironment());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -61,8 +61,9 @@ public class EndpointEnablementProvider {
public EndpointEnablement getEndpointEnablement(String endpointId,
boolean enabledByDefault, EndpointExposure exposure) {
Assert.hasText(endpointId, "Endpoint id must have a value");
Assert.isTrue(!endpointId.equals("default"), "Endpoint id 'default' is a reserved "
+ "value and cannot be used by an endpoint");
Assert.isTrue(!endpointId.equals("default"),
"Endpoint id 'default' is a reserved "
+ "value and cannot be used by an endpoint");
EndpointEnablement result = findEnablement(endpointId, exposure);
if (result != null) {
return result;
@@ -76,8 +77,7 @@ public class EndpointEnablementProvider {
if (!enabledByDefault) {
return getDefaultEndpointEnablement(endpointId, false, exposure);
}
return getGlobalEndpointEnablement(endpointId, enabledByDefault,
exposure);
return getGlobalEndpointEnablement(endpointId, enabledByDefault, exposure);
}
private EndpointEnablement findEnablement(String endpointId,
@@ -98,12 +98,10 @@ public class EndpointEnablementProvider {
if (result != null) {
return result;
}
return getDefaultEndpointEnablement(endpointId, enabledByDefault,
exposure);
return getDefaultEndpointEnablement(endpointId, enabledByDefault, exposure);
}
private EndpointEnablement findGlobalEndpointEnablement(
EndpointExposure exposure) {
private EndpointEnablement findGlobalEndpointEnablement(EndpointExposure exposure) {
if (exposure != null) {
EndpointEnablement result = findEnablement(getKey("default", exposure));
if (result != null) {
@@ -136,8 +134,8 @@ public class EndpointEnablementProvider {
private EndpointEnablement getDefaultEndpointEnablement(String endpointId,
boolean enabledByDefault, EndpointExposure exposure) {
return new EndpointEnablement(enabledByDefault, createDefaultEnablementMessage(
endpointId, enabledByDefault, exposure));
return new EndpointEnablement(enabledByDefault,
createDefaultEnablementMessage(endpointId, enabledByDefault, exposure));
}
private String createDefaultEnablementMessage(String endpointId,
@@ -145,8 +143,7 @@ public class EndpointEnablementProvider {
StringBuilder message = new StringBuilder();
message.append(String.format("endpoint '%s' ", endpointId));
if (exposure != null) {
message.append(
String.format("(%s) ", exposure.name().toLowerCase()));
message.append(String.format("(%s) ", exposure.name().toLowerCase()));
}
message.append(String.format("is %s by default",
(enabledByDefault ? "enabled" : "disabled")));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -32,12 +32,10 @@ import org.springframework.web.servlet.mvc.ServletWrappingController;
/**
* {@link ManagementContextConfiguration} for embedding Jolokia, a JMX-HTTP bridge giving
* an alternative to JSR-160 connectors.
*
* <p>
* This configuration will get automatically enabled as soon as the Jolokia
* {@link AgentServlet} is on the classpath. To disable it set
* {@code management.jolokia.enabled=false}.
*
* <p>
* Additional configuration parameters for Jolokia can be provided by specifying
* {@code management.jolokia.config.*} properties. See the

View File

@@ -31,6 +31,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
* Security configuration for management endpoints.
*
* @author Madhura Bhave
* @since 2.0.0
*/
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@@ -39,9 +40,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
public class ManagementWebSecurityAutoConfiguration {
@Bean
public EndpointPathResolver managementEndpointPathResolver(ManagementServerProperties properties) {
public EndpointPathResolver managementEndpointPathResolver(
ManagementServerProperties properties) {
return new ManagementEndpointPathResolver(properties);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -66,32 +66,33 @@ public class CloudFoundryActuatorAutoConfiguration {
@Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
EndpointProvider<WebEndpointOperation> provider,
Environment environment, RestTemplateBuilder builder) {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = new CloudFoundryWebEndpointServletHandlerMapping(
EndpointProvider<WebEndpointOperation> provider, Environment environment,
RestTemplateBuilder builder) {
return new CloudFoundryWebEndpointServletHandlerMapping(
"/cloudfoundryapplication", provider.getEndpoints(),
getCorsConfiguration(), getSecurityInterceptor(builder, environment));
return handlerMapping;
}
private CloudFoundrySecurityInterceptor getSecurityInterceptor(
RestTemplateBuilder restTemplateBuilder, Environment environment) {
CloudFoundrySecurityService cloudfoundrySecurityService = getCloudFoundrySecurityService(
restTemplateBuilder, environment);
TokenValidator tokenValidator = new TokenValidator(cloudfoundrySecurityService);
return new CloudFoundrySecurityInterceptor(
tokenValidator, cloudfoundrySecurityService,
TokenValidator tokenValidator = new TokenValidator(
cloudfoundrySecurityService);
return new CloudFoundrySecurityInterceptor(tokenValidator,
cloudfoundrySecurityService,
environment.getProperty("vcap.application.application_id"));
}
private CloudFoundrySecurityService getCloudFoundrySecurityService(
RestTemplateBuilder restTemplateBuilder, Environment environment) {
String cloudControllerUrl = environment.getProperty("vcap.application.cf_api");
String cloudControllerUrl = environment
.getProperty("vcap.application.cf_api");
boolean skipSslValidation = environment.getProperty(
"management.cloudfoundry.skip-ssl-validation", Boolean.class, false);
return cloudControllerUrl == null ? null
: new CloudFoundrySecurityService(restTemplateBuilder, cloudControllerUrl,
skipSslValidation);
return (cloudControllerUrl == null ? null
: new CloudFoundrySecurityService(restTemplateBuilder,
cloudControllerUrl, skipSslValidation));
}
private CorsConfiguration getCorsConfiguration() {
@@ -107,9 +108,9 @@ public class CloudFoundryActuatorAutoConfiguration {
}
/**
* {@link WebSecurityConfigurer} to tell Spring Security to
* ignore cloudfoundry specific paths. The Cloud foundry endpoints
* are protected by their own security interceptor.
* {@link WebSecurityConfigurer} to tell Spring Security to ignore cloudfoundry
* specific paths. The Cloud foundry endpoints are protected by their own security
* interceptor.
*/
@ConditionalOnClass(WebSecurity.class)
@Order(SecurityProperties.IGNORED_ORDER)
@@ -119,7 +120,8 @@ public class CloudFoundryActuatorAutoConfiguration {
@Override
public void init(WebSecurity builder) throws Exception {
builder.ignoring().requestMatchers(new AntPathRequestMatcher("/cloudfoundryapplication/**"));
builder.ignoring().requestMatchers(
new AntPathRequestMatcher("/cloudfoundryapplication/**"));
}
@Override

View File

@@ -52,18 +52,19 @@ class CloudFoundrySecurityInterceptor {
this.applicationId = applicationId;
}
SecurityResponse preHandle(HttpServletRequest request,
String endpointId) {
SecurityResponse preHandle(HttpServletRequest request, String endpointId) {
if (CorsUtils.isPreFlightRequest(request)) {
return SecurityResponse.success();
}
try {
if (!StringUtils.hasText(this.applicationId)) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE,
throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE,
"Application id is not available");
}
if (this.cloudFoundrySecurityService == null) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE,
throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE,
"Cloud controller URL is not available");
}
if (HttpMethod.OPTIONS.matches(request.getMethod())) {
@@ -75,21 +76,23 @@ class CloudFoundrySecurityInterceptor {
logger.error(ex);
if (ex instanceof CloudFoundryAuthorizationException) {
CloudFoundryAuthorizationException cfException = (CloudFoundryAuthorizationException) ex;
return new SecurityResponse(cfException.getStatusCode(), "{\"security_error\":\"" + cfException.getMessage() + "\"}");
return new SecurityResponse(cfException.getStatusCode(),
"{\"security_error\":\"" + cfException.getMessage() + "\"}");
}
return new SecurityResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
return new SecurityResponse(HttpStatus.INTERNAL_SERVER_ERROR,
ex.getMessage());
}
return SecurityResponse.success();
}
private void check(HttpServletRequest request, String path)
throws Exception {
private void check(HttpServletRequest request, String path) throws Exception {
Token token = getToken(request);
this.tokenValidator.validate(token);
AccessLevel accessLevel = this.cloudFoundrySecurityService
.getAccessLevel(token.toString(), this.applicationId);
if (!accessLevel.isAccessAllowed(path)) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.ACCESS_DENIED,
throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.ACCESS_DENIED,
"Access denied");
}
accessLevel.put(request);
@@ -100,7 +103,8 @@ class CloudFoundrySecurityInterceptor {
String bearerPrefix = "bearer ";
if (authorization == null
|| !authorization.toLowerCase().startsWith(bearerPrefix)) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.MISSING_AUTHORIZATION,
throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.MISSING_AUTHORIZATION,
"Authorization header is missing or invalid");
}
return new Token(authorization.substring(bearerPrefix.length()));
@@ -116,7 +120,7 @@ class CloudFoundrySecurityInterceptor {
private final String message;
SecurityResponse(HttpStatus status) {
this (status, null);
this(status, null);
}
SecurityResponse(HttpStatus status, String message) {
@@ -135,7 +139,7 @@ class CloudFoundrySecurityInterceptor {
static SecurityResponse success() {
return new SecurityResponse(HttpStatus.OK);
}
}
}

View File

@@ -50,18 +50,20 @@ import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
/**
* A custom {@link RequestMappingInfoHandlerMapping} that makes web endpoints available
* on Cloudfoundry specific URLS over HTTP using Spring MVC.
* A custom {@link RequestMappingInfoHandlerMapping} that makes web endpoints available on
* Cloudfoundry specific URLS over HTTP using Spring MVC.
*
* @author Madhura Bhave
*/
class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointServletHandlerMapping {
class CloudFoundryWebEndpointServletHandlerMapping
extends AbstractWebEndpointServletHandlerMapping {
private final Method handle = ReflectionUtils.findMethod(OperationHandler.class,
"handle", HttpServletRequest.class, Map.class);
private final Method links = ReflectionUtils.findMethod(
CloudFoundryWebEndpointServletHandlerMapping.class, "links", HttpServletRequest.class, HttpServletResponse.class);
CloudFoundryWebEndpointServletHandlerMapping.class, "links",
HttpServletRequest.class, HttpServletResponse.class);
private static final Log logger = LogFactory
.getLog(CloudFoundryWebEndpointServletHandlerMapping.class);
@@ -70,7 +72,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
private final EndpointLinksResolver endpointLinksResolver = new EndpointLinksResolver();
CloudFoundryWebEndpointServletHandlerMapping(String endpointPath, Collection<EndpointInfo<WebEndpointOperation>> webEndpoints, CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor) {
CloudFoundryWebEndpointServletHandlerMapping(String endpointPath,
Collection<EndpointInfo<WebEndpointOperation>> webEndpoints,
CorsConfiguration corsConfiguration,
CloudFoundrySecurityInterceptor securityInterceptor) {
super(endpointPath, webEndpoints, corsConfiguration);
this.securityInterceptor = securityInterceptor;
}
@@ -81,27 +86,32 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
}
@ResponseBody
private Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor.preHandle(request, "");
private Map<String, Map<String, Link>> links(HttpServletRequest request,
HttpServletResponse response) {
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor
.preHandle(request, "");
if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
sendFailureResponse(response, securityResponse);
}
AccessLevel accessLevel = AccessLevel.get(request);
Map<String, Link> links = this.endpointLinksResolver
.resolveLinks(getEndpoints(), request.getRequestURL().toString());
Map<String, Link> links = this.endpointLinksResolver.resolveLinks(getEndpoints(),
request.getRequestURL().toString());
Map<String, Link> filteredLinks = new LinkedHashMap<>();
if (accessLevel == null) {
return Collections.singletonMap("_links", filteredLinks);
}
filteredLinks = links.entrySet().stream()
.filter(e -> e.getKey().equals("self") || accessLevel.isAccessAllowed(e.getKey()))
.filter(e -> e.getKey().equals("self")
|| accessLevel.isAccessAllowed(e.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return Collections.singletonMap("_links", filteredLinks);
}
private void sendFailureResponse(HttpServletResponse response, CloudFoundrySecurityInterceptor.SecurityResponse securityResponse) {
private void sendFailureResponse(HttpServletResponse response,
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse) {
try {
response.sendError(securityResponse.getStatus().value(), securityResponse.getMessage());
response.sendError(securityResponse.getStatus().value(),
securityResponse.getMessage());
}
catch (Exception ex) {
logger.debug("Failed to send error response", ex);
@@ -111,7 +121,9 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
@Override
protected void registerMappingForOperation(WebEndpointOperation operation) {
registerMapping(createRequestMappingInfo(operation),
new OperationHandler(operation.getInvoker(), operation.getId(), this.securityInterceptor), this.handle);
new OperationHandler(operation.getInvoker(), operation.getId(),
this.securityInterceptor),
this.handle);
}
/**
@@ -125,7 +137,8 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
private final CloudFoundrySecurityInterceptor securityInterceptor;
OperationHandler(OperationInvoker operationInvoker, String id, CloudFoundrySecurityInterceptor securityInterceptor) {
OperationHandler(OperationInvoker operationInvoker, String id,
CloudFoundrySecurityInterceptor securityInterceptor) {
this.operationInvoker = operationInvoker;
this.endpointId = id;
this.securityInterceptor = securityInterceptor;
@@ -135,7 +148,8 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
@ResponseBody
public Object handle(HttpServletRequest request,
@RequestBody(required = false) Map<String, String> body) {
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor.preHandle(request, this.endpointId);
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor
.preHandle(request, this.endpointId);
if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
return failureResponse(securityResponse);
}
@@ -155,8 +169,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
}
}
private Object failureResponse(CloudFoundrySecurityInterceptor.SecurityResponse response) {
return handleResult(new WebEndpointResponse<>(response.getMessage(), response.getStatus().value()));
private Object failureResponse(
CloudFoundrySecurityInterceptor.SecurityResponse response) {
return handleResult(new WebEndpointResponse<>(response.getMessage(),
response.getStatus().value()));
}
private Object handleResult(Object result) {
@@ -179,4 +195,3 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@@ -91,4 +91,3 @@ class SkipSslVerificationHttpRequestFactory extends SimpleClientHttpRequestFacto
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -32,7 +32,7 @@ import java.util.regex.PatternSyntaxException;
* @author Phillip Webb
* @author Sergei Egorov
* @author Andy Wilkinson
* @since 2.0.0
* @author Dylian Bego
*/
abstract class NamePatternFilter<T> {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -16,7 +16,9 @@
package org.springframework.boot.actuate.endpoint.web;
import java.io.Closeable;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
@@ -206,12 +208,7 @@ public class HeapDumpWebEndpoint {
@Override
public void close() throws IOException {
try {
readableChannel.close();
}
finally {
deleteFile();
}
closeThenDeleteFile(readableChannel);
}
@Override
@@ -224,62 +221,25 @@ public class HeapDumpWebEndpoint {
@Override
public InputStream getInputStream() throws IOException {
InputStream delegate = super.getInputStream();
return new InputStream() {
@Override
public int read() throws IOException {
return delegate.read();
}
@Override
public int read(byte[] b) throws IOException {
return delegate.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return delegate.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return delegate.skip(n);
}
@Override
public int available() throws IOException {
return delegate.available();
}
return new FilterInputStream(super.getInputStream()) {
@Override
public void close() throws IOException {
try {
delegate.close();
}
finally {
deleteFile();
}
}
@Override
public synchronized void mark(int readlimit) {
delegate.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
delegate.reset();
}
@Override
public boolean markSupported() {
return delegate.markSupported();
closeThenDeleteFile(this.in);
}
};
}
private void closeThenDeleteFile(Closeable closeable) throws IOException {
try {
closeable.close();
}
finally {
deleteFile();
}
}
private void deleteFile() {
try {
Files.delete(getFile().toPath());

View File

@@ -35,8 +35,7 @@ public class HealthIndicatorFactory {
* @return a {@link HealthIndicator} that delegates to the specified
* {@code healthIndicators}.
*/
public HealthIndicator createHealthIndicator(
HealthAggregator healthAggregator,
public HealthIndicator createHealthIndicator(HealthAggregator healthAggregator,
Map<String, HealthIndicator> healthIndicators) {
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
Assert.notNull(healthIndicators, "HealthIndicators must not be null");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -118,10 +118,9 @@ public class ConditionalOnEnabledEndpointTests {
@Test
public void disabledEvenWithEnabledGeneralProperties() {
this.contextRunner.withUserConfiguration(FooConfig.class)
.withPropertyValues("endpoints.default.enabled=true",
"endpoints.default.web.enabled=true",
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false")
this.contextRunner.withUserConfiguration(FooConfig.class).withPropertyValues(
"endpoints.default.enabled=true", "endpoints.default.web.enabled=true",
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
}

View File

@@ -41,7 +41,8 @@ public class DefaultEndpointObjectNameFactoryTests {
private final MockEnvironment environment = new MockEnvironment();
private final JmxEndpointExporterProperties properties = new JmxEndpointExporterProperties(this.environment);
private final JmxEndpointExporterProperties properties = new JmxEndpointExporterProperties(
this.environment);
private final MBeanServer mBeanServer = mock(MBeanServer.class);
@@ -50,23 +51,23 @@ public class DefaultEndpointObjectNameFactoryTests {
@Test
public void generateObjectName() {
ObjectName objectName = generateObjectName(endpoint("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("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 generateObjectNameWithCustomDomain() {
this.properties.setDomain("com.example.acme");
ObjectName objectName = generateObjectName(endpoint("test"));
assertThat(objectName.toString()).isEqualTo(
"com.example.acme:type=Endpoint,name=Test");
assertThat(objectName.toString())
.isEqualTo("com.example.acme:type=Endpoint,name=Test");
}
@Test
@@ -86,17 +87,18 @@ public class DefaultEndpointObjectNameFactoryTests {
ObjectName objectName = generateObjectName(endpoint("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("test"));
assertThat(objectName.toString()).isEqualTo(
"org.springframework.boot:type=Endpoint,name=Test,context=testContext");

View File

@@ -57,25 +57,18 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests {
@Test
public void webEndpointsAreDisabledByDefault() {
this.contextRunner.run(context -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace")).isFalse();
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mvc, HttpMethod.GET, "autoconfig")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "beans")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "configprops")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "env")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "health")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "info")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "mappings")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "metrics")).isFalse();
assertThat(isExposed(mvc, HttpMethod.POST, "shutdown")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "threaddump")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "trace")).isFalse();
});
}
@@ -84,60 +77,45 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests {
WebApplicationContextRunner contextRunner = this.contextRunner
.withPropertyValues("endpoints.default.web.enabled=true");
contextRunner.run(context -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace"))
.isTrue();
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mvc, HttpMethod.GET, "autoconfig")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "beans")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "configprops")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "env")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "health")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "info")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "mappings")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "metrics")).isTrue();
assertThat(isExposed(mvc, HttpMethod.POST, "shutdown")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "threaddump")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "trace")).isTrue();
});
}
@Test
public void singleWebEndpointCanBeEnabled() {
WebApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
"endpoints.default.web.enabled=false", "endpoints.beans.web.enabled=true");
"endpoints.default.web.enabled=false",
"endpoints.beans.web.enabled=true");
contextRunner.run((context) -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace"))
.isFalse();
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mvc, HttpMethod.GET, "autoconfig")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "beans")).isTrue();
assertThat(isExposed(mvc, HttpMethod.GET, "configprops")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "env")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "health")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "info")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "mappings")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "metrics")).isFalse();
assertThat(isExposed(mvc, HttpMethod.POST, "shutdown")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "threaddump")).isFalse();
assertThat(isExposed(mvc, HttpMethod.GET, "trace")).isFalse();
});
}
private boolean isExposed(MockMvc mockMvc, HttpMethod method, String path)
throws Exception {
path = "/application/" + path;
MvcResult mvcResult = mockMvc.perform(request(method, path)).andReturn();
int status = mvcResult.getResponse().getStatus();
if (status == HttpStatus.SC_OK) {

View File

@@ -254,9 +254,8 @@ public class EndpointEnablementProviderTests {
@Test
public void specificEnabledOverrideHasNoEffectWithUnrelatedTechProperty() {
validate(
getEndpointEnablement("foo", true, EndpointExposure.JMX,
"endpoints.default.enabled=false", "endpoints.default.web.enabled=true"),
validate(getEndpointEnablement("foo", true, EndpointExposure.JMX,
"endpoints.default.enabled=false", "endpoints.default.web.enabled=true"),
false, "found property endpoints.default.enabled");
}
@@ -264,8 +263,8 @@ public class EndpointEnablementProviderTests {
public void specificDisabledWithEndpointPropertyEvenWithEnabledGeneralProperties() {
EndpointEnablement enablement = getEndpointEnablement("foo", true,
EndpointExposure.WEB, "endpoints.default.enabled=true",
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true",
"endpoints.foo.enabled=false");
"endpoints.default.web.enabled=true",
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false");
validate(enablement, false, "found property endpoints.foo.enabled");
}
@@ -273,8 +272,9 @@ public class EndpointEnablementProviderTests {
public void specificDisabledWithTechPropertyEvenWithEnabledGeneralProperties() {
EndpointEnablement enablement = getEndpointEnablement("foo", true,
EndpointExposure.WEB, "endpoints.default.enabled=true",
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true",
"endpoints.foo.enabled=true", "endpoints.foo.web.enabled=false");
"endpoints.default.web.enabled=true",
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=true",
"endpoints.foo.web.enabled=false");
validate(enablement, false, "found property endpoints.foo.web.enabled");
}

View File

@@ -73,9 +73,7 @@ public class WebEndpointManagementContextConfigurationTests {
contextRunner.run((context) -> {
HealthWebEndpointExtension extension = context
.getBean(HealthWebEndpointExtension.class);
@SuppressWarnings("unchecked")
Map<String, Integer> statusMappings = ((HealthStatusHttpMapper) ReflectionTestUtils
.getField(extension, "statusHttpMapper")).getStatusMapping();
Map<String, Integer> statusMappings = getStatusMapping(extension);
assertThat(statusMappings).containsEntry("DOWN", 503);
assertThat(statusMappings).containsEntry("OUT_OF_SERVICE", 503);
assertThat(statusMappings).containsEntry("CUSTOM", 500);
@@ -102,9 +100,7 @@ public class WebEndpointManagementContextConfigurationTests {
contextRunner.run((context) -> {
StatusWebEndpointExtension extension = context
.getBean(StatusWebEndpointExtension.class);
@SuppressWarnings("unchecked")
Map<String, Integer> statusMappings = ((HealthStatusHttpMapper) ReflectionTestUtils
.getField(extension, "statusHttpMapper")).getStatusMapping();
Map<String, Integer> statusMappings = getStatusMapping(extension);
assertThat(statusMappings).containsEntry("DOWN", 503);
assertThat(statusMappings).containsEntry("OUT_OF_SERVICE", 503);
assertThat(statusMappings).containsEntry("CUSTOM", 500);
@@ -161,8 +157,7 @@ public class WebEndpointManagementContextConfigurationTests {
}
private void beanIsAutoConfigured(Class<?> beanType, Class<?>... config) {
contextRunner()
.withPropertyValues("endpoints.default.web.enabled:true")
contextRunner().withPropertyValues("endpoints.default.web.enabled:true")
.withUserConfiguration(config)
.run((context) -> assertThat(context).hasSingleBean(beanType));
}
@@ -178,6 +173,11 @@ public class WebEndpointManagementContextConfigurationTests {
AutoConfigurations.of(WebEndpointManagementContextConfiguration.class));
}
private Map<String, Integer> getStatusMapping(Object extension) {
return ((HealthStatusHttpMapper) ReflectionTestUtils.getField(extension,
"statusHttpMapper")).getStatusMapping();
}
@Configuration
static class HealthEndpointConfiguration {

View File

@@ -63,28 +63,30 @@ public class JolokiaManagementContextConfigurationTests {
@Test
public void customPath() {
this.contextRunner.withPropertyValues("management.jolokia.enabled=true",
"management.jolokia.path=/lokia").run(
isDefinedOnPath("/application/lokia/*"));
this.contextRunner
.withPropertyValues("management.jolokia.enabled=true",
"management.jolokia.path=/lokia")
.run(isDefinedOnPath("/application/lokia/*"));
}
@Test
public void customManagementPath() {
this.contextRunner.withPropertyValues("management.jolokia.enabled=true",
"management.context-path=/admin").run(
isDefinedOnPath("/admin/jolokia/*"));
this.contextRunner
.withPropertyValues("management.jolokia.enabled=true",
"management.context-path=/admin")
.run(isDefinedOnPath("/admin/jolokia/*"));
}
@Test
public void customInitParameters() {
this.contextRunner.withPropertyValues("management.jolokia.enabled=true",
"management.jolokia.config.debug=true").run((context) -> {
assertThat(context).hasSingleBean(ServletRegistrationBean.class);
ServletRegistrationBean<?> registrationBean = context
.getBean(ServletRegistrationBean.class);
assertThat(registrationBean.getInitParameters())
.containsOnly(entry("debug", "true"));
});
assertThat(context).hasSingleBean(ServletRegistrationBean.class);
ServletRegistrationBean<?> registrationBean = context
.getBean(ServletRegistrationBean.class);
assertThat(registrationBean.getInitParameters())
.containsOnly(entry("debug", "true"));
});
}
private ContextConsumer<AssertableWebApplicationContext> isDefinedOnPath(

View File

@@ -385,8 +385,10 @@ public class MetricFilterAutoConfigurationTests {
public void doesNotRecordRolledUpMetricsIfConfigured() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class, MetricFilterAutoConfiguration.class);
TestPropertyValues.of("management.metrics.filter.gauge-submissions=",
"management.metrics.filter.counter-submissions=").applyTo(context);
TestPropertyValues
.of("management.metrics.filter.gauge-submissions=",
"management.metrics.filter.counter-submissions=")
.applyTo(context);
context.refresh();
Filter filter = context.getBean(Filter.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/test/path");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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,11 +39,10 @@ final class AuthorizationExceptionMatcher {
public boolean matches(Object object) {
return ((object instanceof CloudFoundryAuthorizationException)
&& ((CloudFoundryAuthorizationException) object)
.getReason() == reason);
.getReason() == reason);
}
};
}
}

View File

@@ -59,8 +59,7 @@ public class CloudFoundryActuatorAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class,
JacksonAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
@@ -80,7 +79,8 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test
public void cloudFoundryPlatformActive() throws Exception {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping();
assertThat(handlerMapping.getEndpointPath()).isEqualTo("/cloudfoundryapplication");
assertThat(handlerMapping.getEndpointPath())
.isEqualTo("/cloudfoundryapplication");
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
.getField(handlerMapping, "corsConfiguration");
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
@@ -136,9 +136,9 @@ public class CloudFoundryActuatorAutoConfigurationTests {
.of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.applyTo(this.context);
this.context.refresh();
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = this.context.getBean(
"cloudFoundryWebEndpointServletHandlerMapping",
CloudFoundryWebEndpointServletHandlerMapping.class);
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = this.context
.getBean("cloudFoundryWebEndpointServletHandlerMapping",
CloudFoundryWebEndpointServletHandlerMapping.class);
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
@@ -152,7 +152,8 @@ public class CloudFoundryActuatorAutoConfigurationTests {
.of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.applyTo(this.context);
this.context.refresh();
FilterChainProxy securityFilterChain = (FilterChainProxy) this.context.getBean("springSecurityFilterChain");
FilterChainProxy securityFilterChain = (FilterChainProxy) this.context
.getBean("springSecurityFilterChain");
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/cloudfoundryapplication/my-path");
@@ -165,8 +166,9 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test
public void cloudFoundryPlatformInactive() throws Exception {
this.context.refresh();
assertThat(this.context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
.isFalse();
assertThat(
this.context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
.isFalse();
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -23,8 +23,6 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.junit.Test;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.springframework.boot.endpoint.CachingConfiguration;
import org.springframework.boot.endpoint.ConversionServiceOperationParameterMapper;
@@ -52,39 +50,40 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock;
/**
* Integration tests for web endpoints exposed using Spring MVC
* on CloudFoundry.
* Integration tests for web endpoints exposed using Spring MVC on CloudFoundry.
*
* @author Madhura Bhave
*/
public class CloudFoundryMvcWebEndpointIntegrationTests {
private static TokenValidator tokenValidator = Mockito.mock(TokenValidator.class);
private static TokenValidator tokenValidator = mock(TokenValidator.class);
private static CloudFoundrySecurityService securityService = Mockito.mock(CloudFoundrySecurityService.class);
private static CloudFoundrySecurityService securityService = mock(
CloudFoundrySecurityService.class);
@Test
public void operationWithSecurityInterceptorForbidden() throws Exception {
BDDMockito.doNothing().when(tokenValidator).validate(any());
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);
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN);
});
}
@Test
public void operationWithSecurityInterceptorSuccess() throws Exception {
BDDMockito.doNothing().when(tokenValidator).validate(any());
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);
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isEqualTo(HttpStatus.OK);
});
}
@@ -103,14 +102,14 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Test
public void linksToOtherEndpointsWithFullAccess() {
BDDMockito.doNothing().when(tokenValidator).validate(any());
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").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken())
.exchange().expectStatus().isOk().expectBody()
.jsonPath("_links.length()").isEqualTo(5)
.jsonPath("_links.self.href").isNotEmpty()
(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)
@@ -124,33 +123,35 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Test
public void linksToOtherEndpointsForbidden() {
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.INVALID_TOKEN, "invalid-token");
BDDMockito.doThrow(exception).when(tokenValidator).validate(any());
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(
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() {
BDDMockito.doNothing().when(tokenValidator).validate(any());
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()
(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());
.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);
}
@@ -159,14 +160,13 @@ 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();
@@ -185,17 +185,20 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Bean
public CloudFoundrySecurityInterceptor interceptor() {
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService,
"app-id");
}
@Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
WebAnnotationEndpointDiscoverer webEndpointDiscoverer, CloudFoundrySecurityInterceptor interceptor) {
WebAnnotationEndpointDiscoverer webEndpointDiscoverer,
CloudFoundrySecurityInterceptor interceptor) {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(Arrays.asList("http://example.com"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
return new CloudFoundryWebEndpointServletHandlerMapping("/cfApplication",
webEndpointDiscoverer.discoverEndpoints(), corsConfiguration, interceptor);
webEndpointDiscoverer.discoverEndpoints(), corsConfiguration,
interceptor);
}
@Bean
@@ -302,4 +305,3 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@@ -19,7 +19,6 @@ package org.springframework.boot.actuate.cloudfoundry;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.BDDMockito;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -30,6 +29,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.util.Base64Utils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
/**
@@ -62,13 +62,15 @@ public class CloudFoundrySecurityInterceptorTests {
this.request.setMethod("OPTIONS");
this.request.addHeader(HttpHeaders.ORIGIN, "http://example.com");
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
}
@Test
public void preHandleWhenTokenIsMissingShouldReturnFalse() throws Exception {
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
}
@@ -76,7 +78,8 @@ public class CloudFoundrySecurityInterceptorTests {
@Test
public void preHandleWhenTokenIsNotBearerShouldReturnFalse() throws Exception {
this.request.addHeader("Authorization", mockAccessToken());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
}
@@ -86,7 +89,8 @@ public class CloudFoundrySecurityInterceptorTests {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
this.securityService, null);
this.request.addHeader("Authorization", "bearer " + mockAccessToken());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus())
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
}
@@ -97,7 +101,8 @@ public class CloudFoundrySecurityInterceptorTests {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
"my-app-id");
this.request.addHeader("Authorization", "bearer " + mockAccessToken());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus())
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
}
@@ -106,20 +111,21 @@ public class CloudFoundrySecurityInterceptorTests {
public void preHandleWhenAccessIsNotAllowedShouldReturnFalse() throws Exception {
String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "bearer " + accessToken);
BDDMockito.given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.RESTRICTED);
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
assertThat(response.getStatus())
.isEqualTo(Reason.ACCESS_DENIED.getStatus());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus());
}
@Test
public void preHandleSuccessfulWithFullAccess() throws Exception {
String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "Bearer " + accessToken);
BDDMockito.given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.FULL);
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
Token token = tokenArgumentCaptor.getValue();
@@ -133,9 +139,10 @@ public class CloudFoundrySecurityInterceptorTests {
public void preHandleSuccessfulWithRestrictedAccess() throws Exception {
String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "Bearer " + accessToken);
BDDMockito.given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.RESTRICTED);
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "info");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "info");
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
Token token = tokenArgumentCaptor.getValue();

View File

@@ -137,4 +137,3 @@ public class TokenTests {
}
}

View File

@@ -266,4 +266,3 @@ public class TokenValidatorTests {
}
}

View File

@@ -46,8 +46,8 @@ public class HealthEndpointTests {
.withDetail("first", "1").build());
healthIndicators.put("upAgain", () -> new Health.Builder().status(Status.UP)
.withDetail("second", "2").build());
HealthEndpoint endpoint = new HealthEndpoint(createHealthIndicator(
healthIndicators));
HealthEndpoint endpoint = new HealthEndpoint(
createHealthIndicator(healthIndicators));
Health health = endpoint.health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).containsOnlyKeys("up", "upAgain");
@@ -59,8 +59,8 @@ public class HealthEndpointTests {
private HealthIndicator createHealthIndicator(
Map<String, HealthIndicator> healthIndicators) {
return new HealthIndicatorFactory().createHealthIndicator(
new OrderedHealthAggregator(), healthIndicators);
return new HealthIndicatorFactory()
.createHealthIndicator(new OrderedHealthAggregator(), healthIndicators);
}
}

View File

@@ -43,8 +43,8 @@ public class StatusEndpointTests {
.withDetail("first", "1").build());
healthIndicators.put("upAgain", () -> new Health.Builder().status(Status.UP)
.withDetail("second", "2").build());
StatusEndpoint endpoint = new StatusEndpoint(createHealthIndicator(
healthIndicators));
StatusEndpoint endpoint = new StatusEndpoint(
createHealthIndicator(healthIndicators));
Health health = endpoint.health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).isEmpty();
@@ -52,8 +52,8 @@ public class StatusEndpointTests {
private HealthIndicator createHealthIndicator(
Map<String, HealthIndicator> healthIndicators) {
return new HealthIndicatorFactory().createHealthIndicator(
new OrderedHealthAggregator(), healthIndicators);
return new HealthIndicatorFactory()
.createHealthIndicator(new OrderedHealthAggregator(), healthIndicators);
}
}

View File

@@ -65,8 +65,7 @@ public class MvcEndpointCorsIntegrationTests {
EndpointInfrastructureAutoConfiguration.class,
EndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ServletEndpointAutoConfiguration.class);
TestPropertyValues.of("endpoints.default.web.enabled:true")
.applyTo(this.context);
TestPropertyValues.of("endpoints.default.web.enabled:true").applyTo(this.context);
}
@Test
@@ -144,8 +143,10 @@ public class MvcEndpointCorsIntegrationTests {
@Test
public void allowedMethodsCanBeConfigured() throws Exception {
TestPropertyValues.of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allowed-methods:GET,HEAD").applyTo(this.context);
TestPropertyValues
.of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allowed-methods:GET,HEAD")
.applyTo(this.context);
createMockMvc()
.perform(options("/application/beans")
.header(HttpHeaders.ORIGIN, "foo.example.com")
@@ -156,16 +157,20 @@ public class MvcEndpointCorsIntegrationTests {
@Test
public void credentialsCanBeAllowed() throws Exception {
TestPropertyValues.of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allow-credentials:true").applyTo(this.context);
TestPropertyValues
.of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.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.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allow-credentials:false").applyTo(this.context);
TestPropertyValues
.of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allow-credentials:false")
.applyTo(this.context);
performAcceptedCorsRequest().andExpect(
header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
}

View File

@@ -69,8 +69,8 @@ public class MvcEndpointIntegrationTests {
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/application/beans")
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized());
mockMvc.perform(get("/application/beans").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
@Test
@@ -80,8 +80,8 @@ public class MvcEndpointIntegrationTests {
TestPropertyValues.of("management.context-path:/management")
.applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/beans")
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized());
mockMvc.perform(get("/management/beans").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
@Test
@@ -92,8 +92,7 @@ public class MvcEndpointIntegrationTests {
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class);
TestPropertyValues.of("management.context-path:/management",
"endpoints.default.web.enabled=true")
.applyTo(this.context);
"endpoints.default.web.enabled=true").applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/beans")).andExpect(status().isOk());
}
@@ -137,7 +136,7 @@ public class MvcEndpointIntegrationTests {
}
@Import(DefaultConfiguration.class)
@ImportAutoConfiguration({ SecurityAutoConfiguration.class})
@ImportAutoConfiguration({ SecurityAutoConfiguration.class })
static class SecureConfiguration {
}

View File

@@ -57,8 +57,8 @@ public class StatusEndpointWebIntegrationTests {
context.getBean("alphaHealthIndicator", TestHealthIndicator.class)
.setHealth(Health.down().build());
client.get().uri("/application/status").exchange().expectStatus()
.isEqualTo(HttpStatus.SERVICE_UNAVAILABLE)
.expectBody().json("{\"status\":\"DOWN\"}");
.isEqualTo(HttpStatus.SERVICE_UNAVAILABLE).expectBody()
.json("{\"status\":\"DOWN\"}");
}
@Configuration

View File

@@ -78,9 +78,8 @@ import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
* The {@link PropertySource PropertySources} that belong to the application context's
* {@link org.springframework.core.env.Environment} are reset at the end of every test.
* This means that {@link TestPropertyValues} can be used in a test without affecting the
* {@code Environment} of other tests in the same class.
* The runner always sets the flag `endpoints.default.web.enabled` to true so that web
* endpoints are enabled.
* {@code Environment} of other tests in the same class. The runner always sets the flag
* `endpoints.default.web.enabled` to true so that web endpoints are enabled.
*
* @author Andy Wilkinson
*/
@@ -266,7 +265,8 @@ public class WebEndpointsRunner extends Suite {
private ReactiveWebEndpointsRunner(Class<?> klass) throws InitializationError {
super(klass, "Reactive", (classes) -> {
ReactiveWebServerApplicationContext context = new ReactiveWebServerApplicationContext();
TestPropertyValues.of("endpoints.default.web.enabled:true").applyTo(context);
TestPropertyValues.of("endpoints.default.web.enabled:true")
.applyTo(context);
classes.add(ReactiveInfrastructureConfiguration.class);
context.register(classes.toArray(new Class<?>[classes.size()]));
context.refresh();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.

View File

@@ -62,8 +62,8 @@ public class HealthIndicatorFactoryTests {
private HealthIndicator createHealthIndicator(
Map<String, HealthIndicator> healthIndicators) {
return new HealthIndicatorFactory().createHealthIndicator(
new OrderedHealthAggregator(), healthIndicators);
return new HealthIndicatorFactory()
.createHealthIndicator(new OrderedHealthAggregator(), healthIndicators);
}
}

View File

@@ -51,12 +51,14 @@ public class RedisHealthIndicatorTests {
@Test
public void indicatorExists() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(
RedisAutoConfiguration.class, EndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class)).run((context) -> {
assertThat(context).hasSingleBean(RedisConnectionFactory.class);
assertThat(context).hasSingleBean(RedisHealthIndicator.class);
});
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
EndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class))
.run((context) -> {
assertThat(context).hasSingleBean(RedisConnectionFactory.class);
assertThat(context).hasSingleBean(RedisHealthIndicator.class);
});
}
@Test
@@ -74,8 +76,8 @@ public class RedisHealthIndicatorTests {
@Test
public void redisIsDown() throws Exception {
RedisConnection redisConnection = mock(RedisConnection.class);
given(redisConnection.info()).willThrow(
new RedisConnectionFailureException("Connection failed"));
given(redisConnection.info())
.willThrow(new RedisConnectionFailureException("Connection failed"));
RedisHealthIndicator healthIndicator = createHealthIndicator(redisConnection);
Health health = healthIndicator.health();
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
@@ -83,9 +85,9 @@ public class RedisHealthIndicatorTests {
.contains("Connection failed");
}
private RedisHealthIndicator createHealthIndicator(
RedisConnection redisConnection) {
RedisConnectionFactory redisConnectionFactory = mock(RedisConnectionFactory.class);
private RedisHealthIndicator createHealthIndicator(RedisConnection redisConnection) {
RedisConnectionFactory redisConnectionFactory = mock(
RedisConnectionFactory.class);
given(redisConnectionFactory.getConnection()).willReturn(redisConnection);
return new RedisHealthIndicator(redisConnectionFactory);
}