From 1083015eeef731fe985e63e5cfce9a22ae8377d9 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Mon, 27 Mar 2023 09:46:48 +0200 Subject: [PATCH 01/19] Upgrade kubernetes-client-api to 6.5.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4c2019e7c1..16eb4e8f78 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.jenkins-ci.plugins kubernetes-client-api - 6.4.1-215.v2ed17097a_8e9 + 6.5.1-216.vf0729f27532b_ org.jenkins-ci.plugins From e6cb569750fb3859faaf3acd80887c4e9427f9ab Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Mon, 27 Mar 2023 10:29:13 +0200 Subject: [PATCH 02/19] align kubernetes-server-mock with client --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 16eb4e8f78..f3a175de01 100644 --- a/pom.xml +++ b/pom.xml @@ -235,7 +235,7 @@ io.fabric8 kubernetes-server-mock - 6.4.1 + 6.5.1 test From 7d83ca28885810fc569c2a5bed3ea086fd9880bc Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Mon, 27 Mar 2023 13:45:54 +0200 Subject: [PATCH 03/19] Add some logs --- .../jenkins/plugins/kubernetes/pod/retention/Reaper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java index 33bae4575b..c98f0eea59 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java @@ -328,6 +328,7 @@ public void eventReceived(Action action, Pod pod) { */ void stop() { if (watch != null) { + LOGGER.info(() -> "Stopping watch for kubernetes cloud " + cloudName); this.watch.close(); } } From 5b812a7e7aa015c2036ec1fc07125b8d8ac15a3a Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Mon, 27 Mar 2023 14:57:32 +0200 Subject: [PATCH 04/19] New SnakeYAML engine does not support octal notation. For backward compatibility, converts decimal to octal notation --- .../plugins/kubernetes/PodTemplateUtils.java | 42 +++++++++++++++++++ .../kubernetes/pod/retention/ReaperTest.java | 39 ++++++++++------- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java index 8c656999f5..3d68f1a261 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java @@ -1,5 +1,8 @@ package org.csanchez.jenkins.plugins.kubernetes; +import io.fabric8.kubernetes.api.model.ConfigMapProjection; +import io.fabric8.kubernetes.api.model.KeyToPath; +import io.fabric8.kubernetes.api.model.SecretProjection; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -619,10 +622,49 @@ public static Pod parseFromYaml(String yaml) { if (podFromYaml.getSpec() == null) { podFromYaml.setSpec(new PodSpec()); } + fixOctal(podFromYaml); return podFromYaml; } } + private static void fixOctal(Pod podFromYaml) { + podFromYaml.getSpec().getVolumes().stream() + .map(Volume::getProjected) + .forEach(projected -> { + Integer defaultMode = projected.getDefaultMode(); + if (defaultMode != null) { + projected.setDefaultMode(convertToOctal(defaultMode)); + } + projected.getSources() + .stream() + .forEach(source -> { + ConfigMapProjection configMap = source.getConfigMap(); + if (configMap != null) { + convertDecimalIntegersToOctal(configMap.getItems()); + } + SecretProjection secret = source.getSecret(); + if (secret != null) { + convertDecimalIntegersToOctal(secret.getItems()); + } + }); + }); + } + + private static void convertDecimalIntegersToOctal(List items) { + items + .stream() + .forEach(i -> { + Integer mode = i.getMode(); + if (mode != null) { + i.setMode(convertToOctal(mode)); + } + }); + } + + private static int convertToOctal(Integer defaultMode) { + return Integer.parseInt(Integer.toString(defaultMode, 10), 8); + } + public static Collection validateYamlContainerNames(List yamls) { Collection errors = new ArrayList<>(); for (String yaml : yamls) { diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java index 44ea24e5de..a6c8b779df 100644 --- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java +++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java @@ -28,6 +28,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import io.fabric8.kubernetes.client.utils.Utils; import java.io.IOException; import java.net.HttpURLConnection; import java.util.LinkedList; @@ -507,6 +508,15 @@ public void testTerminateAgentOnContainerTerminated() throws IOException, Interr .always(); // don't remove pod on activate server.expect().withPath("/api/v1/namespaces/foo/pods/node-123").andReturn(200, node123).once(); + // Get logs + server.expect() + .withPath("/api/v1/namespaces/foo/pods?fieldSelector=" + Utils.toUrlEncoded("metadata.name=node-123")) + .andReturn(200, new PodListBuilder().withNewMetadata().endMetadata().withItems(node123).build()) + .always(); + server.expect() + .withPath("/api/v1/namespaces/foo/pods/node-123/log?pretty=false&tailLines=30") + .andReturn(200, "some log") + .always(); // activate reaper Reaper r = Reaper.getInstance(); @@ -515,13 +525,8 @@ public void testTerminateAgentOnContainerTerminated() throws IOException, Interr // verify node is still registered assertEquals("jenkins nodes", j.jenkins.getNodes().size(), 1); - // wait for the delete event to be processed - waitForKubeClientRequests(6) - .assertRequestCountAtLeast(watchPodsPath, 3); - // verify listener got notified - listener.waitForEvents() - .expectEvent(Watcher.Action.MODIFIED, node); + listener.waitForEvents().expectEvent(Watcher.Action.MODIFIED, node); // expect node to be terminated verify(node, atLeastOnce()).terminate(); @@ -617,14 +622,20 @@ private Pod withContainerImagePullBackoff(Pod pod) { } private Pod withContainerStatusTerminated(Pod pod) { - ContainerStatus status = new ContainerStatus(); - ContainerState state = new ContainerState(); - ContainerStateTerminated terminated = new ContainerStateTerminated(); - terminated.setExitCode(123); - terminated.setReason("because"); - state.setTerminated(terminated); - status.setState(state); - pod.getStatus().getContainerStatuses().add(status); + PodStatus podStatus = pod.getStatus(); + podStatus.getConditions().add(new PodConditionBuilder() + .withType("Ready") + .withStatus("True") + .build()); + podStatus.getContainerStatuses().add(new ContainerStatusBuilder() + .withState(new ContainerStateBuilder() + .withNewTerminated() + .withExitCode(123) + .withReason("because") + .and() + .build()) + .build()); + return pod; } From 19f6aa372cf3b449b6a15499b40e0790134e5060 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Mon, 27 Mar 2023 15:07:21 +0200 Subject: [PATCH 05/19] Spotbugs is stupid here --- .../jenkins/plugins/kubernetes/pod/retention/Reaper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java index c98f0eea59..e0fa733e5e 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java @@ -328,7 +328,7 @@ public void eventReceived(Action action, Pod pod) { */ void stop() { if (watch != null) { - LOGGER.info(() -> "Stopping watch for kubernetes cloud " + cloudName); + LOGGER.info("Stopping watch for kubernetes cloud " + cloudName); this.watch.close(); } } From 45a59852020f2ca01b179a97059809ff851ed878 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 23 Jun 2023 17:02:21 +0200 Subject: [PATCH 06/19] Proxy handling code was not mapping username. Remove usage of HttpClientUtils.getProxyUrl as it got removed in newer version of kubernetes-client --- .../kubernetes/KubernetesFactoryAdapter.java | 19 +++---- .../KubernetesFactoryAdapterTest.java | 52 +++++++++++++------ 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapter.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapter.java index 831daade05..f36c498097 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapter.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapter.java @@ -6,6 +6,8 @@ import io.fabric8.kubernetes.client.KubernetesClientBuilder; import java.util.Base64; import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.logging.Logger; import com.cloudbees.plugins.credentials.CredentialsMatchers; @@ -139,7 +141,7 @@ public KubernetesClient createClient() throws KubernetesAuthException { } LOGGER.log(FINE, "Creating Kubernetes client: {0}", this.toString()); - // JENKINS-63584 If Jenkins has an configured Proxy and cloud has enabled proxy usage pass the arguments to K8S + // JENKINS-63584 If Jenkins has a configured Proxy and cloud has enabled proxy usage pass the arguments to K8S LOGGER.log(FINE, "Proxy Settings for Cloud: " + useJenkinsProxy); if(useJenkinsProxy) { Jenkins jenkins = Jenkins.getInstanceOrNull(); @@ -150,9 +152,10 @@ public KubernetesClient createClient() throws KubernetesAuthException { if (p != null) { builder.withHttpsProxy("http://" + p.name + ":" + p.port); builder.withHttpProxy("http://" + p.name + ":" + p.port); - if (p.name != null) { + String proxyUserName = p.getUserName(); + if (proxyUserName != null) { String password = getProxyPasswordDecrypted(p); - builder.withProxyUsername(p.name); + builder.withProxyUsername(proxyUserName); builder.withProxyPassword(password); } builder.withNoProxy(getNoProxyHosts(p)); @@ -180,13 +183,11 @@ public KubernetesClient createClient() throws KubernetesAuthException { * @return the array of no proxy hosts */ private String[] getNoProxyHosts(@NonNull ProxyConfiguration proxy) { - String[] noProxyHosts = proxy.getNoProxyHost().split("\n"); - int i=0; - while(i noProxyHosts = new HashSet<>(); + for (String noProxyHost : proxy.getNoProxyHost().split("\n")) { + noProxyHosts.add(noProxyHost.replace("*", "")); } - return noProxyHosts; + return noProxyHosts.toArray(new String[0]); } private String getProxyPasswordDecrypted(ProxyConfiguration p) { diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapterTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapterTest.java index 1f30f4a810..4ec7573f12 100644 --- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapterTest.java +++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapterTest.java @@ -28,8 +28,8 @@ import com.cloudbees.plugins.credentials.SystemCredentialsProvider; import hudson.ProxyConfiguration; import hudson.util.Secret; +import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.utils.HttpClientUtils; import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException; import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl; import org.junit.After; @@ -39,7 +39,6 @@ import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; @@ -55,8 +54,6 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** @@ -176,32 +173,57 @@ public void autoConfigWithAuth() throws Exception { @Test @Issue("JENKINS-70563") - public void jenkinsProxyConfiguration() throws KubernetesAuthException, MalformedURLException { + public void jenkinsProxyConfiguration() throws KubernetesAuthException { j.jenkins.setProxy(new ProxyConfiguration("proxy.com", 123, PROXY_USERNAME, PROXY_PASSWORD, "*acme.com\n*acme*.com\n*.example.com|192.168.*")); KubernetesFactoryAdapter factory = new KubernetesFactoryAdapter("http://acme.com", null, null, null, false, 15, 5, 32, true); - try(KubernetesClient client = factory.createClient()) { - assertNull(HttpClientUtils.getProxyUrl(client.getConfiguration())); + try (KubernetesClient client = factory.createClient()) { + Config configuration = client.getConfiguration(); + assertEquals("http://proxy.com:123", configuration.getHttpProxy()); + assertEquals(PROXY_USERNAME, configuration.getProxyUsername()); + assertEquals(PROXY_PASSWORD, configuration.getProxyPassword()); + assertArrayEquals(new String[] {"acme.com", ".example.com|192.168."}, configuration.getNoProxy()); + assertEquals("http://proxy.com:123", configuration.getHttpsProxy()); } j.jenkins.setProxy(new ProxyConfiguration("proxy.com", 123, PROXY_USERNAME, PROXY_PASSWORD, "*acme.com")); factory = new KubernetesFactoryAdapter("http://acme.com", null, null, null, false, 15, 5, 32, true); - try(KubernetesClient client = factory.createClient()) { - assertNull(HttpClientUtils.getProxyUrl(client.getConfiguration())); + try (KubernetesClient client = factory.createClient()) { + Config configuration = client.getConfiguration(); + assertEquals("http://proxy.com:123", configuration.getHttpProxy()); + assertEquals(PROXY_USERNAME, configuration.getProxyUsername()); + assertEquals(PROXY_PASSWORD, configuration.getProxyPassword()); + assertArrayEquals(new String[] {"acme.com"}, configuration.getNoProxy()); + assertEquals("http://proxy.com:123", configuration.getHttpsProxy()); } factory = new KubernetesFactoryAdapter("http://k8s.acme.com", null, null, null, false, 15, 5, 32, true); - try(KubernetesClient client = factory.createClient()) { - assertNull(HttpClientUtils.getProxyUrl(client.getConfiguration())); + try (KubernetesClient client = factory.createClient()) { + Config configuration = client.getConfiguration(); + assertEquals("http://proxy.com:123", configuration.getHttpProxy()); + assertEquals(PROXY_USERNAME, configuration.getProxyUsername()); + assertEquals(PROXY_PASSWORD, configuration.getProxyPassword()); + assertArrayEquals(new String[] {"acme.com"}, configuration.getNoProxy()); + assertEquals("http://proxy.com:123", configuration.getHttpsProxy()); } j.jenkins.setProxy(new ProxyConfiguration("proxy.com", 123, PROXY_USERNAME, PROXY_PASSWORD, "*.acme.com")); factory = new KubernetesFactoryAdapter("http://acme.com", null, null, null, false, 15, 5, 32, true); - try(KubernetesClient client = factory.createClient()) { - assertNotNull(HttpClientUtils.getProxyUrl(client.getConfiguration())); + try (KubernetesClient client = factory.createClient()) { + Config configuration = client.getConfiguration(); + assertEquals("http://proxy.com:123", configuration.getHttpProxy()); + assertEquals(PROXY_USERNAME, configuration.getProxyUsername()); + assertEquals(PROXY_PASSWORD, configuration.getProxyPassword()); + assertArrayEquals(new String[] {".acme.com"}, configuration.getNoProxy()); + assertEquals("http://proxy.com:123", configuration.getHttpsProxy()); } factory = new KubernetesFactoryAdapter("http://k8s.acme.com", null, null, null, false, 15, 5, 32, true); - try(KubernetesClient client = factory.createClient()) { - assertNull(HttpClientUtils.getProxyUrl(client.getConfiguration())); + try (KubernetesClient client = factory.createClient()) { + Config configuration = client.getConfiguration(); + assertEquals("http://proxy.com:123", configuration.getHttpProxy()); + assertEquals(PROXY_USERNAME, configuration.getProxyUsername()); + assertEquals(PROXY_PASSWORD, configuration.getProxyPassword()); + assertArrayEquals(new String[] {".acme.com"}, configuration.getNoProxy()); + assertEquals("http://proxy.com:123", configuration.getHttpsProxy()); } } } From e1880488703d883801b83252d2013592480eaa48 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 23 Jun 2023 17:03:37 +0200 Subject: [PATCH 07/19] Update kubernetes-client to 6.7.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f3a175de01..9ad15e4d3f 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.jenkins-ci.plugins kubernetes-client-api - 6.5.1-216.vf0729f27532b_ + 6.7.2-218.v9d6ca_7fa_cfb_6 org.jenkins-ci.plugins From c77f398a9b789234fa8452ef0f055aab6630a322 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 23 Jun 2023 17:59:53 +0200 Subject: [PATCH 08/19] Handle absence of project volume --- .../plugins/kubernetes/PodTemplateUtils.java | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java index 3d68f1a261..a54006a4d5 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java @@ -627,26 +627,28 @@ public static Pod parseFromYaml(String yaml) { } } - private static void fixOctal(Pod podFromYaml) { + private static void fixOctal(@NonNull Pod podFromYaml) { podFromYaml.getSpec().getVolumes().stream() .map(Volume::getProjected) .forEach(projected -> { - Integer defaultMode = projected.getDefaultMode(); - if (defaultMode != null) { - projected.setDefaultMode(convertToOctal(defaultMode)); + if (projected != null) { + Integer defaultMode = projected.getDefaultMode(); + if (defaultMode != null) { + projected.setDefaultMode(convertToOctal(defaultMode)); + } + projected.getSources() + .stream() + .forEach(source -> { + ConfigMapProjection configMap = source.getConfigMap(); + if (configMap != null) { + convertDecimalIntegersToOctal(configMap.getItems()); + } + SecretProjection secret = source.getSecret(); + if (secret != null) { + convertDecimalIntegersToOctal(secret.getItems()); + } + }); } - projected.getSources() - .stream() - .forEach(source -> { - ConfigMapProjection configMap = source.getConfigMap(); - if (configMap != null) { - convertDecimalIntegersToOctal(configMap.getItems()); - } - SecretProjection secret = source.getSecret(); - if (secret != null) { - convertDecimalIntegersToOctal(secret.getItems()); - } - }); }); } From 06591e0937b0f679a444c0674685269bdc69a3f7 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Wed, 16 Aug 2023 17:42:25 +0200 Subject: [PATCH 09/19] Update to 6.8.1 --- pom.xml | 4 ++-- .../plugins/kubernetes/PodTemplateBuilder.java | 10 +++------- .../jenkins/plugins/kubernetes/PodTemplateUtils.java | 4 ++-- .../plugins/kubernetes/PodTemplateUtilsTest.java | 12 ++++-------- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index e53d764861..20ee1911ca 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.jenkins-ci.plugins kubernetes-client-api - 6.7.2-218.v9d6ca_7fa_cfb_6 + 6.8.1-220.v1f66736f9a_42 org.jenkins-ci.plugins @@ -235,7 +235,7 @@ io.fabric8 kubernetes-server-mock - 6.5.1 + 6.8.1 test diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java index b0e789dc94..ebee925705 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java @@ -42,13 +42,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Util; -import io.fabric8.kubernetes.api.model.PodSpecFluent; import org.apache.commons.lang.StringUtils; import org.csanchez.jenkins.plugins.kubernetes.model.TemplateEnvVar; import org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution; @@ -69,8 +67,6 @@ import io.fabric8.kubernetes.api.model.LocalObjectReference; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodBuilder; -import io.fabric8.kubernetes.api.model.PodFluent.MetadataNested; -import io.fabric8.kubernetes.api.model.PodFluent.SpecNested; import io.fabric8.kubernetes.api.model.Probe; import io.fabric8.kubernetes.api.model.ProbeBuilder; import io.fabric8.kubernetes.api.model.Quantity; @@ -221,7 +217,7 @@ public Pod build() { createContainer(containerTemplate, template.getEnvVars(), volumeMounts.values())); } - MetadataNested metadataBuilder = new PodBuilder().withNewMetadata(); + var metadataBuilder = new PodBuilder().withNewMetadata(); if (agent != null) { metadataBuilder.withName(agent.getPodName()); } @@ -240,7 +236,7 @@ public Pod build() { metadataBuilder.withAnnotations(annotations); } - SpecNested builder = metadataBuilder.endMetadata().withNewSpec(); + var builder = metadataBuilder.endMetadata().withNewSpec(); if (template.getActiveDeadlineSeconds() > 0) { builder = builder.withActiveDeadlineSeconds(Long.valueOf(template.getActiveDeadlineSeconds())); @@ -276,7 +272,7 @@ public Pod build() { Long runAsGroup = template.getRunAsGroupAsLong(); String supplementalGroups = template.getSupplementalGroups(); if (runAsUser != null || runAsGroup != null || supplementalGroups != null) { - PodSpecFluent.SecurityContextNested> securityContext = builder.editOrNewSecurityContext(); + var securityContext = builder.editOrNewSecurityContext(); if (runAsUser != null) { securityContext.withRunAsUser(runAsUser); } diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java index a54006a4d5..8650b250e8 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java @@ -295,7 +295,7 @@ public static Pod combine(Pod parent, Pod template) { // toolLocationNodeProperties.addAll(parent.getNodeProperties()); // toolLocationNodeProperties.addAll(template.getNodeProperties()); - MetadataNested metadataBuilder = new PodBuilder(parent).withNewMetadataLike(parent.getMetadata()) // + var metadataBuilder = new PodBuilder(parent).withNewMetadataLike(parent.getMetadata()) // .withAnnotations(podAnnotations).withLabels(podLabels); if (!isNullOrEmpty(template.getMetadata().getName())) { metadataBuilder.withName(template.getMetadata().getName()); @@ -304,7 +304,7 @@ public static Pod combine(Pod parent, Pod template) { metadataBuilder.withNamespace(template.getMetadata().getNamespace()); } - SpecNested specBuilder = metadataBuilder.endMetadata() // + var specBuilder = metadataBuilder.endMetadata() // .withNewSpecLike(parent.getSpec()) // .withNodeSelector(nodeSelector) // .withServiceAccount(serviceAccount) // diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java index 24e6919ee6..e4912d68cb 100644 --- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java +++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java @@ -540,10 +540,6 @@ public void shouldCombineAllMounts() { assertThat(result.getVolumes(), containsInAnyOrder(hostPathVolume1, hostPathVolume2, hostPathVolume3, hostPathVolume4)); } - private SpecNested podBuilder() { - return new PodBuilder().withNewMetadata().endMetadata().withNewSpec(); - } - private ContainerBuilder containerBuilder() { Map limitMap = new HashMap<>(); limitMap.put("cpu", new Quantity()); @@ -567,9 +563,9 @@ public void shouldCombineAllPodMounts() { VolumeMount vm4 = new VolumeMountBuilder().withMountPath("/host/mnt1").withName("volume-4").withReadOnly(false) .build(); Container container1 = containerBuilder().withName("jnlp").withVolumeMounts(vm1, vm2).build(); - Pod pod1 = podBuilder().withContainers(container1).endSpec().build(); + Pod pod1 = new PodBuilder().withNewMetadata().endMetadata().withNewSpec().withContainers(container1).endSpec().build(); Container container2 = containerBuilder().withName("jnlp").withVolumeMounts(vm3, vm4).build(); - Pod pod2 = podBuilder().withContainers(container2).endSpec().build(); + Pod pod2 = new PodBuilder().withNewMetadata().endMetadata().withNewSpec().withContainers(container2).endSpec().build(); Pod result = combine(pod1, pod2); List containers = result.getSpec().getContainers(); @@ -648,12 +644,12 @@ public void shouldCombineAllResources() { public void shouldCombineContainersInOrder() { Container container1 = containerBuilder().withName("mysql").build(); Container container2 = containerBuilder().withName("jnlp").build(); - Pod pod1 = podBuilder().withContainers(container1, container2).endSpec().build(); + Pod pod1 = new PodBuilder().withNewMetadata().endMetadata().withNewSpec().withContainers(container1, container2).endSpec().build(); Container container3 = containerBuilder().withName("alpine").build(); Container container4 = containerBuilder().withName("node").build(); Container container5 = containerBuilder().withName("mvn").build(); - Pod pod2 = podBuilder().withContainers(container3, container4, container5).endSpec().build(); + Pod pod2 = new PodBuilder().withNewMetadata().endMetadata().withNewSpec().withContainers(container3, container4, container5).endSpec().build(); Pod result = combine(pod1, pod2); assertEquals(Arrays.asList("mysql", "jnlp", "alpine", "node", "mvn"), result.getSpec().getContainers().stream().map(Container::getName).collect(Collectors.toList())); From 32f2225060e69800457bccc2b923b21a96812aee Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Thu, 24 Aug 2023 10:49:35 +0200 Subject: [PATCH 10/19] Spotbugs is stupid --- src/spotbugs/excludesFilter.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/spotbugs/excludesFilter.xml diff --git a/src/spotbugs/excludesFilter.xml b/src/spotbugs/excludesFilter.xml new file mode 100644 index 0000000000..fc39a01caf --- /dev/null +++ b/src/spotbugs/excludesFilter.xml @@ -0,0 +1,10 @@ + + + + + + + From c711b6e571190767619f1b3632403d44d66ec5fa Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 25 Aug 2023 08:48:59 +0200 Subject: [PATCH 11/19] Use kubernetes-credentials incrementals build --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0e27566dc3..f22a88c88a 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,8 @@ org.jenkinsci.plugins kubernetes-credentials - 0.10.0 + + 0.10.1-rc150.f62dc9ee1361 org.jenkins-ci.plugins From c7dc8ffd8037e45dcff129197fb95d9f34154ba2 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 25 Aug 2023 09:15:34 +0200 Subject: [PATCH 12/19] Update dependencies --- pom.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f22a88c88a..abc8524052 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,9 @@ - 2.387.3 + 2.401.1 + 2.401.x + 2357.v1043f8578392 false true jenkinsci/${project.artifactId}-plugin @@ -255,8 +257,8 @@ io.jenkins.tools.bom - bom-2.387.x - 2163.v2d916d90c305 + bom-${bom} + ${bom.version} import pom @@ -265,6 +267,12 @@ mockwebserver 4.9.3 + + io.jenkins.plugins + snakeyaml-api + + 2.1-110.v4960f4074978 + From a3e44e4d4df7fddf3f14cf6a98c3dfaadd24d5f0 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 25 Aug 2023 09:48:53 +0200 Subject: [PATCH 13/19] Fix InjectedTest --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index abc8524052..70143bb5ac 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,7 @@ org.jenkins-ci.plugins authentication-tokens - 1.4 + 1.53.v1c90fd9191a_b_ From 8b373d866d43a4b20ecca37c65b962a08b6e68c9 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Fri, 25 Aug 2023 10:32:39 +0200 Subject: [PATCH 14/19] Closing a watch seems async now. --- pom.xml | 12 ++++++++++++ .../plugins/kubernetes/pod/retention/Reaper.java | 6 +++++- .../plugins/kubernetes/pod/retention/ReaperTest.java | 10 ++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 70143bb5ac..646c331257 100644 --- a/pom.xml +++ b/pom.xml @@ -250,6 +250,18 @@ + + org.awaitility + awaitility + 4.2.0 + test + + + org.hamcrest + hamcrest + + + diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java index 87c2ec0ae0..bac5a73179 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/Reaper.java @@ -240,6 +240,10 @@ boolean isWatchingCloud(String name) { return watchers.get(name) != null; } + public Map getWatchers() { + return watchers; + } + /** * Check if the given cloud pod watcher exists and is still valid. Watchers may become invalid * of the kubernetes client configuration changes. @@ -530,4 +534,4 @@ public void onChange(Saveable o, XmlFile file) { } } } -} \ No newline at end of file +} diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java index a559c02ae1..4e6133060d 100644 --- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java +++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/pod/retention/ReaperTest.java @@ -24,7 +24,9 @@ package org.csanchez.jenkins.plugins.kubernetes.pod.retention; +import static org.awaitility.Awaitility.await; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -452,9 +454,9 @@ public void testCloseWatchersOnShutdown() throws InterruptedException { new Reaper.ReaperShutdownListener().onBeforeShutdown(); // watchers removed - assertFalse(r.isWatchingCloud(cloud.name)); - assertFalse(r.isWatchingCloud(cloud2.name)); - assertFalse(r.isWatchingCloud(cloud3.name)); + await().until(() -> r.isWatchingCloud(cloud.name), is(false)); + await().until(() -> r.isWatchingCloud(cloud2.name), is(false)); + await().until(() -> r.isWatchingCloud(cloud3.name), is(false)); } @Test(timeout = 10_000) @@ -755,7 +757,7 @@ CapturedRequests assertRequestCount(String path, long count) { } CapturedRequests assertRequestCountAtLeast(String path, long count) { - assertThat(path + " count at least", countByPath.getOrDefault(path, 0L), Matchers.greaterThanOrEqualTo(count)); + assertThat(path + " count at least", countByPath.getOrDefault(path, 0L), greaterThanOrEqualTo(count)); return this; } } From d8b62e575b3c2d4693ec1571598ee6c404d8405f Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Mon, 28 Aug 2023 19:00:40 +0200 Subject: [PATCH 15/19] Bump workflow-api to pick up https://github.com/jenkinsci/workflow-api-plugin/pull/304 --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 646c331257..e5ebe13328 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,7 @@ org.jenkins-ci.plugins.workflow workflow-api + 1267.vd9b_a_ddd9eb_47 org.jenkinsci.plugins From 9c8fbdfd197180ab83ab38fd12106ca9bdebf760 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Tue, 29 Aug 2023 10:31:49 +0200 Subject: [PATCH 16/19] Remove snakeyaml-api dependency --- pom.xml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index e5ebe13328..9ad1b30cdf 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ org.jenkins-ci.plugins kubernetes-client-api - 6.8.1-220.v1f66736f9a_42 + 6.8.1-223.vefe792551b_b_d org.jenkins-ci.plugins @@ -280,12 +280,6 @@ mockwebserver 4.9.3 - - io.jenkins.plugins - snakeyaml-api - - 2.1-110.v4960f4074978 - From dc2971c40f83cac0a8242f2148e650fbd6ef76b7 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Tue, 29 Aug 2023 11:00:20 +0200 Subject: [PATCH 17/19] Update kubernetes-credentials --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9ad1b30cdf..47130cb7a8 100644 --- a/pom.xml +++ b/pom.xml @@ -81,8 +81,8 @@ org.jenkinsci.plugins kubernetes-credentials - - 0.10.1-rc150.f62dc9ee1361 + + 0.10.1-rc152.837cce3529e6 org.jenkins-ci.plugins From cee099290814102d610c635b1fb1371a65109bf4 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Tue, 29 Aug 2023 15:29:00 +0200 Subject: [PATCH 18/19] Apply suggestions from code review --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 47130cb7a8..e7dc384a35 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ org.jenkins-ci.plugins kubernetes-client-api - 6.8.1-223.vefe792551b_b_d + 6.8.1-224.vd388fca_4db_3b_ org.jenkins-ci.plugins From a3a6df87c06f9a578a7b96eaa0f0be3768d6a63c Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Tue, 29 Aug 2023 15:49:58 +0200 Subject: [PATCH 19/19] Upgrade to kubernetes-credentials release --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e7dc384a35..5df5d12df2 100644 --- a/pom.xml +++ b/pom.xml @@ -81,8 +81,7 @@ org.jenkinsci.plugins kubernetes-credentials - - 0.10.1-rc152.837cce3529e6 + 0.11 org.jenkins-ci.plugins