Skip to content

Commit d5b1bcb

Browse files
authored
Merge pull request #1260 from Vlatombe/kubernetes-client-api-6.x
2 parents d89e521 + 3ea5a9b commit d5b1bcb

File tree

14 files changed

+194
-122
lines changed

14 files changed

+194
-122
lines changed

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
<dependency>
5656
<groupId>org.jenkins-ci.plugins</groupId>
5757
<artifactId>kubernetes-client-api</artifactId>
58-
<version>5.12.1-187.v577c3e368fb_6</version>
58+
<version>6.3.1-206.v76d3b_6b_14db_b</version>
5959
</dependency>
6060
<dependency>
6161
<groupId>org.jenkins-ci.plugins</groupId>
@@ -76,7 +76,7 @@
7676
<dependency>
7777
<groupId>org.jenkinsci.plugins</groupId>
7878
<artifactId>kubernetes-credentials</artifactId>
79-
<version>0.9.0</version>
79+
<version>0.10.0</version>
8080
</dependency>
8181
<dependency>
8282
<groupId>org.jenkins-ci.plugins</groupId>
@@ -235,7 +235,7 @@
235235
<dependency>
236236
<groupId>io.fabric8</groupId>
237237
<artifactId>kubernetes-server-mock</artifactId>
238-
<version>5.12.1</version>
238+
<version>6.3.1</version>
239239
<scope>test</scope>
240240
<exclusions>
241241
<exclusion>

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
import io.fabric8.kubernetes.api.model.Pod;
3636
import io.fabric8.kubernetes.client.KubernetesClient;
3737
import io.fabric8.kubernetes.client.KubernetesClientException;
38-
import io.fabric8.kubernetes.client.KubernetesClientTimeoutException;
39-
import io.fabric8.kubernetes.client.internal.readiness.Readiness;
4038
import jenkins.metrics.api.Metrics;
4139
import org.apache.commons.lang.StringUtils;
4240
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.Reaper;

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

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

33
import edu.umd.cs.findbugs.annotations.NonNull;
4+
import io.fabric8.kubernetes.api.model.StatusDetails;
45
import java.io.IOException;
56
import java.util.HashSet;
7+
import java.util.List;
68
import java.util.Objects;
79
import java.util.Optional;
810
import java.util.Set;
@@ -353,10 +355,8 @@ protected void _terminate(TaskListener listener) throws IOException, Interrupted
353355

354356
private void deleteSlavePod(TaskListener listener, KubernetesClient client) throws IOException {
355357
try {
356-
Boolean deleted = client.pods().inNamespace(getNamespace()).withName(name).
357-
cascading(true). // TODO JENKINS-58306 pending https://github.com/fabric8io/kubernetes-client/pull/1620
358-
delete();
359-
if (!Boolean.TRUE.equals(deleted)) {
358+
boolean deleted = client.pods().inNamespace(getNamespace()).withName(name).delete().size() == 1;
359+
if (!deleted) {
360360
String msg = String.format("Failed to delete pod for agent %s/%s: not found", getNamespace(), name);
361361
LOGGER.log(Level.WARNING, msg);
362362
listener.error(msg);

src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/ContainerExecDecorator.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.csanchez.jenkins.plugins.kubernetes.pipeline;
1818

1919

20+
import io.fabric8.kubernetes.api.model.Status;
2021
import java.io.ByteArrayOutputStream;
2122
import java.io.Closeable;
2223
import java.io.FilterOutputStream;
@@ -44,7 +45,6 @@
4445

4546
import hudson.AbortException;
4647
import io.fabric8.kubernetes.api.model.Container;
47-
import io.fabric8.kubernetes.client.http.WebSocketHandshakeException;
4848
import org.apache.commons.io.output.TeeOutputStream;
4949
import org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate;
5050
import org.csanchez.jenkins.plugins.kubernetes.KubernetesSlave;
@@ -62,7 +62,6 @@
6262
import io.fabric8.kubernetes.client.KubernetesClientException;
6363
import io.fabric8.kubernetes.client.dsl.ExecListener;
6464
import io.fabric8.kubernetes.client.dsl.ExecWatch;
65-
import io.fabric8.kubernetes.client.dsl.Execable;
6665

6766
import static org.csanchez.jenkins.plugins.kubernetes.pipeline.Constants.EXIT;
6867

@@ -375,7 +374,6 @@ private Proc doLaunch(boolean quiet, String[] cmdEnvs, OutputStream outputForCal
375374
stream = new TeeOutputStream(toggleDryRunCaller, stream);
376375
}
377376
}
378-
ByteArrayOutputStream error = new ByteArrayOutputStream();
379377

380378
String[] sh = shell != null ? new String[]{shell} : launcher.isUnix() ? new String[] {"sh"} : new String[] {"cmd", "/Q"};
381379
String msg = "Executing " + String.join(" ", sh) + " script inside container " + containerName + " of pod " + getPodName();
@@ -414,7 +412,6 @@ private Proc doLaunch(boolean quiet, String[] cmdEnvs, OutputStream outputForCal
414412
.redirectingInput(STDIN_BUFFER_SIZE) // JENKINS-50429
415413
.writingOutput(stream)
416414
.writingError(stream)
417-
.writingErrorChannel(error)
418415
.usingListener(new ExecListener() {
419416
@Override
420417
public void onOpen() {
@@ -449,7 +446,6 @@ public void onClose(int i, String s) {
449446
finished.countDown();
450447
}
451448
}).exec(sh);
452-
453449
// prevent a wait forever if the connection is closed as the listener would never be called
454450
try {
455451
if (started.await(WEBSOCKET_CONNECTION_TIMEOUT, TimeUnit.SECONDS)) {
@@ -468,13 +464,10 @@ public void onClose(int i, String s) {
468464

469465
} catch (KubernetesClientException e) {
470466
launcher.getListener().getLogger().print("Failed to start websocket connection: ");
471-
472-
// In case of 400 / Bad Request, do not attempt a retry
473-
if (e.getCause() instanceof WebSocketHandshakeException) {
474-
WebSocketHandshakeException wsException = (WebSocketHandshakeException) e.getCause();
475-
if (wsException.getResponse() != null && wsException.getResponse().code() == 400) {
476-
throw e;
477-
}
467+
String message = e.getMessage();
468+
if (message != null && message.startsWith("container " + containerName + " not found in pod")) {
469+
// Don't even retry if the container is invalid.
470+
throw e;
478471
}
479472

480473
e.printStackTrace(launcher.getListener().getLogger());
@@ -571,7 +564,7 @@ public void onClose(int i, String s) {
571564

572565
LOGGER.log(Level.INFO, "Created process inside pod: [" + getPodName() + "], container: ["
573566
+ containerName + "]" + "[" + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startMethod) + " ms]");
574-
ContainerExecProc proc = new ContainerExecProc(watch, alive, finished, stdin, error);
567+
ContainerExecProc proc = new ContainerExecProc(watch, alive, finished, stdin);
575568
closables.add(proc);
576569
return proc;
577570
} catch (InterruptedException ie) {

src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/ContainerExecProc.java

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
import java.util.logging.Level;
1515
import java.util.logging.Logger;
1616

17-
import com.fasterxml.jackson.databind.JsonNode;
18-
import com.fasterxml.jackson.databind.ObjectMapper;
19-
2017
import hudson.Proc;
2118
import io.fabric8.kubernetes.client.dsl.ExecWatch;
2219
import jenkins.util.Timer;
@@ -36,27 +33,30 @@ public class ContainerExecProc extends Proc implements Closeable, Runnable {
3633
private final CountDownLatch finished;
3734
private final ExecWatch watch;
3835
private final OutputStream stdin;
39-
private final ByteArrayOutputStream error;
4036

4137
@Deprecated
4238
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished,
4339
Callable<Integer> exitCode) {
44-
this(watch, alive, finished, null, new ByteArrayOutputStream());
40+
this(watch, alive, finished, (OutputStream) null);
4541
}
4642

4743
@Deprecated
4844
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished,
4945
ByteArrayOutputStream error) {
50-
this(watch, alive, finished, null, error);
46+
this(watch, alive, finished, (OutputStream) null);
5147
}
5248

49+
@Deprecated
5350
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished, OutputStream stdin,
5451
ByteArrayOutputStream error) {
52+
this(watch, alive, finished, stdin);
53+
}
54+
55+
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished, OutputStream stdin) {
5556
this.watch = watch;
5657
this.stdin = stdin == null ? watch.getInput() : stdin;
5758
this.alive = alive;
5859
this.finished = finished;
59-
this.error = error;
6060
Timer.get().schedule(this, 1, TimeUnit.MINUTES);
6161
}
6262

@@ -86,41 +86,7 @@ public int join() throws IOException, InterruptedException {
8686
LOGGER.log(Level.FINEST, "Waiting for websocket to close on command finish ({0})", finished);
8787
finished.await();
8888
LOGGER.log(Level.FINEST, "Command is finished ({0})", finished);
89-
if (error.size() == 0) {
90-
return 0;
91-
} else {
92-
// {"metadata":{},"status":"Success"}
93-
// or
94-
// {"metadata":{},"status":"Failure",
95-
// "message":"command terminated with non-zero exit code: Error executing in Docker Container: 127",
96-
// "reason":"NonZeroExitCode",
97-
// "details":{"causes":[{"reason":"ExitCode","message":"127"}]}}
98-
try {
99-
ObjectMapper mapper = new ObjectMapper();
100-
JsonNode errorJson = mapper.readTree(error.toByteArray());
101-
if ("Success".equalsIgnoreCase(errorJson.get("status").asText())) {
102-
return 0;
103-
}
104-
JsonNode causes = errorJson.get("details").get("causes");
105-
if (causes.isArray()) {
106-
for (JsonNode cause : causes) {
107-
if ("ExitCode".equalsIgnoreCase(cause.get("reason").asText(""))) {
108-
return cause.get("message").asInt();
109-
}
110-
}
111-
}
112-
LOGGER.log(Level.WARNING, "Unable to parse exit code from error message: {0}",
113-
error.toString(StandardCharsets.UTF_8.name()));
114-
return -1;
115-
} catch (IOException e) {
116-
LOGGER.log(Level.WARNING, "Unable to parse exit code from error message: "
117-
+ error.toString(StandardCharsets.UTF_8.name()), e);
118-
return -1;
119-
}
120-
}
121-
} catch (Exception e) {
122-
LOGGER.log(Level.WARNING, "Error getting exit code", e);
123-
return -1;
89+
return watch.exitCode().join();
12490
} finally {
12591
close();
12692
}

src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/ContainerLogStepExecution.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ protected String run() throws Exception {
7272

7373
String podName = nodeContext.getPodName();
7474

75-
TimeTailPrettyLoggable<LogWatch> limited = limitBytes > 0
75+
TimeTailPrettyLoggable limited = limitBytes > 0
7676
? client.pods() //
7777
.inNamespace(nodeContext.getNamespace()) //
7878
.withName(podName).inContainer(containerName).limitBytes(limitBytes)
7979
: client.pods() //
8080
.inNamespace(nodeContext.getNamespace()) //
8181
.withName(podName).inContainer(containerName);
8282

83-
TailPrettyLoggable<LogWatch> since = sinceSeconds > 0 ? limited.sinceSeconds(sinceSeconds) : limited;
83+
TailPrettyLoggable since = sinceSeconds > 0 ? limited.sinceSeconds(sinceSeconds) : limited;
8484

8585
String log = (tailingLines > 0 ? since.tailingLines(tailingLines) : since).getLog();
8686

src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/SecretsMasker.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import java.util.concurrent.TimeUnit;
4343
import java.util.logging.Level;
4444
import java.util.logging.Logger;
45-
import okhttp3.Response;
4645
import org.csanchez.jenkins.plugins.kubernetes.KubernetesComputer;
4746
import org.csanchez.jenkins.plugins.kubernetes.KubernetesSlave;
4847
import org.csanchez.jenkins.plugins.kubernetes.PodTemplate;

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,7 @@ public static boolean deletePods(KubernetesClient client, Map<String, String> la
239239
PodList list = client.pods().withLabels(labels).list();
240240
if (!list.getItems().isEmpty()) {
241241
LOGGER.log(WARNING, "Deleting leftover pods: {0}", print(list));
242-
if (Boolean.TRUE.equals(client.pods().withLabels(labels).delete())) {
243-
return true;
244-
}
245-
242+
return client.pods().withLabels(labels).delete().size() > 0;
246243
}
247244
}
248245
return false;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,13 @@ public void childShouldOverrideParentInitContainer() {
344344
Pod parentPod = new PodBuilder()
345345
.withNewMetadata().endMetadata()
346346
.withNewSpec()
347-
.withInitContainers(new ContainerBuilder().withName("init").withNewImage("image-parent").build())
347+
.withInitContainers(new ContainerBuilder().withName("init").withImage("image-parent").build())
348348
.endSpec()
349349
.build();
350350
Pod childPod = new PodBuilder()
351351
.withNewMetadata().endMetadata()
352352
.withNewSpec()
353-
.withInitContainers(new ContainerBuilder().withName("init").withNewImage("image-child").build())
353+
.withInitContainers(new ContainerBuilder().withName("init").withImage("image-child").build())
354354
.endSpec()
355355
.build();
356356

src/test/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/ContainerExecDecoratorTest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@
3535
import io.fabric8.kubernetes.api.model.ContainerBuilder;
3636
import io.fabric8.kubernetes.api.model.Pod;
3737
import io.fabric8.kubernetes.api.model.PodBuilder;
38-
import io.fabric8.kubernetes.client.HttpClientAware;
3938
import io.fabric8.kubernetes.client.KubernetesClient;
4039
import io.fabric8.kubernetes.client.KubernetesClientException;
41-
import io.fabric8.kubernetes.client.http.WebSocketHandshakeException;
4240
import org.apache.commons.io.output.TeeOutputStream;
4341
import org.apache.commons.lang.RandomStringUtils;
4442
import org.apache.commons.lang.StringUtils;
@@ -79,7 +77,6 @@
7977
import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.setupCloud;
8078
import static org.hamcrest.MatcherAssert.assertThat;
8179
import static org.hamcrest.Matchers.arrayContaining;
82-
import static org.hamcrest.Matchers.isA;
8380
import static org.junit.Assert.assertEquals;
8481
import static org.junit.Assert.assertFalse;
8582
import static org.junit.Assert.assertTrue;
@@ -112,6 +109,7 @@ public class ContainerExecDecoratorTest {
112109
@Rule
113110
public LoggerRule containerExecLogs = new LoggerRule()
114111
.record(Logger.getLogger(ContainerExecDecorator.class.getName()), Level.ALL) //
112+
.record(ContainerExecProc.class, Level.ALL) //
115113
.record(Logger.getLogger(KubernetesClientProvider.class.getName()), Level.ALL);
116114

117115
@Rule
@@ -331,7 +329,7 @@ public void testCommandExecutionWithNohupAndError() throws Exception {
331329
public void testContainerDoesNotExist() throws Exception {
332330
decorator.setContainerName("doesNotExist");
333331
exception.expect(KubernetesClientException.class);
334-
exception.expectCause(isA(WebSocketHandshakeException.class));
332+
exception.expectMessage("container doesNotExist not found in pod");
335333
execCommand(false, false, "nohup", "sh", "-c", "sleep 5; return 127");
336334
}
337335

@@ -347,7 +345,6 @@ public void testContainerDoesNotExist() throws Exception {
347345
@Test
348346
@Issue("JENKINS-55392")
349347
public void testRejectedExecutionException() throws Exception {
350-
assertTrue(client instanceof HttpClientAware);
351348
List<Thread> threads = new ArrayList<>();
352349
final AtomicInteger errors = new AtomicInteger(0);
353350
for (int i = 0; i < 10; i++) {

0 commit comments

Comments
 (0)