Skip to content

Commit 2a9b72c

Browse files
committed
Disable by default; introduce dedicated test class; tone down logging
1 parent 3ca3f27 commit 2a9b72c

8 files changed

Lines changed: 90 additions & 20 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ public class KubernetesCloud extends Cloud implements PodTemplateGroup {
174174
private GarbageCollection garbageCollection;
175175

176176
/** @see ContainerListenDecorator */
177-
private boolean activeContainers = true; // TODO do not enable by default
177+
private boolean activeContainers;
178178

179179
@NonNull
180180
private DescribableList<KubernetesCloudTrait, KubernetesCloudTraitDescriptor> traits =

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ final class ContainerListenDecorator extends LauncherDecorator implements Serial
7272
@Override
7373
public Launcher decorate(Launcher launcher, Node node) {
7474
if (!launcher.isUnix()) {
75-
LOGGER.info(() -> "TODO using original implementation on Windows " + node.getNodeName());
75+
LOGGER.fine(() -> "using original implementation on Windows " + node.getNodeName());
7676
return fallback.decorate(launcher, node);
7777
}
7878
if (!(node instanceof KubernetesSlave ks)) {
@@ -109,7 +109,7 @@ public Launcher decorate(Launcher launcher, Node node) {
109109
x,
110110
() -> "Could not verify eligibility of container " + container + " in " + ks.getPodName());
111111
}
112-
LOGGER.info(() -> "TODO prepping launcher for " + container + " in " + ks.getPodName());
112+
LOGGER.finer(() -> "prepping launcher for " + container + " in " + ks.getPodName());
113113
return new LauncherImpl(launcher, ks, pod);
114114
}
115115

@@ -142,7 +142,7 @@ private class LauncherImpl extends Launcher.DecoratedLauncher {
142142
@Override
143143
public Proc launch(Launcher.ProcStarter starter) throws IOException {
144144
if (!isUnix()) {
145-
throw new AbortException("TODO Windows not yet supported");
145+
throw new AbortException("Windows not yet supported");
146146
}
147147
FilePath procDir;
148148
try {
@@ -157,7 +157,7 @@ public Proc launch(Launcher.ProcStarter starter) throws IOException {
157157
if (!bootstrap.exists()) {
158158
work.mkdirs();
159159
bootstrap.copyFrom(ContainerListenDecorator.class.getResource("scripts/container-bootstrap.sh"));
160-
LOGGER.info("TODO created " + bootstrap);
160+
LOGGER.fine(() -> "created " + bootstrap);
161161
}
162162
procDir = work.child(container)
163163
.child("%016x".formatted(RandomGenerator.getDefault().nextLong()));
@@ -186,7 +186,7 @@ public Proc launch(Launcher.ProcStarter starter) throws IOException {
186186
.findFirst()
187187
.orElse(null);
188188
if (workspaceToContainer != null && !workspaceToContainer.equals(workspaceToAgent)) {
189-
LOGGER.info("TODO translating " + workspaceToAgent + " to " + workspaceToContainer);
189+
LOGGER.fine(() -> "translating " + workspaceToAgent + " to " + workspaceToContainer);
190190
if (pwd.startsWith(workspaceToAgent + "/")) {
191191
pwd = workspaceToContainer + pwd.substring(workspaceToAgent.length());
192192
}
@@ -225,7 +225,7 @@ public Proc launch(Launcher.ProcStarter starter) throws IOException {
225225
sb.append(" ");
226226
}
227227
f.write(sb.toString(), null);
228-
LOGGER.info("TODO wrote to " + f + ": \n" + sb);
228+
LOGGER.fine(() -> "wrote to " + f + ": \n" + sb);
229229
if (!starter.quiet()) {
230230
maskedPrintCommandLine(
231231
cmds, starter.masks(), pwd != null ? new FilePath(pwdF.getChannel(), pwd) : null);
@@ -248,17 +248,20 @@ public void kill() throws IOException, InterruptedException {
248248
@Override
249249
public int join() throws IOException, InterruptedException {
250250
var status = procDir.child("status.txt");
251-
LOGGER.info("TODO waiting for " + status);
251+
LOGGER.fine(() -> "waiting for " + status);
252252
while (!status.exists()) {
253253
Thread.sleep(100);
254254
}
255+
var r = Integer.parseInt(status.readToString().trim());
255256
// No streaming supported, just logging/capturing of stdio from a completed process.
256257
// In practice most steps are durable, which produce no stdio themselves;
257258
// or relatively brief and so streaming is unnecessary.
258-
LOGGER.info("TODO " + procDir + " completed with status "
259-
+ status.readToString().trim() + " and stdout "
260-
+ procDir.child("out.txt").length() + "b stderr"
261-
+ procDir.child("err.txt").length() + "b");
259+
if (LOGGER.isLoggable(Level.FINE)) {
260+
LOGGER.fine(procDir + " completed with status "
261+
+ status.readToString().trim() + " and stdout "
262+
+ procDir.child("out.txt").length() + "b stderr"
263+
+ procDir.child("err.txt").length() + "b");
264+
}
262265
var os = starter.stdout();
263266
if (os == null) {
264267
os = getListener().getLogger();
@@ -269,7 +272,6 @@ public int join() throws IOException, InterruptedException {
269272
os = getListener().getLogger();
270273
}
271274
procDir.child("err.txt").copyTo(new CloseProofOutputStream(os));
272-
var r = Integer.parseInt(status.readToString().trim());
273275
procDir.deleteRecursive();
274276
return r;
275277
}
@@ -340,7 +342,6 @@ public static final class Decorator implements PodDecorator {
340342
@Override
341343
public Pod decorate(KubernetesCloud kubernetesCloud, Pod pod) {
342344
if (kubernetesCloud.isActiveContainers()) {
343-
// TODO exclude Windows
344345
for (var c : pod.getSpec().getContainers()) {
345346
var cmds = c.getCommand();
346347
if (cmds != null && !cmds.isEmpty() && cmds.get(0).matches("((/usr)?/bin/)?(sleep|cat)")) {

src/main/resources/org/csanchez/jenkins/plugins/kubernetes/KubernetesCloud/config.jelly

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ THE SOFTWARE.
122122
<f:optionalProperty field="garbageCollection" title="${%Enable garbage collection}"/>
123123

124124
<f:entry title="${%Use active containers}" field="activeContainers">
125-
<f:checkbox default="true"/> <!-- TODO do not enable by default -->
125+
<f:checkbox/>
126126
</f:entry>
127127

128128
<f:descriptorList field="traits" descriptors="${descriptor.allTraits}" />

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.junit.jupiter.api.BeforeAll;
5858
import org.junit.jupiter.api.BeforeEach;
5959
import org.junit.jupiter.api.TestInfo;
60+
import org.junit.jupiter.api.extension.RegisterExtension;
6061
import org.jvnet.hudson.test.JenkinsRule;
6162
import org.jvnet.hudson.test.LogRecorder;
6263
import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
@@ -68,7 +69,7 @@ public abstract class AbstractKubernetesPipelineTest {
6869
protected static final String POD_ENV_VAR_VALUE = "pod-env-var-value";
6970
protected static final String GLOBAL = "GLOBAL";
7071

71-
@SuppressWarnings("unused")
72+
@RegisterExtension
7273
protected static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
7374

7475
protected KubernetesCloud cloud;

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import static org.hamcrest.MatcherAssert.assertThat;
2020
import static org.hamcrest.Matchers.containsString;
2121
import static org.junit.jupiter.api.Assertions.*;
22-
import static org.junit.jupiter.api.Assumptions.assumeFalse;
2322

2423
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey;
2524
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.PrivateKeySource;
@@ -97,7 +96,6 @@ void docker() throws Exception {
9796
@Issue("JENKINS-58290")
9897
@Test
9998
void closedWebSocketExit() throws Exception {
100-
assumeFalse(cloud.isActiveContainers());
10199
assertNotNull(createJobThenScheduleRun());
102100
containerExecLogs.capture(1000);
103101
r.waitForMessage("have started user process", b);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2026 CloudBees, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.csanchez.jenkins.plugins.kubernetes.pipeline;
18+
19+
import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.deletePods;
20+
import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.getLabels;
21+
22+
import java.util.logging.Level;
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Test;
25+
26+
class ContainerListenDecoratorTest extends AbstractKubernetesPipelineTest {
27+
28+
@BeforeEach
29+
void beforeEach() throws Exception {
30+
deletePods(cloud.connect(), getLabels(cloud, this, name), false);
31+
cloud.setActiveContainers(true);
32+
logs.record(ContainerListenDecorator.class, Level.FINE);
33+
}
34+
35+
@Test
36+
void activeContainerSmokes() throws Exception {
37+
r.assertLogContains(
38+
"go version go1.6.3", r.assertBuildStatusSuccess(r.waitForCompletion(createJobThenScheduleRun())));
39+
}
40+
41+
// TODO missing test coverage (compare https://github.com/jenkinsci/kubernetes-plugin/pull/2837/commits):
42+
// · using cat rather than sleep
43+
// · environment variables from agent pod vs. container
44+
// (KubernetesDeclarativeAgentTest#declarative & ContainerExecDecoratorPipelineTest#containerEnvironmentIsHonored)
45+
// · BASH_COMPLIANT_ENV_VAR (KubernetesPipelineTest#runWithEnvVariablesInContext)
46+
// · interrupting sh step (KubernetesPipelineTest#interruptedPod)
47+
// · nonexistent container name (KubernetesDeclarativeAgentTest.declarativeWithNestedExplicitInheritance)
48+
// · unpatched container
49+
// · custom workingDir
50+
// · restart controller during or between sh steps
51+
// · container step used in addition to defaultContainer (so nested steps)
52+
// · command masking (ContainerExecDecoratorPipelineTest.docker)
53+
// · nondefault shell (KubernetesPipelineTest#runInPodWithDifferentShell but a passing build)
54+
// · fallback on Windows
55+
56+
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import static org.hamcrest.Matchers.is;
4343
import static org.hamcrest.Matchers.oneOf;
4444
import static org.junit.jupiter.api.Assertions.*;
45-
import static org.junit.jupiter.api.Assumptions.assumeFalse;
4645
import static org.junit.jupiter.api.Assumptions.assumeTrue;
4746

4847
import edu.umd.cs.findbugs.annotations.NonNull;
@@ -322,7 +321,6 @@ void runInPodWithDifferentShell() throws Exception {
322321
// Completed /home/jenkins/agent/container-work/busybox/1bfd9327891af5c0 with status 127
323322
// The hack used to make this pass in ContainerExecDecorator is unsatisfactory;
324323
// the proper fix should be in BourneShellScript like https://github.com/jenkinsci/durable-task-plugin/pull/561
325-
assumeFalse(cloud.isActiveContainers());
326324
r.assertBuildStatus(Result.FAILURE, r.waitForCompletion(b));
327325
r.assertLogContains("ERROR: Process exited immediately after creation", b);
328326
// r.assertLogContains("/bin/bash: no such file or directory", b); // Not printed in CI for an unknown reason.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
podTemplate(yaml: '''
2+
spec:
3+
containers:
4+
- name: golang
5+
image: golang:1.6.3-alpine
6+
command:
7+
- sleep
8+
args:
9+
- infinity
10+
''') {
11+
node(POD_LABEL) {
12+
container('golang') {
13+
sh 'go version'
14+
}
15+
}
16+
}

0 commit comments

Comments
 (0)