Skip to content

Commit 5b1d2a9

Browse files
committed
More compelling test, using a containerized agent
1 parent 3d414a8 commit 5b1d2a9

File tree

2 files changed

+72
-20
lines changed

2 files changed

+72
-20
lines changed

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@
150150
<version>2.2</version>
151151
<scope>test</scope>
152152
</dependency>
153+
<dependency>
154+
<groupId>org.jenkins-ci.plugins</groupId>
155+
<artifactId>ssh-slaves</artifactId>
156+
<scope>test</scope>
157+
</dependency>
158+
<dependency>
159+
<groupId>org.testcontainers</groupId>
160+
<artifactId>testcontainers</artifactId>
161+
<version>1.21.0</version>
162+
<scope>test</scope>
163+
</dependency>
153164
<!-- Required because git plugin optionally depends on a recent version of matrix-project, and if we do not depend
154165
on matrix-project here, an older version is installed automatically as a detached plugin, causing git plugin to fail to load. -->
155166
<dependency>

src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424
package org.jenkinsci.plugins.docker.workflow;
2525

26+
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey;
2627
import com.cloudbees.plugins.credentials.CredentialsProvider;
2728
import com.cloudbees.plugins.credentials.CredentialsScope;
2829
import com.cloudbees.plugins.credentials.common.IdCredentials;
@@ -37,6 +38,9 @@
3738
import hudson.model.Node;
3839
import hudson.model.Result;
3940
import hudson.model.User;
41+
import hudson.plugins.sshslaves.SSHLauncher;
42+
import hudson.slaves.DumbSlave;
43+
import java.io.ByteArrayOutputStream;
4044
import jenkins.model.Jenkins;
4145
import jenkins.security.QueueItemAuthenticatorConfiguration;
4246
import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryEndpoint;
@@ -70,16 +74,21 @@
7074
import java.util.Set;
7175
import java.util.logging.Level;
7276
import org.apache.commons.text.StringEscapeUtils;
77+
import org.apache.sshd.common.config.keys.KeyUtils;
78+
import org.apache.sshd.common.config.keys.writer.openssh.OpenSSHKeyPairResourceWriter;
79+
import org.apache.sshd.common.keyprovider.KeyPairProvider;
7380
import static org.hamcrest.MatcherAssert.assertThat;
7481
import static org.hamcrest.Matchers.containsString;
7582
import static org.hamcrest.Matchers.not;
83+
import static org.jenkinsci.plugins.docker.workflow.DockerTestUtil.assumeDocker;
7684
import org.jenkinsci.plugins.structs.describable.DescribableModel;
7785
import org.jenkinsci.plugins.workflow.support.pickles.FilePathPickle;
7886
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
7987
import org.junit.ClassRule;
8088
import org.jvnet.hudson.test.BuildWatcher;
8189
import org.jvnet.hudson.test.JenkinsSessionRule;
8290
import org.jvnet.hudson.test.LoggerRule;
91+
import org.testcontainers.containers.GenericContainer;
8392

8493
public class RegistryEndpointStepTest {
8594

@@ -200,36 +209,68 @@ public void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throw
200209

201210
@Issue("JENKINS-75679")
202211
@Test public void noFilePathPickle() throws Throwable {
203-
assumeNotWindows();
204-
rr.then(r -> {
205-
var registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "s3cr3t");
206-
CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials);
207-
var p = r.createProject(WorkflowJob.class, "p");
208-
p.setDefinition(new CpsFlowDefinition(
212+
assumeDocker();
213+
try (var agent = new SSHAgentContainer()) {
214+
agent.start();
215+
rr.then(r -> {
216+
agent.register("remote");
217+
var registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "s3cr3t");
218+
CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials);
219+
var p = r.createProject(WorkflowJob.class, "p");
220+
p.setDefinition(new CpsFlowDefinition(
209221
"""
210-
node {
222+
node('remote') {
211223
mockDockerLogin {
212224
withDockerRegistry(url: 'https://my-reg:1234', credentialsId: 'registryCreds') {
213225
semaphore 'wait'
214226
}
215227
}
216228
}
217229
""", true));
218-
var b = p.scheduleBuild2(0).waitForStart();
219-
SemaphoreStep.waitForStart("wait/1", b);
220-
});
221-
@SuppressWarnings("deprecation")
222-
var verboten = FilePathPickle.class.getName();
223-
assertThat(StringEscapeUtils.escapeJava(Files.readString(rr.getHome().toPath().resolve("jobs/p/builds/1/program.dat"), StandardCharsets.ISO_8859_1)), not(containsString(verboten)));
224-
rr.then(r -> {
225-
var b = r.jenkins.getItemByFullName("p", WorkflowJob.class).getBuildByNumber(1);
226-
SemaphoreStep.success("wait/1", null);
227-
r.assertBuildStatusSuccess(r.waitForCompletion(b));
228-
r.assertLogContains("docker login -u me -p ******** https://my-reg:1234", b);
229-
r.assertLogNotContains("s3cr3t", b);
230-
});
230+
var b = p.scheduleBuild2(0).waitForStart();
231+
SemaphoreStep.waitForStart("wait/1", b);
232+
});
233+
@SuppressWarnings("deprecation")
234+
var verboten = FilePathPickle.class.getName();
235+
assertThat(StringEscapeUtils.escapeJava(Files.readString(rr.getHome().toPath().resolve("jobs/p/builds/1/program.dat"), StandardCharsets.ISO_8859_1)), not(containsString(verboten)));
236+
rr.then(r -> {
237+
var b = r.jenkins.getItemByFullName("p", WorkflowJob.class).getBuildByNumber(1);
238+
SemaphoreStep.success("wait/1", null);
239+
r.assertBuildStatusSuccess(r.waitForCompletion(b));
240+
r.assertLogContains("docker login -u me -p ******** https://my-reg:1234", b);
241+
r.assertLogNotContains("s3cr3t", b);
242+
});
243+
}
231244
}
232245

246+
private static final class SSHAgentContainer extends GenericContainer<SSHAgentContainer> {
247+
private final String priv;
248+
SSHAgentContainer() {
249+
super("jenkins/ssh-agent:6.17.0");
250+
try {
251+
var kp = KeyUtils.generateKeyPair(KeyPairProvider.SSH_RSA, 2048);
252+
var kprw = new OpenSSHKeyPairResourceWriter();
253+
var baos = new ByteArrayOutputStream();
254+
kprw.writePublicKey(kp, null, baos);
255+
var pub = baos.toString(StandardCharsets.US_ASCII);
256+
baos.reset();
257+
kprw.writePrivateKey(kp, null, null, baos);
258+
priv = baos.toString(StandardCharsets.US_ASCII);
259+
withEnv("JENKINS_AGENT_SSH_PUBKEY", pub);
260+
withExposedPorts(22);
261+
} catch (Exception x) {
262+
throw new AssertionError(x);
263+
}
264+
}
265+
void register(String name) throws Exception{
266+
var creds = new BasicSSHUserPrivateKey(CredentialsScope.GLOBAL, null, "jenkins", new BasicSSHUserPrivateKey.DirectEntryPrivateKeySource(priv), null, null);
267+
CredentialsProvider.lookupStores(Jenkins.get()).iterator().next().addCredentials(Domain.global(), creds);
268+
var port = getMappedPort(22);
269+
Jenkins.get().addNode(new DumbSlave(name, "/home/jenkins/agent", new SSHLauncher(getHost(), port, creds.getId())));
270+
}
271+
}
272+
273+
233274
public static class MockLauncherStep extends Step {
234275

235276
@DataBoundConstructor

0 commit comments

Comments
 (0)