Remove health actuator code deprecated in 2.2

This partially re-applies the deprecation removal from commit
df1837a16b,
without removing CompositeHealthIndicator, HealthAggregator, and related
configuration that is required by Spring Cloud.
This commit is contained in:
Scott Frederick
2020-02-03 17:07:56 -06:00
parent e64a145ef0
commit 60f5bb1636
20 changed files with 20 additions and 1103 deletions

View File

@@ -1,225 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.elasticsearch;
import java.util.Map;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchTimeoutException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.client.AdminClient;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.ClusterAdminClient;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlocks;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.routing.RoutingTable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.Status;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
/**
* Test for {@link ElasticsearchHealthIndicator}.
*
* @author Andy Wilkinson
*/
@Deprecated
class ElasticsearchHealthIndicatorTests {
@Mock
private Client client;
@Mock
private AdminClient admin;
@Mock
private ClusterAdminClient cluster;
private ElasticsearchHealthIndicator indicator;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
given(this.client.admin()).willReturn(this.admin);
given(this.admin.cluster()).willReturn(this.cluster);
this.indicator = new ElasticsearchHealthIndicator(this.client, 100L);
}
@Test
void defaultConfigurationQueriesAllIndicesWith100msTimeout() {
TestActionFuture responseFuture = new TestActionFuture();
responseFuture.onResponse(new StubClusterHealthResponse());
ArgumentCaptor<ClusterHealthRequest> requestCaptor = ArgumentCaptor.forClass(ClusterHealthRequest.class);
given(this.cluster.health(requestCaptor.capture())).willReturn(responseFuture);
Health health = this.indicator.health();
assertThat(responseFuture.getTimeout).isEqualTo(100L);
assertThat(requestCaptor.getValue().indices()).contains("_all");
assertThat(health.getStatus()).isEqualTo(Status.UP);
}
@Test
void certainIndices() {
this.indicator = new ElasticsearchHealthIndicator(this.client, 100L, "test-index-1", "test-index-2");
PlainActionFuture<ClusterHealthResponse> responseFuture = new PlainActionFuture<>();
responseFuture.onResponse(new StubClusterHealthResponse());
ArgumentCaptor<ClusterHealthRequest> requestCaptor = ArgumentCaptor.forClass(ClusterHealthRequest.class);
given(this.cluster.health(requestCaptor.capture())).willReturn(responseFuture);
Health health = this.indicator.health();
assertThat(requestCaptor.getValue().indices()).contains("test-index-1", "test-index-2");
assertThat(health.getStatus()).isEqualTo(Status.UP);
}
@Test
void customTimeout() {
this.indicator = new ElasticsearchHealthIndicator(this.client, 1000L);
TestActionFuture responseFuture = new TestActionFuture();
responseFuture.onResponse(new StubClusterHealthResponse());
ArgumentCaptor<ClusterHealthRequest> requestCaptor = ArgumentCaptor.forClass(ClusterHealthRequest.class);
given(this.cluster.health(requestCaptor.capture())).willReturn(responseFuture);
this.indicator.health();
assertThat(responseFuture.getTimeout).isEqualTo(1000L);
}
@Test
void healthDetails() {
PlainActionFuture<ClusterHealthResponse> responseFuture = new PlainActionFuture<>();
responseFuture.onResponse(new StubClusterHealthResponse());
given(this.cluster.health(any(ClusterHealthRequest.class))).willReturn(responseFuture);
Health health = this.indicator.health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
Map<String, Object> details = health.getDetails();
assertDetail(details, "clusterName", "test-cluster");
assertDetail(details, "activeShards", 1);
assertDetail(details, "relocatingShards", 2);
assertDetail(details, "activePrimaryShards", 3);
assertDetail(details, "initializingShards", 4);
assertDetail(details, "unassignedShards", 5);
assertDetail(details, "numberOfNodes", 6);
assertDetail(details, "numberOfDataNodes", 7);
}
@Test
void redResponseMapsToDown() {
PlainActionFuture<ClusterHealthResponse> responseFuture = new PlainActionFuture<>();
responseFuture.onResponse(new StubClusterHealthResponse(ClusterHealthStatus.RED));
given(this.cluster.health(any(ClusterHealthRequest.class))).willReturn(responseFuture);
assertThat(this.indicator.health().getStatus()).isEqualTo(Status.DOWN);
}
@Test
void yellowResponseMapsToUp() {
PlainActionFuture<ClusterHealthResponse> responseFuture = new PlainActionFuture<>();
responseFuture.onResponse(new StubClusterHealthResponse(ClusterHealthStatus.YELLOW));
given(this.cluster.health(any(ClusterHealthRequest.class))).willReturn(responseFuture);
assertThat(this.indicator.health().getStatus()).isEqualTo(Status.UP);
}
@Test
void responseTimeout() {
PlainActionFuture<ClusterHealthResponse> responseFuture = new PlainActionFuture<>();
given(this.cluster.health(any(ClusterHealthRequest.class))).willReturn(responseFuture);
Health health = this.indicator.health();
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
assertThat((String) health.getDetails().get("error")).contains(ElasticsearchTimeoutException.class.getName());
}
@SuppressWarnings("unchecked")
private <T> void assertDetail(Map<String, Object> details, String detail, T value) {
assertThat((T) details.get(detail)).isEqualTo(value);
}
private static final class StubClusterHealthResponse extends ClusterHealthResponse {
private final ClusterHealthStatus status;
private StubClusterHealthResponse() {
this(ClusterHealthStatus.GREEN);
}
private StubClusterHealthResponse(ClusterHealthStatus status) {
super("test-cluster", new String[0], new ClusterState(null, 0, null, null, RoutingTable.builder().build(),
DiscoveryNodes.builder().build(), ClusterBlocks.builder().build(), null, 1, false));
this.status = status;
}
@Override
public int getActiveShards() {
return 1;
}
@Override
public int getRelocatingShards() {
return 2;
}
@Override
public int getActivePrimaryShards() {
return 3;
}
@Override
public int getInitializingShards() {
return 4;
}
@Override
public int getUnassignedShards() {
return 5;
}
@Override
public int getNumberOfNodes() {
return 6;
}
@Override
public int getNumberOfDataNodes() {
return 7;
}
@Override
public ClusterHealthStatus getStatus() {
return this.status;
}
}
static class TestActionFuture extends PlainActionFuture<ClusterHealthResponse> {
private long getTimeout = -1L;
@Override
public ClusterHealthResponse actionGet(long timeoutMillis) throws ElasticsearchException {
this.getTimeout = timeoutMillis;
return super.actionGet(timeoutMillis);
}
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ApplicationHealthIndicator}.
*
* @author Phillip Webb
*/
@Deprecated
class ApplicationHealthIndicatorTests {
@Test
void indicatesUp() {
ApplicationHealthIndicator healthIndicator = new ApplicationHealthIndicator();
assertThat(healthIndicator.health().getStatus()).isEqualTo(Status.UP);
}
}

View File

@@ -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");
* you may not use this file except in compliance with the License.
@@ -24,26 +24,17 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link HealthEndpoint}.
*
* @author Phillip Webb
* @author Scott Frederick
*/
class HealthEndpointTests
extends HealthEndpointSupportTests<HealthContributorRegistry, HealthContributor, HealthComponent> {
@Test
@SuppressWarnings("deprecation")
void createWhenUsingDeprecatedConstructorThrowsException() {
HealthIndicator healthIndicator = mock(HealthIndicator.class);
assertThatIllegalStateException().isThrownBy(() -> new HealthEndpoint(healthIndicator))
.withMessage("Unable to create class org.springframework.boot.actuate.health.HealthEndpoint "
+ "using deprecated constructor");
}
@Test
void healthReturnsSystemHealth() {
this.registry.registerContributor("test", createContributor(this.up));

View File

@@ -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");
* you may not use this file except in compliance with the License.
@@ -27,27 +27,17 @@ import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link HealthEndpointWebExtension}.
*
* @author Phillip Webb
* @author Scott Frederick
*/
class HealthEndpointWebExtensionTests
extends HealthEndpointSupportTests<HealthContributorRegistry, HealthContributor, HealthComponent> {
@Test
@SuppressWarnings("deprecation")
void createWhenUsingDeprecatedConstructorThrowsException() {
HealthEndpoint delegate = mock(HealthEndpoint.class);
HealthWebEndpointResponseMapper responseMapper = mock(HealthWebEndpointResponseMapper.class);
assertThatIllegalStateException().isThrownBy(() -> new HealthEndpointWebExtension(delegate, responseMapper))
.withMessage("Unable to create class org.springframework.boot.actuate."
+ "health.HealthEndpointWebExtension using deprecated constructor");
}
@Test
void healthReturnsSystemHealth() {
this.registry.registerContributor("test", createContributor(this.up));

View File

@@ -1,155 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.security.Principal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
import org.mockito.stubbing.Answer;
import org.springframework.boot.actuate.endpoint.SecurityContext;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* Tests for {@link HealthWebEndpointResponseMapper}.
*
* @author Stephane Nicoll
*/
@Deprecated
class HealthWebEndpointResponseMapperTests {
private final HealthStatusHttpMapper statusHttpMapper = new HealthStatusHttpMapper();
private Set<String> authorizedRoles = Collections.singleton("ACTUATOR");
@Test
void mapDetailsWithDisableDetailsDoesNotInvokeSupplier() {
HealthWebEndpointResponseMapper mapper = createMapper(ShowDetails.NEVER);
Supplier<Health> supplier = mockSupplier();
SecurityContext securityContext = mock(SecurityContext.class);
WebEndpointResponse<Health> response = mapper.mapDetails(supplier, securityContext);
assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value());
verifyNoInteractions(supplier);
verifyNoInteractions(securityContext);
}
@Test
void mapDetailsWithUnauthorizedUserDoesNotInvokeSupplier() {
HealthWebEndpointResponseMapper mapper = createMapper(ShowDetails.WHEN_AUTHORIZED);
Supplier<Health> supplier = mockSupplier();
SecurityContext securityContext = mockSecurityContext("USER");
WebEndpointResponse<Health> response = mapper.mapDetails(supplier, securityContext);
assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value());
assertThat(response.getBody()).isNull();
verifyNoInteractions(supplier);
verify(securityContext).isUserInRole("ACTUATOR");
}
@Test
void mapDetailsWithAuthorizedUserInvokesSupplier() {
HealthWebEndpointResponseMapper mapper = createMapper(ShowDetails.WHEN_AUTHORIZED);
Supplier<Health> supplier = mockSupplier();
given(supplier.get()).willReturn(Health.down().build());
SecurityContext securityContext = mockSecurityContext("ACTUATOR");
WebEndpointResponse<Health> response = mapper.mapDetails(supplier, securityContext);
assertThat(response.getStatus()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE.value());
assertThat(response.getBody().getStatus()).isEqualTo(Status.DOWN);
verify(supplier).get();
verify(securityContext).isUserInRole("ACTUATOR");
}
@Test
void mapDetailsWithRightAuthoritiesInvokesSupplier() {
HealthWebEndpointResponseMapper mapper = createMapper(ShowDetails.WHEN_AUTHORIZED);
Supplier<Health> supplier = mockSupplier();
given(supplier.get()).willReturn(Health.down().build());
SecurityContext securityContext = getSecurityContext("ACTUATOR");
WebEndpointResponse<Health> response = mapper.mapDetails(supplier, securityContext);
assertThat(response.getStatus()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE.value());
assertThat(response.getBody().getStatus()).isEqualTo(Status.DOWN);
verify(supplier).get();
}
@Test
void mapDetailsWithOtherAuthoritiesShouldNotInvokeSupplier() {
HealthWebEndpointResponseMapper mapper = createMapper(ShowDetails.WHEN_AUTHORIZED);
Supplier<Health> supplier = mockSupplier();
given(supplier.get()).willReturn(Health.down().build());
SecurityContext securityContext = getSecurityContext("OTHER");
WebEndpointResponse<Health> response = mapper.mapDetails(supplier, securityContext);
assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value());
assertThat(response.getBody()).isNull();
verifyNoInteractions(supplier);
}
private SecurityContext getSecurityContext(String other) {
SecurityContext securityContext = mock(SecurityContext.class);
Authentication principal = mock(Authentication.class);
given(securityContext.getPrincipal()).willReturn(principal);
given(principal.getAuthorities())
.willAnswer((invocation) -> Collections.singleton(new SimpleGrantedAuthority(other)));
return securityContext;
}
@Test
void mapDetailsWithUnavailableHealth() {
HealthWebEndpointResponseMapper mapper = createMapper(ShowDetails.ALWAYS);
Supplier<Health> supplier = mockSupplier();
SecurityContext securityContext = mock(SecurityContext.class);
WebEndpointResponse<Health> response = mapper.mapDetails(supplier, securityContext);
assertThat(response.getStatus()).isEqualTo(HttpStatus.NOT_FOUND.value());
assertThat(response.getBody()).isNull();
verify(supplier).get();
verifyNoInteractions(securityContext);
}
@SuppressWarnings("unchecked")
private Supplier<Health> mockSupplier() {
return mock(Supplier.class);
}
private SecurityContext mockSecurityContext(String... roles) {
List<String> associatedRoles = Arrays.asList(roles);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole(anyString())).will((Answer<Boolean>) (invocation) -> {
String expectedRole = invocation.getArgument(0);
return associatedRoles.contains(expectedRole);
});
return securityContext;
}
private HealthWebEndpointResponseMapper createMapper(ShowDetails showDetails) {
return new HealthWebEndpointResponseMapper(this.statusHttpMapper, showDetails, this.authorizedRoles);
}
}

View File

@@ -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");
* you may not use this file except in compliance with the License.
@@ -28,28 +28,17 @@ import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.boot.actuate.health.HealthEndpointSupport.HealthResult;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ReactiveHealthEndpointWebExtension}.
*
* @author Phillip Webb
* @author Scott Frederick
*/
class ReactiveHealthEndpointWebExtensionTests extends
HealthEndpointSupportTests<ReactiveHealthContributorRegistry, ReactiveHealthContributor, Mono<? extends HealthComponent>> {
@Test
@SuppressWarnings("deprecation")
void createWhenUsingDeprecatedConstructorThrowsException() {
ReactiveHealthIndicator delegate = mock(ReactiveHealthIndicator.class);
HealthWebEndpointResponseMapper responseMapper = mock(HealthWebEndpointResponseMapper.class);
assertThatIllegalStateException()
.isThrownBy(() -> new ReactiveHealthEndpointWebExtension(delegate, responseMapper)).withMessage(
"Unable to create class org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension "
+ "using deprecated constructor");
}
@Test
void healthReturnsSystemHealth() {
this.registry.registerContributor("test", createContributor(this.up));