Skip to content

Commit 87f0837

Browse files
authored
Merge pull request #1289 from Vlatombe/JENKINS-70392
2 parents 45d9da3 + be95a48 commit 87f0837

File tree

11 files changed

+265
-25
lines changed

11 files changed

+265
-25
lines changed

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

Lines changed: 20 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,19 @@ private static StandardCredentials resolveCredentials(@CheckForNull String crede
184187
}
185188
return c;
186189
}
190+
191+
private static class WithContextClassLoader implements AutoCloseable {
192+
193+
private final ClassLoader previousClassLoader;
194+
195+
public WithContextClassLoader(ClassLoader classLoader) {
196+
this.previousClassLoader = Thread.currentThread().getContextClassLoader();
197+
Thread.currentThread().setContextClassLoader(classLoader);
198+
}
199+
200+
@Override
201+
public void close() {
202+
Thread.currentThread().setContextClassLoader(previousClassLoader);
203+
}
204+
}
187205
}

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

Lines changed: 25 additions & 23 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);
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+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline.steps;
2+
3+
import java.net.InetAddress;
4+
import java.net.URL;
5+
import java.net.UnknownHostException;
6+
import jenkins.model.JenkinsLocationConfiguration;
7+
import org.apache.commons.lang3.StringUtils;
8+
import org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud;
9+
import org.jvnet.hudson.test.JenkinsRule;
10+
import org.jvnet.hudson.test.RealJenkinsRule;
11+
12+
/**
13+
* Sets up a Kubernetes cloud instance named kubernetes.
14+
*/
15+
public class SetupCloud implements RealJenkinsRule.Step {
16+
private String hostAddress;
17+
private Integer agentPort;
18+
19+
private boolean websocket;
20+
21+
public SetupCloud(boolean websocket) throws UnknownHostException {
22+
hostAddress = StringUtils.defaultIfBlank(System.getProperty("jenkins.host.address"), InetAddress.getLocalHost().getHostAddress());
23+
agentPort = Integer.getInteger("slaveAgentPort");
24+
this.websocket = websocket;
25+
}
26+
27+
public SetupCloud() throws UnknownHostException {
28+
this(false);
29+
}
30+
31+
@Override
32+
public void run(JenkinsRule r) throws Throwable {
33+
KubernetesCloud cloud = new KubernetesCloud("kubernetes");
34+
cloud.setWebSocket(websocket);
35+
r.jenkins.clouds.add(cloud);
36+
// Agents running in Kubernetes (minikube) need to connect to this server, so localhost does not work
37+
URL url = new URL(JenkinsLocationConfiguration.get().getUrl());
38+
System.err.println("Calling home to address: " + hostAddress);
39+
URL nonLocalhostUrl = new URL(url.getProtocol(), hostAddress, url.getPort(), url.getFile());
40+
cloud.setJenkinsUrl(nonLocalhostUrl.toString());
41+
if (agentPort != null) {
42+
r.jenkins.setSlaveAgentPort(agentPort);
43+
}
44+
r.jenkins.save();
45+
}
46+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.csanchez.jenkins.plugins.kubernetes.pipeline.steps;
2+
/**
3+
* Reusable steps for tests relying on RealJenkinsRule.
4+
*/

0 commit comments

Comments
 (0)