diff --git a/docs/modules/ROOT/pages/leader-election.adoc b/docs/modules/ROOT/pages/leader-election.adoc index bc0d920a77..9d86439dae 100644 --- a/docs/modules/ROOT/pages/leader-election.adoc +++ b/docs/modules/ROOT/pages/leader-election.adoc @@ -25,3 +25,29 @@ To specify the name of the configmap used for leader election use the following ---- spring.cloud.kubernetes.leader.config-map-name=leader ---- + +== Leader Election Info Contributor + +Spring Cloud Kubernetes Leader includes an `InfoContributor` which adds leader election information to +Spring Boot's `/actuator/info` endpoint. This contributor provides information about the current leader, +including the leader ID, role, and whether the current application instance is the leader. + +Example output: +[source,json] +---- +{ + "leaderElection": { + "leaderId": "my-app-pod-1", + "role": "my-role", + "isLeader": true + } +} +---- + +You can disable this `InfoContributor` by setting `management.info.leade.enabled` +to `false` in `application.[properties | yaml]`: + +[source,properties] +---- +management.info.leader.enabled=false +---- diff --git a/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfiguration.java b/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfiguration.java index bb04ed4275..037f35c0b8 100644 --- a/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfiguration.java +++ b/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfiguration.java @@ -20,6 +20,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.boot.actuate.autoconfigure.info.ConditionalOnEnabledInfoContributor; import org.springframework.boot.actuate.info.InfoContributor; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -74,6 +75,7 @@ public Candidate candidate(LeaderProperties leaderProperties) throws UnknownHost */ @Bean @ConditionalOnClass(InfoContributor.class) + @ConditionalOnEnabledInfoContributor("leader") public LeaderInfoContributor leaderInfoContributor(Fabric8LeadershipController fabric8LeadershipController, Candidate candidate) { return new LeaderInfoContributor(fabric8LeadershipController, candidate); diff --git a/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfigurationTests.java b/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfigurationTests.java index 566249cf82..a1549e21d9 100644 --- a/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderAutoConfigurationTests.java @@ -26,8 +26,6 @@ import org.springframework.http.MediaType; import org.springframework.test.web.reactive.server.WebTestClient; -import static org.hamcrest.Matchers.containsString; - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.leader.autoStartup=false", "management.endpoints.web.exposure.include=info", "management.endpoint.info.show-details=always", @@ -52,8 +50,13 @@ void infoEndpointShouldContainLeaderElection() { .exchange() .expectStatus() .isOk() - .expectBody(String.class) - .value(containsString("kubernetes")); + .expectBody() + .jsonPath("kubernetes") + .exists() + .jsonPath("leaderElection") + .exists() + .jsonPath("leaderElection.leaderId") + .exists(); } @SpringBootConfiguration diff --git a/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderInfoContributorDisabledTests.java b/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderInfoContributorDisabledTests.java new file mode 100644 index 0000000000..363c929f73 --- /dev/null +++ b/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeaderInfoContributorDisabledTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-present 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.cloud.kubernetes.fabric8.leader; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.kubernetes.commons.leader.LeaderInfoContributor; +import org.springframework.context.ApplicationContext; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Tests that verify LeaderInfoContributor can be disabled via configuration property. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { "spring.main.cloud-platform=KUBERNETES", "spring.cloud.kubernetes.leader.autoStartup=false", + "management.info.leader.enabled=false" }) +class Fabric8LeaderInfoContributorDisabledTests { + + @Autowired + private ApplicationContext context; + + /** + * Test that the LeaderInfoContributor bean is NOT present when + * management.info.leader.enabled=false + */ + @Test + void leaderInfoContributorShouldNotBePresent() { + assertThatThrownBy(() -> context.getBean(LeaderInfoContributor.class)) + .isInstanceOf(NoSuchBeanDefinitionException.class); + } + + @SpringBootConfiguration + @EnableAutoConfiguration + protected static class TestConfig { + + } + +}