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 cbec9e68..8ae55521 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 @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2024 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. @@ -17,30 +17,34 @@ package org.springframework.cloud.kubernetes.fabric8.leader; import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.cloud.kubernetes.commons.leader.Leader; import org.springframework.cloud.kubernetes.commons.leader.LeaderProperties; import org.springframework.cloud.kubernetes.commons.leader.LeadershipController; import org.springframework.cloud.kubernetes.commons.leader.PodReadinessWatcher; +import org.springframework.core.log.LogAccessor; import org.springframework.integration.leader.Candidate; import org.springframework.integration.leader.event.LeaderEventPublisher; +import static org.springframework.cloud.kubernetes.commons.leader.LeaderUtils.guarded; + /** * @author Gytis Trikleris */ public class Fabric8LeadershipController extends LeadershipController { - private static final Logger LOGGER = LoggerFactory.getLogger(Fabric8LeadershipController.class); + private static final LogAccessor LOGGER = new LogAccessor(Fabric8LeadershipController.class); private final KubernetesClient kubernetesClient; + private final ReentrantLock lock = new ReentrantLock(); + public Fabric8LeadershipController(Candidate candidate, LeaderProperties leaderProperties, LeaderEventPublisher leaderEventPublisher, KubernetesClient kubernetesClient) { super(candidate, leaderProperties, leaderEventPublisher); @@ -48,41 +52,47 @@ public class Fabric8LeadershipController extends LeadershipController { } @Override - 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); + public void update() { + guarded(lock, () -> { + LOGGER.debug(() -> "Checking leader state"); + ConfigMap configMap = getConfigMap(); + if (configMap == null && !leaderProperties.isCreateConfigMap()) { + LOGGER.warn("ConfigMap '" + leaderProperties.getConfigMapName() + + "' does not exist and leaderProperties.isCreateConfigMap() " + + "is false, cannot acquire leadership"); + notifyOnFailedToAcquire(); + return; + } + Leader leader = extractLeader(configMap); - if (leader != null && isPodReady(leader.getId())) { - handleLeaderChange(leader); - return; - } + if (leader != null && isPodReady(leader.getId())) { + handleLeaderChange(leader); + return; + } + + if (leader != null && leader.isCandidate(candidate)) { + revoke(configMap); + } + else { + acquire(configMap); + } + }); - if (leader != null && leader.isCandidate(this.candidate)) { - revoke(configMap); - } - else { - acquire(configMap); - } } - public synchronized void revoke() { - ConfigMap configMap = getConfigMap(); - Leader leader = extractLeader(configMap); + public void revoke() { + guarded(lock, () -> { + ConfigMap configMap = getConfigMap(); + Leader leader = extractLeader(configMap); - if (leader != null && leader.isCandidate(this.candidate)) { - revoke(configMap); - } + if (leader != null && leader.isCandidate(candidate)) { + revoke(configMap); + } + }); } private void revoke(ConfigMap configMap) { - LOGGER.debug("Trying to revoke leadership for '{}'", this.candidate); + LOGGER.debug(() -> "Trying to revoke leadership for :" + candidate); try { String leaderKey = getLeaderKey(); @@ -90,20 +100,20 @@ public class Fabric8LeadershipController extends LeadershipController { handleLeaderChange(null); } catch (KubernetesClientException e) { - LOGGER.warn("Failure when revoking leadership for '{}': {}", this.candidate, e.getMessage()); + LOGGER.warn("Failure when revoking leadership for : " + candidate + "because : " + e.getMessage()); } } private void acquire(ConfigMap configMap) { - LOGGER.debug("Trying to acquire leadership for '{}'", this.candidate); + LOGGER.debug(() -> "Trying to acquire leadership for :" + this.candidate); - if (!isPodReady(this.candidate.getId())) { - LOGGER.debug("Pod of '{}' is not ready at the moment, cannot acquire leadership", this.candidate); + if (!isPodReady(candidate.getId())) { + LOGGER.debug("Pod : " + candidate + "is not ready at the moment, cannot acquire leadership"); return; } try { - Map data = getLeaderData(this.candidate); + Map data = getLeaderData(candidate); if (configMap == null) { createConfigMap(data); @@ -112,11 +122,11 @@ public class Fabric8LeadershipController extends LeadershipController { updateConfigMapEntry(configMap, data); } - Leader newLeader = new Leader(this.candidate.getRole(), this.candidate.getId()); + Leader newLeader = new Leader(candidate.getRole(), candidate.getId()); handleLeaderChange(newLeader); } catch (KubernetesClientException e) { - LOGGER.warn("Failure when acquiring leadership for '{}': {}", this.candidate, e.getMessage()); + LOGGER.warn(() -> "Failure when acquiring leadership for : " + candidate + " because : " + e.getMessage()); notifyOnFailedToAcquire(); } } @@ -135,47 +145,39 @@ public class Fabric8LeadershipController extends LeadershipController { } private boolean isPodReady(String name) { - return this.kubernetesClient.pods().withName(name).isReady(); + return kubernetesClient.pods().withName(name).isReady(); } private ConfigMap getConfigMap() { - return this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) - .withName(this.leaderProperties.getConfigMapName()).get(); + return kubernetesClient.configMaps().inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace())) + .withName(leaderProperties.getConfigMapName()).get(); } private void createConfigMap(Map data) { - LOGGER.debug("Creating new config map with data: {}", data); + LOGGER.debug(() -> "Creating new config map with data: " + data); - ConfigMap newConfigMap = new ConfigMapBuilder().withNewMetadata() - .withName(this.leaderProperties.getConfigMapName()).addToLabels(PROVIDER_KEY, PROVIDER) - .addToLabels(KIND_KEY, KIND).endMetadata().addToData(data).build(); + ConfigMap newConfigMap = new ConfigMapBuilder().withNewMetadata().withName(leaderProperties.getConfigMapName()) + .addToLabels(PROVIDER_KEY, PROVIDER).addToLabels(KIND_KEY, KIND).endMetadata().addToData(data).build(); - this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) + kubernetesClient.configMaps().inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace())) .resource(newConfigMap).create(); } private void updateConfigMapEntry(ConfigMap configMap, Map newData) { - LOGGER.debug("Adding new data to config map: {}", newData); - + LOGGER.debug(() -> "Adding new data to config map: " + newData); ConfigMap newConfigMap = new ConfigMapBuilder(configMap).addToData(newData).build(); - updateConfigMap(configMap, newConfigMap); } private void removeConfigMapEntry(ConfigMap configMap, String key) { - LOGGER.debug("Removing config map entry '{}'", key); - + LOGGER.debug(() -> "Removing config map entry: " + key); ConfigMap newConfigMap = new ConfigMapBuilder(configMap).removeFromData(key).build(); - updateConfigMap(configMap, newConfigMap); } private void updateConfigMap(ConfigMap oldConfigMap, ConfigMap newConfigMap) { - this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) - .resource(newConfigMap).lockResourceVersion(oldConfigMap.getMetadata().getResourceVersion()).replace(); + kubernetesClient.configMaps().inNamespace(leaderProperties.getNamespace(kubernetesClient.getNamespace())) + .resource(newConfigMap).lockResourceVersion(oldConfigMap.getMetadata().getResourceVersion()).update(); } } 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 adee10a8..5347f71e 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 @@ -94,8 +94,7 @@ public class Fabric8LeadershipControllerTest { fabric8LeadershipController.update(); // then - assertThat(output).contains("ConfigMap '" + testConfigmap + "' does not exist " - + "and leaderProperties.isCreateConfigMap() is false, cannot acquire leadership"); + assertThat(output).contains("ConfigMap 'test-configmap' does not exist and leaderProperties.isCreateConfigMap() is false, cannot acquire leadership"); verify(mockLeaderEventPublisher).publishOnFailedToAcquire(any(), any(), any()); verify(mockKubernetesClient, never()).pods();