From 66e538efbc67d76c450f5ae9b1b9c5e590378558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Mu=C3=B1iz?= Date: Mon, 16 Dec 2024 13:10:57 +0100 Subject: [PATCH] Moving informer registration to `KubernetesCloud` and make it thread safe. --- .../plugins/kubernetes/KubernetesCloud.java | 33 ++++++++++++++++--- .../kubernetes/KubernetesLauncher.java | 21 ++---------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java index 21dab08eb..fec252971 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud.java @@ -2,6 +2,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.commons.lang.StringUtils.isEmpty; +import static org.csanchez.jenkins.plugins.kubernetes.PodTemplateUtils.sanitizeLabel; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.common.StandardCredentials; @@ -51,11 +52,13 @@ import java.util.Base64; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; @@ -72,6 +75,7 @@ import org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateMap; import org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default; import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention; +import org.csanchez.jenkins.plugins.kubernetes.watch.PodStatusEventHandler; import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuth; import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException; import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl; @@ -931,10 +935,6 @@ public HttpResponse doCreate(StaplerRequest req, StaplerResponse rsp) return FormApply.success("templates"); } - public Map> getInformers() { - return informers; - } - @Extension public static class DescriptorImpl extends Descriptor { @Override @@ -1320,6 +1320,31 @@ public Cloud reconfigure(@NonNull StaplerRequest req, JSONObject form) throws De return newInstance; } + public void registerPodInformer(KubernetesSlave node, KubernetesClient client, String namespace) { + if (informers.get(namespace) == null) { + synchronized (this) { + // sync recheck + if (informers.get(namespace) != null) { + return; + } + Map labelsFilter = + new HashMap<>(node.getKubernetesCloud().getPodLabelsMap()); + String jenkinsUrlLabel = sanitizeLabel(this.getJenkinsUrlOrNull()); + if (jenkinsUrlLabel != null) { + labelsFilter.put(PodTemplateBuilder.LABEL_KUBERNETES_CONTROLLER, jenkinsUrlLabel); + } + SharedIndexInformer inform = client.pods() + .inNamespace(namespace) + .withLabels(labelsFilter) + .inform(new PodStatusEventHandler(), TimeUnit.SECONDS.toMillis(30)); + LOGGER.info(String.format( + "Registered informer to watch pod events on namespace [%s], with labels [%s]", + namespace, labelsFilter)); + informers.put(namespace, inform); + } + } + } + @Extension public static class PodTemplateSourceImpl extends PodTemplateSource { @NonNull diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java index 5a1316a5f..8608ebdd4 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesLauncher.java @@ -149,25 +149,8 @@ public synchronized void launch(SlaveComputer computer, TaskListener listener) { .orElse(null); node.setNamespace(namespace); - // register a namespace informer (if not registered yet) show relevant pod events in build logs - Map> informers = - node.getKubernetesCloud().getInformers(); - if (informers.get(namespace) == null) { - Map labelsFilter = - new HashMap<>(node.getKubernetesCloud().getPodLabelsMap()); - String jenkinsUrlLabel = sanitizeLabel(cloud.getJenkinsUrlOrNull()); - if (jenkinsUrlLabel != null) { - labelsFilter.put(PodTemplateBuilder.LABEL_KUBERNETES_CONTROLLER, jenkinsUrlLabel); - } - SharedIndexInformer inform = client.pods() - .inNamespace(namespace) - .withLabels(labelsFilter) - .inform(new PodStatusEventHandler(), TimeUnit.SECONDS.toMillis(30)); - LOGGER.info(String.format( - "Registered informer to watch pod events on namespace [%s], with labels [%s]", - namespace, labelsFilter)); - informers.put(namespace, inform); - } + // register a namespace informer (if not registered yet) to show relevant pod events in build logs + cloud.registerPodInformer(node, client, namespace); // if the controller was interrupted after creating the pod but before it connected back, then // the pod might already exist and the creating logic must be skipped.