Skip to content

Commit 19244b0

Browse files
authored
Merge branch 'master' into parallel-ci
2 parents fd9d13e + bb60083 commit 19244b0

File tree

13 files changed

+272
-28
lines changed

13 files changed

+272
-28
lines changed

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesFactoryAdapter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.csanchez.jenkins.plugins.kubernetes;
22

33

4+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
45
import java.util.Base64;
56
import java.util.Collections;
67
import java.util.logging.Logger;
@@ -18,7 +19,6 @@
1819

1920
import io.fabric8.kubernetes.client.Config;
2021
import io.fabric8.kubernetes.client.ConfigBuilder;
21-
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
2222
import io.fabric8.kubernetes.client.KubernetesClient;
2323
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuth;
2424
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthConfig;
@@ -144,7 +144,10 @@ public KubernetesClient createClient() throws KubernetesAuthException {
144144
}
145145
}
146146
}
147-
return new DefaultKubernetesClient(builder.build());
147+
// TODO post 2.362 use jenkins.util.SetContextClassLoader
148+
try (WithContextClassLoader ignored = new WithContextClassLoader(getClass().getClassLoader())) {
149+
return new KubernetesClientBuilder().withConfig(builder.build()).build();
150+
}
148151
}
149152
private String getProxyPasswordDecrypted(ProxyConfiguration p) {
150153
String passwordEncrypted = p.getPassword();
@@ -184,4 +187,5 @@ private static StandardCredentials resolveCredentials(@CheckForNull String crede
184187
}
185188
return c;
186189
}
190+
187191
}

src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
import io.fabric8.kubernetes.api.model.Toleration;
5555
import io.fabric8.kubernetes.api.model.Volume;
5656
import io.fabric8.kubernetes.api.model.VolumeMount;
57-
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
5857
import io.fabric8.kubernetes.client.KubernetesClient;
58+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
5959
import io.fabric8.kubernetes.client.KubernetesClientException;
6060

6161
import static hudson.Util.replaceMacro;
@@ -599,7 +599,8 @@ public static String substitute(String s, Map<String, String> properties, String
599599

600600
public static Pod parseFromYaml(String yaml) {
601601
String s = yaml;
602-
try (KubernetesClient client = new DefaultKubernetesClient()) {
602+
try (WithContextClassLoader ignored = new WithContextClassLoader(PodTemplateUtils.class.getClassLoader());
603+
KubernetesClient client = new KubernetesClientBuilder().build()) {
603604
// JENKINS-57116
604605
if (StringUtils.isBlank(s)) {
605606
LOGGER.log(Level.WARNING, "[JENKINS-57116] Trying to parse invalid yaml: \"{0}\"", yaml);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.csanchez.jenkins.plugins.kubernetes;
2+
3+
// TODO post 2.362 use jenkins.util.SetContextClassLoader
4+
class WithContextClassLoader implements AutoCloseable {
5+
6+
private final ClassLoader previousClassLoader;
7+
8+
public WithContextClassLoader(ClassLoader classLoader) {
9+
this.previousClassLoader = Thread.currentThread().getContextClassLoader();
10+
Thread.currentThread().setContextClassLoader(classLoader);
11+
}
12+
13+
@Override
14+
public void close() {
15+
Thread.currentThread().setContextClassLoader(previousClassLoader);
16+
}
17+
}

src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesTestUtil.java

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,31 @@
2323
*/
2424
package org.csanchez.jenkins.plugins.kubernetes;
2525

26-
import static java.util.logging.Level.*;
27-
import static org.junit.Assume.*;
26+
import static java.util.logging.Level.FINE;
27+
import static java.util.logging.Level.INFO;
28+
import static java.util.logging.Level.WARNING;
29+
import static org.junit.Assert.assertNotNull;
30+
import static org.junit.Assert.assertTrue;
31+
import static org.junit.Assume.assumeNoException;
32+
import static org.junit.Assume.assumeTrue;
2833

2934
import edu.umd.cs.findbugs.annotations.CheckForNull;
35+
import hudson.Util;
36+
import io.fabric8.kubernetes.api.model.NamespaceBuilder;
37+
import io.fabric8.kubernetes.api.model.Node;
38+
import io.fabric8.kubernetes.api.model.PodList;
39+
import io.fabric8.kubernetes.api.model.Secret;
40+
import io.fabric8.kubernetes.api.model.SecretBuilder;
41+
import io.fabric8.kubernetes.client.Config;
42+
import io.fabric8.kubernetes.client.ConfigBuilder;
43+
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
44+
import io.fabric8.kubernetes.client.KubernetesClient;
45+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
46+
import io.fabric8.kubernetes.client.KubernetesClientException;
47+
import io.fabric8.kubernetes.client.utils.Serialization;
3048
import java.io.IOException;
49+
import java.net.InetAddress;
50+
import java.net.URL;
3151
import java.util.Collections;
3252
import java.util.HashMap;
3353
import java.util.List;
@@ -40,32 +60,15 @@
4060
import java.util.logging.Logger;
4161
import java.util.stream.Collectors;
4262
import java.util.stream.IntStream;
43-
44-
import hudson.Util;
63+
import jenkins.model.Jenkins;
64+
import jenkins.model.JenkinsLocationConfiguration;
4565
import org.apache.commons.compress.utils.IOUtils;
4666
import org.apache.commons.lang.StringUtils;
4767
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
4868
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
4969
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
5070
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
5171
import org.junit.rules.TestName;
52-
53-
import io.fabric8.kubernetes.api.model.NamespaceBuilder;
54-
import io.fabric8.kubernetes.api.model.Node;
55-
import io.fabric8.kubernetes.api.model.PodList;
56-
import io.fabric8.kubernetes.api.model.Secret;
57-
import io.fabric8.kubernetes.api.model.SecretBuilder;
58-
import io.fabric8.kubernetes.client.Config;
59-
import io.fabric8.kubernetes.client.ConfigBuilder;
60-
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
61-
import io.fabric8.kubernetes.client.KubernetesClient;
62-
import io.fabric8.kubernetes.client.KubernetesClientException;
63-
import io.fabric8.kubernetes.client.utils.Serialization;
64-
import java.net.InetAddress;
65-
import java.net.URL;
66-
import jenkins.model.Jenkins;
67-
import jenkins.model.JenkinsLocationConfiguration;
68-
import static org.junit.Assert.*;
6972
import org.jvnet.hudson.test.JenkinsRule;
7073

7174
public class KubernetesTestUtil {
@@ -139,8 +142,7 @@ public static void setupHost(KubernetesCloud cloud) throws Exception {
139142
}
140143

141144
public static void assumeKubernetes() throws Exception {
142-
try (DefaultKubernetesClient client = new DefaultKubernetesClient(
143-
new ConfigBuilder(Config.autoConfigure(null)).build())) {
145+
try (KubernetesClient client = new KubernetesClientBuilder().build()) {
144146
client.pods().list();
145147
} catch (Exception e) {
146148
assumeNoException(e);
@@ -158,7 +160,7 @@ public static void assumeWindows(String buildNumber) {
158160
}
159161

160162
public static boolean isWindows(@CheckForNull String buildNumber) {
161-
try (KubernetesClient client = new DefaultKubernetesClient(new ConfigBuilder(Config.autoConfigure(null)).build())) {
163+
try (KubernetesClient client = new KubernetesClientBuilder().build()) {
162164
for (Node n : client.nodes().list().getItems()) {
163165
Map<String, String> labels = n.getMetadata().getLabels();
164166
String os = labels.get("kubernetes.io/os");
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline;
2+
3+
import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.assumeKubernetes;
4+
5+
import org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil;
6+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.CreateWorkflowJobThenScheduleRun;
7+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.RunId;
8+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.SetupCloud;
9+
import org.junit.Before;
10+
import org.junit.BeforeClass;
11+
import org.junit.Rule;
12+
import org.junit.rules.TestName;
13+
import org.jvnet.hudson.test.RealJenkinsRule;
14+
15+
public abstract class AbstractKubernetesPipelineRJRTest {
16+
17+
@Rule
18+
public TestName name = new TestName();
19+
20+
@Rule
21+
public RealJenkinsRule rjr = new RealJenkinsRule();
22+
23+
protected RunId runId;
24+
25+
private SetupCloud setup;
26+
27+
public AbstractKubernetesPipelineRJRTest(SetupCloud setup) {
28+
this.setup = setup;
29+
}
30+
31+
@BeforeClass
32+
public static void isKubernetesConfigured() throws Exception {
33+
assumeKubernetes();
34+
}
35+
36+
@Before
37+
public void setUp() throws Throwable {
38+
rjr.startJenkins();
39+
rjr.runRemotely(setup);
40+
runId = rjr.runRemotely(new CreateWorkflowJobThenScheduleRun(KubernetesTestUtil.loadPipelineScript(getClass(), name.getMethodName() + ".groovy")));
41+
}
42+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline;
2+
3+
import java.net.UnknownHostException;
4+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.AssertBuildStatusSuccess;
5+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.SetupCloud;
6+
import org.junit.Ignore;
7+
import org.junit.Test;
8+
9+
public class KubernetesPipelineRJRTest extends AbstractKubernetesPipelineRJRTest {
10+
public KubernetesPipelineRJRTest() throws UnknownHostException {
11+
super(new SetupCloud());
12+
}
13+
14+
@Test
15+
@Ignore // Need RealJenkinsRule to accept a custom port
16+
public void basicPipeline() throws Throwable {
17+
rjr.runRemotely(new AssertBuildStatusSuccess(runId));
18+
}
19+
}
20+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline;
2+
3+
import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.assumeKubernetes;
4+
5+
import java.net.UnknownHostException;
6+
import org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil;
7+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.AssertBuildStatusSuccess;
8+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.CreateWorkflowJobThenScheduleRun;
9+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.RunId;
10+
import org.csanchez.jenkins.plugins.kubernetes.pipeline.steps.SetupCloud;
11+
import org.junit.Before;
12+
import org.junit.BeforeClass;
13+
import org.junit.Ignore;
14+
import org.junit.Rule;
15+
import org.junit.Test;
16+
import org.junit.rules.TestName;
17+
import org.jvnet.hudson.test.RealJenkinsRule;
18+
19+
public class KubernetesPipelineWebsocketRJRTest extends AbstractKubernetesPipelineRJRTest{
20+
21+
public KubernetesPipelineWebsocketRJRTest() throws UnknownHostException {
22+
super(new SetupCloud(true));
23+
}
24+
@Test
25+
@Ignore // Need RealJenkinsRule to accept a custom port
26+
public void basicPipeline() throws Throwable {
27+
rjr.runRemotely(new AssertBuildStatusSuccess(runId));
28+
}
29+
30+
}
31+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline.steps;
2+
3+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
4+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
5+
import org.jvnet.hudson.test.JenkinsRule;
6+
import org.jvnet.hudson.test.RealJenkinsRule;
7+
8+
public class AssertBuildStatusSuccess implements RealJenkinsRule.Step {
9+
private RunId runId;
10+
11+
public AssertBuildStatusSuccess(RunId runId) {
12+
this.runId = runId;
13+
}
14+
15+
@Override
16+
public void run(JenkinsRule r) throws Throwable {
17+
WorkflowJob p = r.jenkins.getItemByFullName(runId.name, WorkflowJob.class);
18+
WorkflowRun b = p.getBuildByNumber(runId.number);
19+
r.assertBuildStatusSuccess(r.waitForCompletion(b));
20+
}
21+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline.steps;
2+
3+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
4+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
5+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
6+
import org.jvnet.hudson.test.JenkinsRule;
7+
import org.jvnet.hudson.test.RealJenkinsRule;
8+
9+
/**
10+
* Creates a workflow job using the specified script, then schedules it and returns a reference to the run.
11+
*/
12+
public class CreateWorkflowJobThenScheduleRun implements RealJenkinsRule.Step2<RunId> {
13+
private String script;
14+
15+
public CreateWorkflowJobThenScheduleRun(String script) {
16+
this.script = script;
17+
}
18+
19+
@Override
20+
public RunId run(JenkinsRule r) throws Throwable {
21+
WorkflowJob project = r.createProject(WorkflowJob.class);
22+
project.setDefinition(new CpsFlowDefinition(script, true));
23+
project.save();
24+
WorkflowRun b = project.scheduleBuild2(0).get();
25+
return new RunId(project.getFullName(), b.number);
26+
}
27+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline.steps;
2+
3+
import java.io.Serializable;
4+
5+
/**
6+
* Lightweight, serializable reference to a run which can be passed around steps.
7+
*/
8+
public class RunId implements Serializable {
9+
String name;
10+
int number;
11+
12+
RunId(String name, int number) {
13+
this.name = name;
14+
this.number = number;
15+
}
16+
17+
public String getName() {
18+
return name;
19+
}
20+
21+
public int getNumber() {
22+
return number;
23+
}
24+
}

0 commit comments

Comments
 (0)