Change HealthEndpointGroups customization support
Update the `HealthEndpointGroups` customization support to use a post-processor rather than a mutable registry. Although this approach is slightly less flexible, it removes a lot of complexity from the `HealthEndpointGroups` code. Specifically, it allows us to drop the `HealthEndpointGroupsRegistry` interface entirely. The probe health groups are now added via the post-processor if they aren't already defined. Unlike the previous implementation, users are no longer able to customize status aggregation and http status code mapping rules _unless_ they also re-define the health indicators that are members of the group. See gh-20962
This commit is contained in:
parent
f32a37e289
commit
5311c04437
|
@ -20,7 +20,6 @@ import org.springframework.boot.actuate.autoconfigure.availability.AvailabilityP
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
||||||
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
||||||
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistryCustomizer;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration;
|
import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration;
|
||||||
|
@ -38,11 +37,10 @@ import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for
|
* {@link EnableAutoConfiguration Auto-configuration} for availability probes.
|
||||||
* {@link LivenessStateHealthIndicator}, {@link ReadinessStateHealthIndicator} and
|
|
||||||
* {@link HealthEndpointGroupsRegistryCustomizer}.
|
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
|
* @author Phillip Webb
|
||||||
* @since 2.3.0
|
* @since 2.3.0
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ -66,8 +64,8 @@ public class AvailabilityProbesAutoConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public HealthEndpointGroupsRegistryCustomizer probesRegistryCustomizer() {
|
public AvailabilityProbesHealthEndpointGroupsPostProcessor availabilityProbesHealthEndpointGroupsPostProcessor() {
|
||||||
return new AvailabilityProbesHealthEndpointGroupsRegistrar();
|
return new AvailabilityProbesHealthEndpointGroupsPostProcessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,15 +73,17 @@ public class AvailabilityProbesAutoConfiguration {
|
||||||
*/
|
*/
|
||||||
static class ProbesCondition extends SpringBootCondition {
|
static class ProbesCondition extends SpringBootCondition {
|
||||||
|
|
||||||
|
private static final String ENABLED_PROPERTY = "management.health.probes.enabled";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||||
Environment environment = context.getEnvironment();
|
Environment environment = context.getEnvironment();
|
||||||
ConditionMessage.Builder message = ConditionMessage.forCondition("Health probes");
|
ConditionMessage.Builder message = ConditionMessage.forCondition("Health availability");
|
||||||
String enabled = environment.getProperty("management.health.probes.enabled");
|
String enabled = environment.getProperty(ENABLED_PROPERTY);
|
||||||
if (enabled != null) {
|
if (enabled != null) {
|
||||||
boolean match = !"false".equalsIgnoreCase(enabled);
|
boolean match = !"false".equalsIgnoreCase(enabled);
|
||||||
return new ConditionOutcome(match,
|
return new ConditionOutcome(match,
|
||||||
message.because("'management.health.probes.enabled' set to '" + enabled + "'"));
|
message.because("'" + ENABLED_PROPERTY + "' set to '" + enabled + "'"));
|
||||||
}
|
}
|
||||||
if (CloudPlatform.getActive(environment) == CloudPlatform.KUBERNETES) {
|
if (CloudPlatform.getActive(environment) == CloudPlatform.KUBERNETES) {
|
||||||
return ConditionOutcome.match(message.because("running on Kubernetes"));
|
return ConditionOutcome.match(message.because("running on Kubernetes"));
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.endpoint.SecurityContext;
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
||||||
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
|
import org.springframework.boot.actuate.health.StatusAggregator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link HealthEndpointGroup} used to support availability probes.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class AvailabilityProbesHealthEndpointGroup implements HealthEndpointGroup {
|
||||||
|
|
||||||
|
private final Set<String> members;
|
||||||
|
|
||||||
|
AvailabilityProbesHealthEndpointGroup(String... members) {
|
||||||
|
this.members = new HashSet<>(Arrays.asList(members));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMember(String name) {
|
||||||
|
return this.members.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showComponents(SecurityContext securityContext) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showDetails(SecurityContext securityContext) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StatusAggregator getStatusAggregator() {
|
||||||
|
return StatusAggregator.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpCodeStatusMapper getHttpCodeStatusMapper() {
|
||||||
|
return HttpCodeStatusMapper.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link HealthEndpointGroups} decorator to support availability probes.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Brian Clozel
|
||||||
|
*/
|
||||||
|
class AvailabilityProbesHealthEndpointGroups implements HealthEndpointGroups {
|
||||||
|
|
||||||
|
private static final Map<String, AvailabilityProbesHealthEndpointGroup> GROUPS;
|
||||||
|
static {
|
||||||
|
Map<String, AvailabilityProbesHealthEndpointGroup> groups = new LinkedHashMap<>();
|
||||||
|
groups.put("liveness", new AvailabilityProbesHealthEndpointGroup("livenessState"));
|
||||||
|
groups.put("readiness", new AvailabilityProbesHealthEndpointGroup("readinessState"));
|
||||||
|
GROUPS = Collections.unmodifiableMap(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final HealthEndpointGroups groups;
|
||||||
|
|
||||||
|
private final Set<String> names;
|
||||||
|
|
||||||
|
AvailabilityProbesHealthEndpointGroups(HealthEndpointGroups groups) {
|
||||||
|
Assert.notNull(groups, "Groups must not be null");
|
||||||
|
this.groups = groups;
|
||||||
|
Set<String> names = new LinkedHashSet<>(groups.getNames());
|
||||||
|
names.addAll(GROUPS.keySet());
|
||||||
|
this.names = Collections.unmodifiableSet(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HealthEndpointGroup getPrimary() {
|
||||||
|
return this.groups.getPrimary();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getNames() {
|
||||||
|
return this.names;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HealthEndpointGroup get(String name) {
|
||||||
|
HealthEndpointGroup group = this.groups.get(name);
|
||||||
|
if (group == null) {
|
||||||
|
group = GROUPS.get(name);
|
||||||
|
}
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean containsAllProbeGroups(HealthEndpointGroups groups) {
|
||||||
|
return groups.getNames().containsAll(GROUPS.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroupsPostProcessor;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link HealthEndpointGroupsPostProcessor} to add
|
||||||
|
* {@link AvailabilityProbesHealthEndpointGroups}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
|
class AvailabilityProbesHealthEndpointGroupsPostProcessor implements HealthEndpointGroupsPostProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HealthEndpointGroups postProcessHealthEndpointGroups(HealthEndpointGroups groups) {
|
||||||
|
if (AvailabilityProbesHealthEndpointGroups.containsAllProbeGroups(groups)) {
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
return new AvailabilityProbesHealthEndpointGroups(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.availability;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistry;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistryCustomizer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link HealthEndpointGroupsRegistryCustomizer} that registers {@code "liveness"} and
|
|
||||||
* {@code "readiness"} {@link HealthEndpointGroup groups} if they don't exist already.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.3.0
|
|
||||||
*/
|
|
||||||
public class AvailabilityProbesHealthEndpointGroupsRegistrar implements HealthEndpointGroupsRegistryCustomizer {
|
|
||||||
|
|
||||||
private static final String LIVENESS_GROUP_NAME = "liveness";
|
|
||||||
|
|
||||||
private static final String READINESS_GROUP_NAME = "readiness";
|
|
||||||
|
|
||||||
private static final String LIVENESS_PROBE_INDICATOR = "livenessProbe";
|
|
||||||
|
|
||||||
private static final String READINESS_PROBE_INDICATOR = "readinessProbe";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void customize(HealthEndpointGroupsRegistry registry) {
|
|
||||||
if (registry.get(LIVENESS_GROUP_NAME) == null) {
|
|
||||||
registry.add(LIVENESS_GROUP_NAME, (configurer) -> configurer.include(LIVENESS_PROBE_INDICATOR));
|
|
||||||
}
|
|
||||||
if (registry.get(READINESS_GROUP_NAME) == null) {
|
|
||||||
registry.add(READINESS_GROUP_NAME, (configurer) -> configurer.include(READINESS_PROBE_INDICATOR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ import java.security.Principal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Show;
|
||||||
import org.springframework.boot.actuate.endpoint.SecurityContext;
|
import org.springframework.boot.actuate.endpoint.SecurityContext;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
||||||
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
|
@ -30,12 +31,12 @@ import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-configured {@link HealthEndpointGroup}.
|
* Auto-configured {@link HealthEndpointGroup} backed by {@link HealthProperties}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
class DefaultHealthEndpointGroup implements HealthEndpointGroup {
|
class AutoConfiguredHealthEndpointGroup implements HealthEndpointGroup {
|
||||||
|
|
||||||
private final Predicate<String> members;
|
private final Predicate<String> members;
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ class DefaultHealthEndpointGroup implements HealthEndpointGroup {
|
||||||
private final Collection<String> roles;
|
private final Collection<String> roles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link DefaultHealthEndpointGroup} instance.
|
* Create a new {@link AutoConfiguredHealthEndpointGroup} instance.
|
||||||
* @param members a predicate used to test for group membership
|
* @param members a predicate used to test for group membership
|
||||||
* @param statusAggregator the status aggregator to use
|
* @param statusAggregator the status aggregator to use
|
||||||
* @param httpCodeStatusMapper the HTTP code status mapper to use
|
* @param httpCodeStatusMapper the HTTP code status mapper to use
|
||||||
|
@ -58,7 +59,7 @@ class DefaultHealthEndpointGroup implements HealthEndpointGroup {
|
||||||
* @param showDetails the show details setting
|
* @param showDetails the show details setting
|
||||||
* @param roles the roles to match
|
* @param roles the roles to match
|
||||||
*/
|
*/
|
||||||
DefaultHealthEndpointGroup(Predicate<String> members, StatusAggregator statusAggregator,
|
AutoConfiguredHealthEndpointGroup(Predicate<String> members, StatusAggregator statusAggregator,
|
||||||
HttpCodeStatusMapper httpCodeStatusMapper, Show showComponents, Show showDetails,
|
HttpCodeStatusMapper httpCodeStatusMapper, Show showComponents, Show showDetails,
|
||||||
Collection<String> roles) {
|
Collection<String> roles) {
|
||||||
this.members = members;
|
this.members = members;
|
|
@ -22,7 +22,6 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -32,12 +31,10 @@ import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties.Group;
|
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties.Group;
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Show;
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Status;
|
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Status;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup.Show;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupConfigurer;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistry;
|
|
||||||
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
import org.springframework.boot.actuate.health.SimpleHttpCodeStatusMapper;
|
import org.springframework.boot.actuate.health.SimpleHttpCodeStatusMapper;
|
||||||
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
|
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
|
||||||
|
@ -48,113 +45,71 @@ import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-configured {@link HealthEndpointGroupsRegistry}.
|
* Auto-configured {@link HealthEndpointGroups}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
*/
|
||||||
class AutoConfiguredHealthEndpointGroupsRegistry implements HealthEndpointGroupsRegistry {
|
class AutoConfiguredHealthEndpointGroups implements HealthEndpointGroups {
|
||||||
|
|
||||||
private static Predicate<String> ALL = (name) -> true;
|
private static Predicate<String> ALL = (name) -> true;
|
||||||
|
|
||||||
private final StatusAggregator defaultStatusAggregator;
|
private final HealthEndpointGroup primaryGroup;
|
||||||
|
|
||||||
private final HttpCodeStatusMapper defaultHttpCodeStatusMapper;
|
|
||||||
|
|
||||||
private final Show defaultShowComponents;
|
|
||||||
|
|
||||||
private final Show defaultShowDetails;
|
|
||||||
|
|
||||||
private final Set<String> defaultRoles;
|
|
||||||
|
|
||||||
private HealthEndpointGroup primaryGroup;
|
|
||||||
|
|
||||||
private final Map<String, HealthEndpointGroup> groups;
|
private final Map<String, HealthEndpointGroup> groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link AutoConfiguredHealthEndpointGroupsRegistry} instance.
|
* Create a new {@link AutoConfiguredHealthEndpointGroups} instance.
|
||||||
* @param applicationContext the application context used to check for override beans
|
* @param applicationContext the application context used to check for override beans
|
||||||
* @param properties the health endpoint properties
|
* @param properties the health endpoint properties
|
||||||
*/
|
*/
|
||||||
AutoConfiguredHealthEndpointGroupsRegistry(ApplicationContext applicationContext,
|
AutoConfiguredHealthEndpointGroups(ApplicationContext applicationContext, HealthEndpointProperties properties) {
|
||||||
HealthEndpointProperties properties) {
|
|
||||||
ListableBeanFactory beanFactory = (applicationContext instanceof ConfigurableApplicationContext)
|
ListableBeanFactory beanFactory = (applicationContext instanceof ConfigurableApplicationContext)
|
||||||
? ((ConfigurableApplicationContext) applicationContext).getBeanFactory() : applicationContext;
|
? ((ConfigurableApplicationContext) applicationContext).getBeanFactory() : applicationContext;
|
||||||
this.defaultShowComponents = convertVisibility(properties.getShowComponents());
|
Show showComponents = properties.getShowComponents();
|
||||||
this.defaultShowDetails = convertVisibility(properties.getShowDetails());
|
Show showDetails = properties.getShowDetails();
|
||||||
this.defaultRoles = properties.getRoles();
|
Set<String> roles = properties.getRoles();
|
||||||
|
|
||||||
StatusAggregator statusAggregator = getNonQualifiedBean(beanFactory, StatusAggregator.class);
|
StatusAggregator statusAggregator = getNonQualifiedBean(beanFactory, StatusAggregator.class);
|
||||||
if (statusAggregator == null) {
|
if (statusAggregator == null) {
|
||||||
statusAggregator = new SimpleStatusAggregator(properties.getStatus().getOrder());
|
statusAggregator = new SimpleStatusAggregator(properties.getStatus().getOrder());
|
||||||
}
|
}
|
||||||
this.defaultStatusAggregator = statusAggregator;
|
|
||||||
|
|
||||||
HttpCodeStatusMapper httpCodeStatusMapper = getNonQualifiedBean(beanFactory, HttpCodeStatusMapper.class);
|
HttpCodeStatusMapper httpCodeStatusMapper = getNonQualifiedBean(beanFactory, HttpCodeStatusMapper.class);
|
||||||
if (httpCodeStatusMapper == null) {
|
if (httpCodeStatusMapper == null) {
|
||||||
httpCodeStatusMapper = new SimpleHttpCodeStatusMapper(properties.getStatus().getHttpMapping());
|
httpCodeStatusMapper = new SimpleHttpCodeStatusMapper(properties.getStatus().getHttpMapping());
|
||||||
}
|
}
|
||||||
this.defaultHttpCodeStatusMapper = httpCodeStatusMapper;
|
this.primaryGroup = new AutoConfiguredHealthEndpointGroup(ALL, statusAggregator, httpCodeStatusMapper,
|
||||||
|
showComponents, showDetails, roles);
|
||||||
this.primaryGroup = new DefaultHealthEndpointGroup(ALL, statusAggregator, httpCodeStatusMapper,
|
this.groups = createGroups(properties.getGroup(), beanFactory, statusAggregator, httpCodeStatusMapper,
|
||||||
this.defaultShowComponents, this.defaultShowDetails, this.defaultRoles);
|
showComponents, showDetails, roles);
|
||||||
|
|
||||||
this.groups = createGroups(properties.getGroup(), beanFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Map<String, HealthEndpointGroup> createGroups(Map<String, Group> groupProperties, BeanFactory beanFactory,
|
||||||
public HealthEndpointGroupsRegistry add(String groupName, Consumer<HealthEndpointGroupConfigurer> consumer) {
|
StatusAggregator defaultStatusAggregator, HttpCodeStatusMapper defaultHttpCodeStatusMapper,
|
||||||
DefaultHealthEndpointGroupConfigurer groupConfigurer = new DefaultHealthEndpointGroupConfigurer(
|
Show defaultShowComponents, Show defaultShowDetails, Set<String> defaultRoles) {
|
||||||
this.defaultStatusAggregator, this.defaultHttpCodeStatusMapper, this.defaultShowComponents,
|
|
||||||
this.defaultShowDetails, this.defaultRoles);
|
|
||||||
consumer.accept(groupConfigurer);
|
|
||||||
this.groups.put(groupName, groupConfigurer.toHealthEndpointGroup());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupsRegistry remove(String groupName) {
|
|
||||||
this.groups.remove(groupName);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroups toGroups() {
|
|
||||||
return HealthEndpointGroups.of(this.primaryGroup, Collections.unmodifiableMap(this.groups));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, HealthEndpointGroup> createGroups(Map<String, Group> groupProperties, BeanFactory beanFactory) {
|
|
||||||
Map<String, HealthEndpointGroup> groups = new LinkedHashMap<>();
|
Map<String, HealthEndpointGroup> groups = new LinkedHashMap<>();
|
||||||
groupProperties
|
groupProperties.forEach((groupName, group) -> {
|
||||||
.forEach((groupName, group) -> groups.put(groupName, createGroup(groupName, group, beanFactory)));
|
Status status = group.getStatus();
|
||||||
return groups;
|
Show showComponents = (group.getShowComponents() != null) ? group.getShowComponents()
|
||||||
}
|
: defaultShowComponents;
|
||||||
|
Show showDetails = (group.getShowDetails() != null) ? group.getShowDetails() : defaultShowDetails;
|
||||||
private HealthEndpointGroup createGroup(String groupName, Group groupProperties, BeanFactory beanFactory) {
|
Set<String> roles = !CollectionUtils.isEmpty(group.getRoles()) ? group.getRoles() : defaultRoles;
|
||||||
Status status = groupProperties.getStatus();
|
|
||||||
Show showComponents = (groupProperties.getShowComponents() != null)
|
|
||||||
? convertVisibility(groupProperties.getShowComponents()) : this.defaultShowComponents;
|
|
||||||
Show showDetails = (groupProperties.getShowDetails() != null)
|
|
||||||
? convertVisibility(groupProperties.getShowDetails()) : this.defaultShowDetails;
|
|
||||||
Set<String> roles = !CollectionUtils.isEmpty(groupProperties.getRoles()) ? groupProperties.getRoles()
|
|
||||||
: this.defaultRoles;
|
|
||||||
StatusAggregator statusAggregator = getQualifiedBean(beanFactory, StatusAggregator.class, groupName, () -> {
|
StatusAggregator statusAggregator = getQualifiedBean(beanFactory, StatusAggregator.class, groupName, () -> {
|
||||||
if (!CollectionUtils.isEmpty(status.getOrder())) {
|
if (!CollectionUtils.isEmpty(status.getOrder())) {
|
||||||
return new SimpleStatusAggregator(status.getOrder());
|
return new SimpleStatusAggregator(status.getOrder());
|
||||||
}
|
}
|
||||||
return this.defaultStatusAggregator;
|
return defaultStatusAggregator;
|
||||||
});
|
});
|
||||||
HttpCodeStatusMapper httpCodeStatusMapper = getQualifiedBean(beanFactory, HttpCodeStatusMapper.class, groupName,
|
HttpCodeStatusMapper httpCodeStatusMapper = getQualifiedBean(beanFactory, HttpCodeStatusMapper.class,
|
||||||
() -> {
|
groupName, () -> {
|
||||||
if (!CollectionUtils.isEmpty(status.getHttpMapping())) {
|
if (!CollectionUtils.isEmpty(status.getHttpMapping())) {
|
||||||
return new SimpleHttpCodeStatusMapper(status.getHttpMapping());
|
return new SimpleHttpCodeStatusMapper(status.getHttpMapping());
|
||||||
}
|
}
|
||||||
return this.defaultHttpCodeStatusMapper;
|
return defaultHttpCodeStatusMapper;
|
||||||
});
|
});
|
||||||
Predicate<String> members = new IncludeExcludeGroupMemberPredicate(groupProperties.getInclude(),
|
Predicate<String> members = new IncludeExcludeGroupMemberPredicate(group.getInclude(), group.getExclude());
|
||||||
groupProperties.getExclude());
|
groups.put(groupName, new AutoConfiguredHealthEndpointGroup(members, statusAggregator, httpCodeStatusMapper,
|
||||||
return new DefaultHealthEndpointGroup(members, statusAggregator, httpCodeStatusMapper, showComponents,
|
showComponents, showDetails, roles));
|
||||||
showDetails, roles);
|
});
|
||||||
|
return Collections.unmodifiableMap(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getNonQualifiedBean(ListableBeanFactory beanFactory, Class<T> type) {
|
private <T> T getNonQualifiedBean(ListableBeanFactory beanFactory, Class<T> type) {
|
||||||
|
@ -185,21 +140,6 @@ class AutoConfiguredHealthEndpointGroupsRegistry implements HealthEndpointGroups
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Show convertVisibility(HealthProperties.Show show) {
|
|
||||||
if (show == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch (show) {
|
|
||||||
case ALWAYS:
|
|
||||||
return Show.ALWAYS;
|
|
||||||
case NEVER:
|
|
||||||
return Show.NEVER;
|
|
||||||
case WHEN_AUTHORIZED:
|
|
||||||
return Show.WHEN_AUTHORIZED;
|
|
||||||
}
|
|
||||||
throw new IllegalStateException("Unsupported 'show' value " + show);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HealthEndpointGroup getPrimary() {
|
public HealthEndpointGroup getPrimary() {
|
||||||
return this.primaryGroup;
|
return this.primaryGroup;
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.health;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup.Show;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupConfigurer;
|
|
||||||
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
|
||||||
import org.springframework.boot.actuate.health.StatusAggregator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mutable {@link HealthEndpointGroupConfigurer configurer} for
|
|
||||||
* {@link HealthEndpointGroup}.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class DefaultHealthEndpointGroupConfigurer implements HealthEndpointGroupConfigurer {
|
|
||||||
|
|
||||||
Set<String> includedIndicators;
|
|
||||||
|
|
||||||
Set<String> excludedIndicators;
|
|
||||||
|
|
||||||
private StatusAggregator statusAggregator;
|
|
||||||
|
|
||||||
private HttpCodeStatusMapper httpCodeStatusMapper;
|
|
||||||
|
|
||||||
private Show showComponents;
|
|
||||||
|
|
||||||
private Show showDetails;
|
|
||||||
|
|
||||||
private Set<String> roles;
|
|
||||||
|
|
||||||
DefaultHealthEndpointGroupConfigurer(StatusAggregator defaultStatusAggregator,
|
|
||||||
HttpCodeStatusMapper defaultHttpCodeStatusMapper, Show defaultShowComponents, Show defaultShowDetails,
|
|
||||||
Set<String> defaultRoles) {
|
|
||||||
this.statusAggregator = defaultStatusAggregator;
|
|
||||||
this.httpCodeStatusMapper = defaultHttpCodeStatusMapper;
|
|
||||||
this.showComponents = defaultShowComponents;
|
|
||||||
this.showDetails = defaultShowDetails;
|
|
||||||
this.roles = new HashSet<>(defaultRoles);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer include(String... indicators) {
|
|
||||||
this.includedIndicators = new HashSet<>(Arrays.asList(indicators));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer exclude(String... exclude) {
|
|
||||||
this.excludedIndicators = new HashSet<>(Arrays.asList(exclude));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer statusAggregator(StatusAggregator statusAggregator) {
|
|
||||||
this.statusAggregator = statusAggregator;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer httpCodeStatusMapper(HttpCodeStatusMapper httpCodeStatusMapper) {
|
|
||||||
this.httpCodeStatusMapper = httpCodeStatusMapper;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer showComponents(Show showComponents) {
|
|
||||||
this.showComponents = showComponents;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer showDetails(Show showDetails) {
|
|
||||||
this.showDetails = showDetails;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer roles(String... roles) {
|
|
||||||
this.roles = new HashSet<>(Arrays.asList(roles));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
HealthEndpointGroup toHealthEndpointGroup() {
|
|
||||||
IncludeExcludeGroupMemberPredicate predicate = new IncludeExcludeGroupMemberPredicate(this.includedIndicators,
|
|
||||||
this.excludedIndicators);
|
|
||||||
return new DefaultHealthEndpointGroup(predicate, this.statusAggregator, this.httpCodeStatusMapper,
|
|
||||||
this.showComponents, this.showDetails, this.roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -21,7 +21,9 @@ import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
import org.springframework.boot.actuate.health.CompositeHealthContributor;
|
import org.springframework.boot.actuate.health.CompositeHealthContributor;
|
||||||
import org.springframework.boot.actuate.health.CompositeReactiveHealthContributor;
|
import org.springframework.boot.actuate.health.CompositeReactiveHealthContributor;
|
||||||
import org.springframework.boot.actuate.health.Health;
|
import org.springframework.boot.actuate.health.Health;
|
||||||
|
@ -29,7 +31,7 @@ import org.springframework.boot.actuate.health.HealthContributor;
|
||||||
import org.springframework.boot.actuate.health.HealthContributorRegistry;
|
import org.springframework.boot.actuate.health.HealthContributorRegistry;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistryCustomizer;
|
import org.springframework.boot.actuate.health.HealthEndpointGroupsPostProcessor;
|
||||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||||
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
import org.springframework.boot.actuate.health.NamedContributor;
|
import org.springframework.boot.actuate.health.NamedContributor;
|
||||||
|
@ -68,11 +70,8 @@ class HealthEndpointConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
HealthEndpointGroups healthEndpointGroups(ApplicationContext applicationContext,
|
HealthEndpointGroups healthEndpointGroups(ApplicationContext applicationContext,
|
||||||
HealthEndpointProperties properties, ObjectProvider<HealthEndpointGroupsRegistryCustomizer> customizers) {
|
HealthEndpointProperties properties) {
|
||||||
AutoConfiguredHealthEndpointGroupsRegistry registry = new AutoConfiguredHealthEndpointGroupsRegistry(
|
return new AutoConfiguredHealthEndpointGroups(applicationContext, properties);
|
||||||
applicationContext, properties);
|
|
||||||
customizers.orderedStream().forEach((customizer) -> customizer.customize(registry));
|
|
||||||
return registry.toGroups();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -93,6 +92,42 @@ class HealthEndpointConfiguration {
|
||||||
return new HealthEndpoint(registry, groups);
|
return new HealthEndpoint(registry, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
static HealthEndpointGroupsBeanPostProcessor healthEndpointGroupsBeanPostProcessor(
|
||||||
|
ObjectProvider<HealthEndpointGroupsPostProcessor> healthEndpointGroupsPostProcessors) {
|
||||||
|
return new HealthEndpointGroupsBeanPostProcessor(healthEndpointGroupsPostProcessors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link BeanPostProcessor} to invoke {@link HealthEndpointGroupsPostProcessor}
|
||||||
|
* beans.
|
||||||
|
*/
|
||||||
|
private static class HealthEndpointGroupsBeanPostProcessor implements BeanPostProcessor {
|
||||||
|
|
||||||
|
private final ObjectProvider<HealthEndpointGroupsPostProcessor> postProcessors;
|
||||||
|
|
||||||
|
HealthEndpointGroupsBeanPostProcessor(ObjectProvider<HealthEndpointGroupsPostProcessor> postProcessors) {
|
||||||
|
this.postProcessors = postProcessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
if (bean instanceof HealthEndpointGroups) {
|
||||||
|
return applyPostProcessors((HealthEndpointGroups) bean);
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object applyPostProcessors(HealthEndpointGroups bean) {
|
||||||
|
for (HealthEndpointGroupsPostProcessor postProcessor : this.postProcessors.orderedStream()
|
||||||
|
.toArray(HealthEndpointGroupsPostProcessor[]::new)) {
|
||||||
|
bean = postProcessor.postProcessHealthEndpointGroups(bean);
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter to expose {@link ReactiveHealthContributor} beans as
|
* Adapter to expose {@link ReactiveHealthContributor} beans as
|
||||||
* {@link HealthContributor} instances.
|
* {@link HealthContributor} instances.
|
||||||
|
|
|
@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
||||||
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistryCustomizer;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration;
|
import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration;
|
||||||
import org.springframework.boot.availability.ApplicationAvailability;
|
import org.springframework.boot.availability.ApplicationAvailability;
|
||||||
|
@ -43,7 +42,7 @@ class AvailabilityProbesAutoConfigurationTests {
|
||||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||||
.doesNotHaveBean(HealthEndpointGroupsRegistryCustomizer.class));
|
.doesNotHaveBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -52,7 +51,7 @@ class AvailabilityProbesAutoConfigurationTests {
|
||||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||||
.hasSingleBean(HealthEndpointGroupsRegistryCustomizer.class));
|
.hasSingleBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -61,7 +60,7 @@ class AvailabilityProbesAutoConfigurationTests {
|
||||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||||
.hasSingleBean(HealthEndpointGroupsRegistryCustomizer.class));
|
.hasSingleBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -71,7 +70,7 @@ class AvailabilityProbesAutoConfigurationTests {
|
||||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||||
.doesNotHaveBean(HealthEndpointGroupsRegistryCustomizer.class));
|
.doesNotHaveBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.endpoint.SecurityContext;
|
||||||
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
|
import org.springframework.boot.actuate.health.StatusAggregator;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AvailabilityProbesHealthEndpointGroup}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class AvailabilityProbesHealthEndpointGroupTests {
|
||||||
|
|
||||||
|
private AvailabilityProbesHealthEndpointGroup group = new AvailabilityProbesHealthEndpointGroup("a", "b");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isMemberWhenMemberReturnsTrue() {
|
||||||
|
assertThat(this.group.isMember("a")).isTrue();
|
||||||
|
assertThat(this.group.isMember("b")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isMemberWhenNotMemberReturnsFalse() {
|
||||||
|
assertThat(this.group.isMember("c")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void showComponentsReturnsFalse() {
|
||||||
|
assertThat(this.group.showComponents(mock(SecurityContext.class))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void showDetailsReturnsFalse() {
|
||||||
|
assertThat(this.group.showDetails(mock(SecurityContext.class))).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getStatusAggregattorReturnsDefaultStatusAggregator() {
|
||||||
|
assertThat(this.group.getStatusAggregator()).isEqualTo(StatusAggregator.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getHttpCodeStatusMapperReturnsDefaultHttpCodeStatusMapper() {
|
||||||
|
assertThat(this.group.getHttpCodeStatusMapper()).isEqualTo(HttpCodeStatusMapper.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AvailabilityProbesHealthEndpointGroupsPostProcessor}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class AvailabilityProbesHealthEndpointGroupsPostProcessorTests {
|
||||||
|
|
||||||
|
private AvailabilityProbesHealthEndpointGroupsPostProcessor postProcessor = new AvailabilityProbesHealthEndpointGroupsPostProcessor();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postProcessHealthEndpointGroupsWhenGroupsAlreadyContainedReturnsOriginal() {
|
||||||
|
HealthEndpointGroups groups = mock(HealthEndpointGroups.class);
|
||||||
|
Set<String> names = new LinkedHashSet<>();
|
||||||
|
names.add("test");
|
||||||
|
names.add("readiness");
|
||||||
|
names.add("liveness");
|
||||||
|
given(groups.getNames()).willReturn(names);
|
||||||
|
assertThat(this.postProcessor.postProcessHealthEndpointGroups(groups)).isSameAs(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postProcessHealthEndpointGroupsWhenGroupContainsOneReturnsPostProcessed() {
|
||||||
|
HealthEndpointGroups groups = mock(HealthEndpointGroups.class);
|
||||||
|
Set<String> names = new LinkedHashSet<>();
|
||||||
|
names.add("test");
|
||||||
|
names.add("readiness");
|
||||||
|
given(groups.getNames()).willReturn(names);
|
||||||
|
assertThat(this.postProcessor.postProcessHealthEndpointGroups(groups))
|
||||||
|
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postProcessHealthEndpointGroupsWhenGroupsContainsNoneReturnsProcessed() {
|
||||||
|
HealthEndpointGroups groups = mock(HealthEndpointGroups.class);
|
||||||
|
Set<String> names = new LinkedHashSet<>();
|
||||||
|
names.add("test");
|
||||||
|
names.add("spring");
|
||||||
|
names.add("boot");
|
||||||
|
given(groups.getNames()).willReturn(names);
|
||||||
|
assertThat(this.postProcessor.postProcessHealthEndpointGroups(groups))
|
||||||
|
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.availability;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.availability.AvailabilityProbesHealthEndpointGroupsRegistrar;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistry;
|
|
||||||
import org.springframework.boot.actuate.health.TestHealthEndpointGroupsRegistry;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@code ProbesHealthEndpointGroupsRegistrar}
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class AvailabilityProbesHealthEndpointGroupsRegistrarTests {
|
|
||||||
|
|
||||||
private AvailabilityProbesHealthEndpointGroupsRegistrar registrar = new AvailabilityProbesHealthEndpointGroupsRegistrar();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldAddKubernetesProbes() {
|
|
||||||
HealthEndpointGroupsRegistry registry = new TestHealthEndpointGroupsRegistry();
|
|
||||||
this.registrar.customize(registry);
|
|
||||||
HealthEndpointGroup liveness = registry.get("liveness");
|
|
||||||
assertThat(liveness).isNotNull();
|
|
||||||
assertThat(liveness.isMember("livenessProbe")).isTrue();
|
|
||||||
HealthEndpointGroup readiness = registry.get("readiness");
|
|
||||||
assertThat(readiness).isNotNull();
|
|
||||||
assertThat(readiness.isMember("readinessProbe")).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void shouldNotAddProbeIfGroupExists() {
|
|
||||||
HealthEndpointGroupsRegistry registry = new TestHealthEndpointGroupsRegistry();
|
|
||||||
registry.add("readiness", (configurer) -> configurer.include("test"));
|
|
||||||
this.registrar.customize(registry);
|
|
||||||
|
|
||||||
HealthEndpointGroup liveness = registry.get("liveness");
|
|
||||||
assertThat(liveness).isNotNull();
|
|
||||||
assertThat(liveness.isMember("livenessProbe")).isTrue();
|
|
||||||
|
|
||||||
HealthEndpointGroup readiness = registry.get("readiness");
|
|
||||||
assertThat(readiness).isNotNull();
|
|
||||||
assertThat(readiness.isMember("readinessProbe")).isFalse();
|
|
||||||
assertThat(readiness.isMember("test")).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroup;
|
||||||
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link AvailabilityProbesHealthEndpointGroups}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class AvailabilityProbesHealthEndpointGroupsTests {
|
||||||
|
|
||||||
|
private HealthEndpointGroups delegate;
|
||||||
|
|
||||||
|
private HealthEndpointGroup group;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.delegate = mock(HealthEndpointGroups.class);
|
||||||
|
this.group = mock(HealthEndpointGroup.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createWhenGroupsIsNullThrowsException() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> new AvailabilityProbesHealthEndpointGroups(null))
|
||||||
|
.withMessage("Groups must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getPrimaryDelegatesToGroups() {
|
||||||
|
given(this.delegate.getPrimary()).willReturn(this.group);
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
assertThat(availabilityProbes.getPrimary()).isEqualTo(this.group);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getNamesIncludesAvailabilityProbeGroups() {
|
||||||
|
given(this.delegate.getNames()).willReturn(Collections.singleton("test"));
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
assertThat(availabilityProbes.getNames()).containsExactly("test", "liveness", "readiness");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWhenProbeInDelegateReturnsGroupFromDelegate() {
|
||||||
|
given(this.delegate.get("liveness")).willReturn(this.group);
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
assertThat(availabilityProbes.get("liveness")).isEqualTo(this.group);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWhenProbeNotInDelegateReturnsProbeGroup() {
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
assertThat(availabilityProbes.get("liveness")).isInstanceOf(AvailabilityProbesHealthEndpointGroup.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWhenNotProbeAndNotInDelegateReturnsNull() {
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
assertThat(availabilityProbes.get("mygroup")).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getLivenessProbeHasOnlyLivenessStateAsMember() {
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
HealthEndpointGroup probeGroup = availabilityProbes.get("liveness");
|
||||||
|
assertThat(probeGroup.isMember("livenessState")).isTrue();
|
||||||
|
assertThat(probeGroup.isMember("readinessState")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getRedinessProbeHasOnlyReadinessStateAsMember() {
|
||||||
|
HealthEndpointGroups availabilityProbes = new AvailabilityProbesHealthEndpointGroups(this.delegate);
|
||||||
|
HealthEndpointGroup probeGroup = availabilityProbes.get("readiness");
|
||||||
|
assertThat(probeGroup.isMember("livenessState")).isFalse();
|
||||||
|
assertThat(probeGroup.isMember("readinessState")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void containsAllWhenContainsAllReturnTrue() {
|
||||||
|
given(this.delegate.getNames()).willReturn(new LinkedHashSet<>(Arrays.asList("test", "liveness", "readiness")));
|
||||||
|
assertThat(AvailabilityProbesHealthEndpointGroups.containsAllProbeGroups(this.delegate)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void containsAllWhenContainsOneReturnFalse() {
|
||||||
|
given(this.delegate.getNames()).willReturn(new LinkedHashSet<>(Arrays.asList("test", "liveness")));
|
||||||
|
assertThat(AvailabilityProbesHealthEndpointGroups.containsAllProbeGroups(this.delegate)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void containsAllWhenContainsNoneReturnFalse() {
|
||||||
|
given(this.delegate.getNames()).willReturn(new LinkedHashSet<>(Arrays.asList("test", "spring")));
|
||||||
|
assertThat(AvailabilityProbesHealthEndpointGroups.containsAllProbeGroups(this.delegate)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,8 +25,8 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Show;
|
||||||
import org.springframework.boot.actuate.endpoint.SecurityContext;
|
import org.springframework.boot.actuate.endpoint.SecurityContext;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup.Show;
|
|
||||||
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
import org.springframework.boot.actuate.health.StatusAggregator;
|
import org.springframework.boot.actuate.health.StatusAggregator;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
@ -37,11 +37,11 @@ import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link DefaultHealthEndpointGroup}.
|
* Tests for {@link AutoConfiguredHealthEndpointGroup}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class DefaultHealthEndpointGroupTests {
|
class AutoConfiguredHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private StatusAggregator statusAggregator;
|
private StatusAggregator statusAggregator;
|
||||||
|
@ -62,7 +62,7 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void isMemberWhenMemberPredicateMatchesAcceptsTrue() {
|
void isMemberWhenMemberPredicateMatchesAcceptsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> name.startsWith("a"),
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> name.startsWith("a"),
|
||||||
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(group.isMember("albert")).isTrue();
|
assertThat(group.isMember("albert")).isTrue();
|
||||||
assertThat(group.isMember("arnold")).isTrue();
|
assertThat(group.isMember("arnold")).isTrue();
|
||||||
|
@ -70,7 +70,7 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void isMemberWhenMemberPredicateRejectsReturnsTrue() {
|
void isMemberWhenMemberPredicateRejectsReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> name.startsWith("a"),
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> name.startsWith("a"),
|
||||||
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(group.isMember("bert")).isFalse();
|
assertThat(group.isMember("bert")).isFalse();
|
||||||
assertThat(group.isMember("ernie")).isFalse();
|
assertThat(group.isMember("ernie")).isFalse();
|
||||||
|
@ -78,38 +78,39 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsNeverReturnsFalse() {
|
void showDetailsWhenShowDetailsIsNeverReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.NEVER, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.NEVER, Collections.emptySet());
|
||||||
assertThat(group.showDetails(SecurityContext.NONE)).isFalse();
|
assertThat(group.showDetails(SecurityContext.NONE)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsAlwaysReturnsTrue() {
|
void showDetailsWhenShowDetailsIsAlwaysReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(group.showDetails(SecurityContext.NONE)).isTrue();
|
assertThat(group.showDetails(SecurityContext.NONE)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsWhenAuthorizedAndPrincipalIsNullReturnsFalse() {
|
void showDetailsWhenShowDetailsIsWhenAuthorizedAndPrincipalIsNullReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Collections.emptySet());
|
||||||
given(this.securityContext.getPrincipal()).willReturn(null);
|
given(this.securityContext.getPrincipal()).willReturn(null);
|
||||||
assertThat(group.showDetails(this.securityContext)).isFalse();
|
assertThat(group.showDetails(this.securityContext)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsWhenAuthorizedAndRolesAreEmptyReturnsTrue() {
|
void showDetailsWhenShowDetailsIsWhenAuthorizedAndRolesAreEmptyReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Collections.emptySet());
|
||||||
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
||||||
assertThat(group.showDetails(this.securityContext)).isTrue();
|
assertThat(group.showDetails(this.securityContext)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUseIsInRoleReturnsTrue() {
|
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUseIsInRoleReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Arrays.asList("admin", "root", "bossmode"));
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED,
|
||||||
|
Arrays.asList("admin", "root", "bossmode"));
|
||||||
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
||||||
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
||||||
assertThat(group.showDetails(this.securityContext)).isTrue();
|
assertThat(group.showDetails(this.securityContext)).isTrue();
|
||||||
|
@ -117,8 +118,9 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUseIsNotInRoleReturnsFalse() {
|
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUseIsNotInRoleReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Arrays.asList("admin", "rot", "bossmode"));
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED,
|
||||||
|
Arrays.asList("admin", "rot", "bossmode"));
|
||||||
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
||||||
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
||||||
assertThat(group.showDetails(this.securityContext)).isFalse();
|
assertThat(group.showDetails(this.securityContext)).isFalse();
|
||||||
|
@ -126,8 +128,9 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUserHasRightAuthorityReturnsTrue() {
|
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUserHasRightAuthorityReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Arrays.asList("admin", "root", "bossmode"));
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED,
|
||||||
|
Arrays.asList("admin", "root", "bossmode"));
|
||||||
Authentication principal = mock(Authentication.class);
|
Authentication principal = mock(Authentication.class);
|
||||||
given(principal.getAuthorities())
|
given(principal.getAuthorities())
|
||||||
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority("admin")));
|
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority("admin")));
|
||||||
|
@ -137,8 +140,9 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUserDoesNotHaveRightAuthoritiesReturnsFalse() {
|
void showDetailsWhenShowDetailsIsWhenAuthorizedAndUserDoesNotHaveRightAuthoritiesReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED, Arrays.asList("admin", "rot", "bossmode"));
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.WHEN_AUTHORIZED,
|
||||||
|
Arrays.asList("admin", "rot", "bossmode"));
|
||||||
Authentication principal = mock(Authentication.class);
|
Authentication principal = mock(Authentication.class);
|
||||||
given(principal.getAuthorities())
|
given(principal.getAuthorities())
|
||||||
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority("other")));
|
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority("other")));
|
||||||
|
@ -148,48 +152,50 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsNullDelegatesToShowDetails() {
|
void showComponentsWhenShowComponentsIsNullDelegatesToShowDetails() {
|
||||||
DefaultHealthEndpointGroup alwaysGroup = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup alwaysGroup = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(alwaysGroup.showComponents(SecurityContext.NONE)).isTrue();
|
assertThat(alwaysGroup.showComponents(SecurityContext.NONE)).isTrue();
|
||||||
DefaultHealthEndpointGroup neverGroup = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup neverGroup = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.NEVER, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.NEVER, Collections.emptySet());
|
||||||
assertThat(neverGroup.showComponents(SecurityContext.NONE)).isFalse();
|
assertThat(neverGroup.showComponents(SecurityContext.NONE)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsNeverReturnsFalse() {
|
void showComponentsWhenShowComponentsIsNeverReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.NEVER, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, Show.NEVER, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(group.showComponents(SecurityContext.NONE)).isFalse();
|
assertThat(group.showComponents(SecurityContext.NONE)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsAlwaysReturnsTrue() {
|
void showComponentsWhenShowComponentsIsAlwaysReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.ALWAYS, Show.NEVER, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, Show.ALWAYS, Show.NEVER, Collections.emptySet());
|
||||||
assertThat(group.showComponents(SecurityContext.NONE)).isTrue();
|
assertThat(group.showComponents(SecurityContext.NONE)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsWhenAuthorizedAndPrincipalIsNullReturnsFalse() {
|
void showComponentsWhenShowComponentsIsWhenAuthorizedAndPrincipalIsNullReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
||||||
|
Collections.emptySet());
|
||||||
given(this.securityContext.getPrincipal()).willReturn(null);
|
given(this.securityContext.getPrincipal()).willReturn(null);
|
||||||
assertThat(group.showComponents(this.securityContext)).isFalse();
|
assertThat(group.showComponents(this.securityContext)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsWhenAuthorizedAndRolesAreEmptyReturnsTrue() {
|
void showComponentsWhenShowComponentsIsWhenAuthorizedAndRolesAreEmptyReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
||||||
|
Collections.emptySet());
|
||||||
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
||||||
assertThat(group.showComponents(this.securityContext)).isTrue();
|
assertThat(group.showComponents(this.securityContext)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUseIsInRoleReturnsTrue() {
|
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUseIsInRoleReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
this.statusAggregator, this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
||||||
Arrays.asList("admin", "root", "bossmode"));
|
Arrays.asList("admin", "root", "bossmode"));
|
||||||
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
||||||
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
||||||
|
@ -198,8 +204,9 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUseIsNotInRoleReturnsFalse() {
|
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUseIsNotInRoleReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER, Arrays.asList("admin", "rot", "bossmode"));
|
this.statusAggregator, this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
||||||
|
Arrays.asList("admin", "rot", "bossmode"));
|
||||||
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
given(this.securityContext.getPrincipal()).willReturn(this.principal);
|
||||||
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
given(this.securityContext.isUserInRole("root")).willReturn(true);
|
||||||
assertThat(group.showComponents(this.securityContext)).isFalse();
|
assertThat(group.showComponents(this.securityContext)).isFalse();
|
||||||
|
@ -207,8 +214,8 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUserHasRightAuthoritiesReturnsTrue() {
|
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUserHasRightAuthoritiesReturnsTrue() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
this.statusAggregator, this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
||||||
Arrays.asList("admin", "root", "bossmode"));
|
Arrays.asList("admin", "root", "bossmode"));
|
||||||
Authentication principal = mock(Authentication.class);
|
Authentication principal = mock(Authentication.class);
|
||||||
given(principal.getAuthorities())
|
given(principal.getAuthorities())
|
||||||
|
@ -219,8 +226,9 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUserDoesNotHaveRightAuthoritiesReturnsFalse() {
|
void showComponentsWhenShowComponentsIsWhenAuthorizedAndUserDoesNotHaveRightAuthoritiesReturnsFalse() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER, Arrays.asList("admin", "rot", "bossmode"));
|
this.statusAggregator, this.httpCodeStatusMapper, Show.WHEN_AUTHORIZED, Show.NEVER,
|
||||||
|
Arrays.asList("admin", "rot", "bossmode"));
|
||||||
Authentication principal = mock(Authentication.class);
|
Authentication principal = mock(Authentication.class);
|
||||||
given(principal.getAuthorities())
|
given(principal.getAuthorities())
|
||||||
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority("other")));
|
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority("other")));
|
||||||
|
@ -230,15 +238,15 @@ class DefaultHealthEndpointGroupTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getStatusAggregatorReturnsStatusAggregator() {
|
void getStatusAggregatorReturnsStatusAggregator() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(group.getStatusAggregator()).isSameAs(this.statusAggregator);
|
assertThat(group.getStatusAggregator()).isSameAs(this.statusAggregator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getHttpCodeStatusMapperReturnsHttpCodeStatusMapper() {
|
void getHttpCodeStatusMapperReturnsHttpCodeStatusMapper() {
|
||||||
DefaultHealthEndpointGroup group = new DefaultHealthEndpointGroup((name) -> true, this.statusAggregator,
|
AutoConfiguredHealthEndpointGroup group = new AutoConfiguredHealthEndpointGroup((name) -> true,
|
||||||
this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
this.statusAggregator, this.httpCodeStatusMapper, null, Show.ALWAYS, Collections.emptySet());
|
||||||
assertThat(group.getHttpCodeStatusMapper()).isSameAs(this.httpCodeStatusMapper);
|
assertThat(group.getHttpCodeStatusMapper()).isSameAs(this.httpCodeStatusMapper);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,11 @@ import org.springframework.context.annotation.Primary;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AutoConfiguredHealthEndpointGroupsRegistry}.
|
* Tests for {@link AutoConfiguredHealthEndpointGroups}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class AutoConfiguredHealthEndpointGroupsBuilderTests {
|
class AutoConfiguredHealthEndpointGroupsTests {
|
||||||
|
|
||||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
.withConfiguration(AutoConfigurations.of(AutoConfiguredHealthEndpointGroupsTestConfiguration.class));
|
.withConfiguration(AutoConfigurations.of(AutoConfiguredHealthEndpointGroupsTestConfiguration.class));
|
||||||
|
@ -313,9 +313,9 @@ class AutoConfiguredHealthEndpointGroupsBuilderTests {
|
||||||
static class AutoConfiguredHealthEndpointGroupsTestConfiguration {
|
static class AutoConfiguredHealthEndpointGroupsTestConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
AutoConfiguredHealthEndpointGroupsRegistry healthEndpointGroups(
|
AutoConfiguredHealthEndpointGroups healthEndpointGroups(ConfigurableApplicationContext applicationContext,
|
||||||
ConfigurableApplicationContext applicationContext, HealthEndpointProperties properties) {
|
HealthEndpointProperties properties) {
|
||||||
return new AutoConfiguredHealthEndpointGroupsRegistry(applicationContext, properties);
|
return new AutoConfiguredHealthEndpointGroups(applicationContext, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -37,7 +37,7 @@ import org.springframework.boot.actuate.health.HealthComponent;
|
||||||
import org.springframework.boot.actuate.health.HealthContributorRegistry;
|
import org.springframework.boot.actuate.health.HealthContributorRegistry;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
import org.springframework.boot.actuate.health.HealthEndpointGroups;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroupsRegistryCustomizer;
|
import org.springframework.boot.actuate.health.HealthEndpointGroupsPostProcessor;
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointWebExtension;
|
import org.springframework.boot.actuate.health.HealthEndpointWebExtension;
|
||||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||||
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
import org.springframework.boot.actuate.health.HttpCodeStatusMapper;
|
||||||
|
@ -56,6 +56,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
@ -155,6 +156,7 @@ class HealthEndpointAutoConfigurationTests {
|
||||||
void runCreatesHealthEndpointGroups() {
|
void runCreatesHealthEndpointGroups() {
|
||||||
this.contextRunner.withPropertyValues("management.endpoint.health.group.ready.include=*").run((context) -> {
|
this.contextRunner.withPropertyValues("management.endpoint.health.group.ready.include=*").run((context) -> {
|
||||||
HealthEndpointGroups groups = context.getBean(HealthEndpointGroups.class);
|
HealthEndpointGroups groups = context.getBean(HealthEndpointGroups.class);
|
||||||
|
assertThat(groups).isInstanceOf(AutoConfiguredHealthEndpointGroups.class);
|
||||||
assertThat(groups.getNames()).containsOnly("ready");
|
assertThat(groups.getNames()).containsOnly("ready");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -302,11 +304,12 @@ class HealthEndpointAutoConfigurationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void runWhenHealthEndpointGroupsRegistryCustomizerAddsHealthEndpointGroup() {
|
void runWhenHasHealthEndpointGroupsPostProcessorPerformsProcessing() {
|
||||||
this.contextRunner.withUserConfiguration(HealthEndpointGroupsRegistryCustomizerConfig.class).run((context) -> {
|
this.contextRunner.withPropertyValues("management.endpoint.health.group.ready.include=*").withUserConfiguration(
|
||||||
assertThat(context).hasSingleBean(HealthEndpointGroupsRegistryCustomizer.class);
|
HealthEndpointGroupsConfiguration.class, TestHealthEndpointGroupsPostProcessor.class).run((context) -> {
|
||||||
HealthEndpointGroups groups = context.getBean(HealthEndpointGroups.class);
|
HealthEndpointGroups groups = context.getBean(HealthEndpointGroups.class);
|
||||||
assertThat(groups.getNames()).contains("test");
|
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> groups.get("test"))
|
||||||
|
.withMessage("postprocessed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,12 +432,12 @@ class HealthEndpointAutoConfigurationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
static class TestHealthEndpointGroupsPostProcessor implements HealthEndpointGroupsPostProcessor {
|
||||||
static class HealthEndpointGroupsRegistryCustomizerConfig {
|
|
||||||
|
|
||||||
@Bean
|
@Override
|
||||||
HealthEndpointGroupsRegistryCustomizer customHealthEndpointGroup() {
|
public HealthEndpointGroups postProcessHealthEndpointGroups(HealthEndpointGroups groups) {
|
||||||
return (registry) -> registry.add("test", (configurer) -> configurer.include("ping"));
|
given(groups.get("test")).willThrow(new RuntimeException("postprocessed"));
|
||||||
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import org.springframework.boot.actuate.endpoint.SecurityContext;
|
||||||
* by the {@link HealthEndpoint}.
|
* by the {@link HealthEndpoint}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
*/
|
*/
|
||||||
public interface HealthEndpointGroup {
|
public interface HealthEndpointGroup {
|
||||||
|
@ -63,27 +62,4 @@ public interface HealthEndpointGroup {
|
||||||
*/
|
*/
|
||||||
HttpCodeStatusMapper getHttpCodeStatusMapper();
|
HttpCodeStatusMapper getHttpCodeStatusMapper();
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for showing items in responses from the {@link HealthEndpointGroup} web
|
|
||||||
* extensions.
|
|
||||||
*/
|
|
||||||
enum Show {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Never show the item in the response.
|
|
||||||
*/
|
|
||||||
NEVER,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the item in the response when accessed by an authorized user.
|
|
||||||
*/
|
|
||||||
WHEN_AUTHORIZED,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always show the item in the response.
|
|
||||||
*/
|
|
||||||
ALWAYS
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.health;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.health.HealthEndpointGroup.Show;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A configurer for customizing an {@link HealthEndpointGroup} being built.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.3.0
|
|
||||||
*/
|
|
||||||
public interface HealthEndpointGroupConfigurer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the indicator endpoint ids to include in this group.
|
|
||||||
* @param indicators the indicator endpoint ids
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer include(String... indicators);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the indicator endpoint ids to exclude from this group.
|
|
||||||
* @param indicators the indicator endpoint ids
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer exclude(String... indicators);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the {@link StatusAggregator} to use for this group.
|
|
||||||
* <p>
|
|
||||||
* If none set, this will default to the globally configured {@link StatusAggregator}.
|
|
||||||
* @param statusAggregator the status aggregator
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer statusAggregator(StatusAggregator statusAggregator);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the {@link HttpCodeStatusMapper} to use for this group.
|
|
||||||
* <p>
|
|
||||||
* If none set, this will default to the globally configured
|
|
||||||
* {@link HttpCodeStatusMapper}.
|
|
||||||
* @param httpCodeStatusMapper the status code mapper
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer httpCodeStatusMapper(HttpCodeStatusMapper httpCodeStatusMapper);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the {@link Show visibility option} for showing components of this group.
|
|
||||||
* @param showComponents the components visibility
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer showComponents(Show showComponents);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the {@link Show visibility option} for showing details of this group.
|
|
||||||
* @param showDetails the details visibility
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer showDetails(Show showDetails);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure roles used to determine whether or not a user is authorized to be shown
|
|
||||||
* details.
|
|
||||||
* @param roles the roles
|
|
||||||
* @return the configurer instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupConfigurer roles(String... roles);
|
|
||||||
|
|
||||||
}
|
|
|
@ -17,19 +17,22 @@
|
||||||
package org.springframework.boot.actuate.health;
|
package org.springframework.boot.actuate.health;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback interface that can be used to customize a
|
* Hook that allows for custom modification of {@link HealthEndpointGroups} — for
|
||||||
* {@link HealthEndpointGroupsRegistry}.
|
* example, automatically adding additional auto-configured groups.
|
||||||
*
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @since 2.3.0
|
* @since 2.3.0
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface HealthEndpointGroupsRegistryCustomizer {
|
public interface HealthEndpointGroupsPostProcessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to customize a {@link HealthEndpointGroupsRegistry} instance.
|
* Post-process the given {@link HealthEndpointGroups} instance.
|
||||||
* @param healthEndpointGroupsRegistry the registry to customize
|
* @param groups the existing groups instance
|
||||||
|
* @return a post-processed groups instance, or the original instance if not
|
||||||
|
* post-processing was required
|
||||||
*/
|
*/
|
||||||
void customize(HealthEndpointGroupsRegistry healthEndpointGroupsRegistry);
|
HealthEndpointGroups postProcessHealthEndpointGroups(HealthEndpointGroups groups);
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.health;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for an {@link HealthEndpointGroups} immutable instance.
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.3.0
|
|
||||||
*/
|
|
||||||
public interface HealthEndpointGroupsRegistry extends HealthEndpointGroups {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new {@link HealthEndpointGroup}.
|
|
||||||
* @param groupName the name of the group to add
|
|
||||||
* @param builder the group to add
|
|
||||||
* @return the builder instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupsRegistry add(String groupName, Consumer<HealthEndpointGroupConfigurer> builder);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an existing {@link HealthEndpointGroup}.
|
|
||||||
* @param groupName the name of the group to remove
|
|
||||||
* @return the builder instance
|
|
||||||
*/
|
|
||||||
HealthEndpointGroupsRegistry remove(String groupName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an immutable {@link HealthEndpointGroups}.
|
|
||||||
* @return the {@link HealthEndpointGroups}
|
|
||||||
*/
|
|
||||||
HealthEndpointGroups toGroups();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -26,6 +26,12 @@ package org.springframework.boot.actuate.health;
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface HttpCodeStatusMapper {
|
public interface HttpCodeStatusMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link HttpCodeStatusMapper} instance using default mappings.
|
||||||
|
* @since 2.3.0
|
||||||
|
*/
|
||||||
|
HttpCodeStatusMapper DEFAULT = new SimpleHttpCodeStatusMapper();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the HTTP status code that corresponds to the given {@link Status health
|
* Return the HTTP status code that corresponds to the given {@link Status health
|
||||||
* status}.
|
* status}.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -32,6 +32,12 @@ import java.util.Set;
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface StatusAggregator {
|
public interface StatusAggregator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link StatusAggregator} instance using default ordering rules.
|
||||||
|
* @since 2.3.0
|
||||||
|
*/
|
||||||
|
StatusAggregator DEFAULT = new SimpleStatusAggregator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the aggregate status for the given set of statuses.
|
* Return the aggregate status for the given set of statuses.
|
||||||
* @param statuses the statuses to aggregate
|
* @param statuses the statuses to aggregate
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2020 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.health;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test implementation for {@link HealthEndpointGroupsRegistry}
|
|
||||||
*
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
public class TestHealthEndpointGroupsRegistry implements HealthEndpointGroupsRegistry {
|
|
||||||
|
|
||||||
private TestHealthEndpointGroup primary = new TestHealthEndpointGroup();
|
|
||||||
|
|
||||||
private Map<String, TestHealthEndpointGroup> groups = new HashMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupsRegistry add(String groupName, Consumer<HealthEndpointGroupConfigurer> builder) {
|
|
||||||
TestHealthEndpointGroupConfigurer configurer = new TestHealthEndpointGroupConfigurer();
|
|
||||||
builder.accept(configurer);
|
|
||||||
this.groups.put(groupName, configurer.toHealthEndpointGroup());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupsRegistry remove(String groupName) {
|
|
||||||
this.groups.remove(groupName);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroups toGroups() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroup getPrimary() {
|
|
||||||
return this.primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getNames() {
|
|
||||||
return this.groups.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroup get(String name) {
|
|
||||||
return this.groups.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestHealthEndpointGroupConfigurer implements HealthEndpointGroupConfigurer {
|
|
||||||
|
|
||||||
private Predicate<String> predicate = (name) -> true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer include(String... indicators) {
|
|
||||||
Predicate<String> included = Arrays.asList(indicators).stream()
|
|
||||||
.map((group) -> (Predicate<String>) (s) -> s.equals(group)).reduce(Predicate::or)
|
|
||||||
.orElse((s) -> true);
|
|
||||||
this.predicate = this.predicate.and(included);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer exclude(String... indicators) {
|
|
||||||
Predicate<String> excluded = Arrays.asList(indicators).stream()
|
|
||||||
.map((group) -> (Predicate<String>) (s) -> !s.equals(group)).reduce(Predicate::or)
|
|
||||||
.orElse((s) -> true);
|
|
||||||
this.predicate = this.predicate.and(excluded);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer statusAggregator(StatusAggregator statusAggregator) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer httpCodeStatusMapper(HttpCodeStatusMapper httpCodeStatusMapper) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer showComponents(HealthEndpointGroup.Show showComponents) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer showDetails(HealthEndpointGroup.Show showDetails) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HealthEndpointGroupConfigurer roles(String... roles) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
TestHealthEndpointGroup toHealthEndpointGroup() {
|
|
||||||
return new TestHealthEndpointGroup(this.predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue