From cae442fde54f90ad9f1301ea5b0a320592708e18 Mon Sep 17 00:00:00 2001 From: Cyril Sadovsky Date: Wed, 28 Sep 2022 20:01:52 +0200 Subject: [PATCH] Add possibility to disable configmap creation (#1081) --- docs/src/main/asciidoc/_configprops.adoc | 3 +- .../commons/leader/LeaderProperties.java | 15 ++++++ .../leader/Fabric8LeadershipController.java | 7 +++ .../Fabric8LeadershipControllerTest.java | 49 ++++++++++++++++++- 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 76b149db..e23dcdec 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -86,6 +86,7 @@ |spring.cloud.kubernetes.leader.publish-failed-events | `+++false+++` | Enable/disable publishing events in case leadership acquisition fails. Default: false |spring.cloud.kubernetes.leader.role | | Role for which leadership this candidate will compete. |spring.cloud.kubernetes.leader.update-period | `+++60000ms+++` | Leadership status check period. Default: 60s +|spring.cloud.kubernetes.leader.create-config-map | `+++true+++` | Enable/disable creating ConfigMap if it does not exist. Default: true |spring.cloud.kubernetes.loadbalancer.cluster-domain | `+++cluster.local+++` | cluster domain. |spring.cloud.kubernetes.loadbalancer.enabled | `+++true+++` | Load balancer enabled,default true. |spring.cloud.kubernetes.loadbalancer.mode | | {@link KubernetesLoadBalancerMode} setting load balancer server list with ip of pod or service name. default value is POD. @@ -115,4 +116,4 @@ |spring.cloud.kubernetes.secrets.sources | | |spring.cloud.kubernetes.secrets.use-name-as-prefix | `+++false+++` | -|=== \ No newline at end of file +|=== diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/leader/LeaderProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/leader/LeaderProperties.java index e66ebe53..f1352461 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/leader/LeaderProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/leader/LeaderProperties.java @@ -38,6 +38,8 @@ public class LeaderProperties { private static final boolean DEFAULT_PUBLISH_FAILED_EVENTS = false; + private static final boolean DEFAULT_CREATE_CONFIG_MAP = true; + /** * Should leader election be enabled. Default: true */ @@ -79,6 +81,11 @@ public class LeaderProperties { */ private boolean publishFailedEvents = DEFAULT_PUBLISH_FAILED_EVENTS; + /** + * Enable/disable creating ConfigMap if it does not exist. Default: true + */ + private boolean createConfigMap = DEFAULT_CREATE_CONFIG_MAP; + public boolean isEnabled() { return this.enabled; } @@ -151,4 +158,12 @@ public class LeaderProperties { this.publishFailedEvents = publishFailedEvents; } + public boolean isCreateConfigMap() { + return this.createConfigMap; + } + + public void setCreateConfigMap(boolean createConfigMap) { + this.createConfigMap = createConfigMap; + } + } diff --git a/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipController.java b/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipController.java index 757bd46c..fada557e 100644 --- a/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipController.java +++ b/spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipController.java @@ -51,6 +51,12 @@ public class Fabric8LeadershipController extends LeadershipController { public synchronized void update() { LOGGER.debug("Checking leader state"); ConfigMap configMap = getConfigMap(); + if (configMap == null && !leaderProperties.isCreateConfigMap()) { + LOGGER.warn("ConfigMap '{}' does not exist and leaderProperties.isCreateConfigMap() " + + "is false, cannot acquire leadership", leaderProperties.getConfigMapName()); + notifyOnFailedToAcquire(); + return; + } Leader leader = extractLeader(configMap); if (leader != null && isPodReady(leader.getId())) { @@ -98,6 +104,7 @@ public class Fabric8LeadershipController extends LeadershipController { try { Map data = getLeaderData(this.candidate); + if (configMap == null) { createConfigMap(data); } diff --git a/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipControllerTest.java b/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipControllerTest.java index 690df9ae..652c3f76 100644 --- a/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipControllerTest.java +++ b/spring-cloud-kubernetes-fabric8-leader/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/Fabric8LeadershipControllerTest.java @@ -17,17 +17,28 @@ package org.springframework.cloud.kubernetes.fabric8.leader; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; +import io.fabric8.kubernetes.client.dsl.Resource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.cloud.kubernetes.commons.leader.LeaderProperties; import org.springframework.integration.leader.Candidate; import org.springframework.integration.leader.event.LeaderEventPublisher; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * @author Gytis Trikleris @@ -44,7 +55,7 @@ public class Fabric8LeadershipControllerTest { @Mock private LeaderEventPublisher mockLeaderEventPublisher; - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private KubernetesClient mockKubernetesClient; private Fabric8LeadershipController fabric8LeadershipController; @@ -60,4 +71,40 @@ public class Fabric8LeadershipControllerTest { assertThat(this.fabric8LeadershipController.getLocalLeader().isPresent()).isFalse(); } + @ExtendWith(OutputCaptureExtension.class) + @Test + void whenNonExistentConfigmapAndCreationNotAllowedStopLeadershipAcquire(CapturedOutput output) { + // given + String testNamespace = "test-namespace"; + String testConfigmap = "test-configmap"; + Resource mockResource = Mockito.mock(Resource.class); + NonNamespaceOperation mockNonNamespaceOperation = Mockito.mock(NonNamespaceOperation.class); + + Fabric8LeadershipController fabric8LeadershipController = new Fabric8LeadershipController(mockCandidate, + mockLeaderProperties, mockLeaderEventPublisher, mockKubernetesClient); + + when(mockLeaderProperties.isCreateConfigMap()).thenReturn(false); + when(mockLeaderProperties.isPublishFailedEvents()).thenReturn(true); + when(mockLeaderProperties.getConfigMapName()).thenReturn(testConfigmap); + when(mockKubernetesClient.getNamespace()).thenReturn(testNamespace); + when(mockLeaderProperties.getNamespace(anyString())).thenReturn(testNamespace); + when(mockKubernetesClient.configMaps().inNamespace(anyString())).thenReturn(mockNonNamespaceOperation); + when(mockNonNamespaceOperation.withName(any())).thenReturn(mockResource); + when(mockResource.get()).thenReturn(null); + + // when + fabric8LeadershipController.update(); + + // then + assertThat(output).contains("ConfigMap '" + testConfigmap + "' does not exist " + + "and leaderProperties.isCreateConfigMap() is false, cannot acquire leadership"); + verify(mockLeaderEventPublisher).publishOnFailedToAcquire(any(), any(), any()); + + verify(mockKubernetesClient, never()).pods(); + verify(mockCandidate, never()).getId(); + verify(mockLeaderProperties, never()).getLeaderIdPrefix(); + verify(mockLeaderEventPublisher, never()).publishOnGranted(any(), any(), any()); + verify(mockLeaderEventPublisher, never()).publishOnRevoked(any(), any(), any()); + } + }