From f606866f592b308365869863583edb281974e964 Mon Sep 17 00:00:00 2001 From: strangelookingnerd <49242855+strangelookingnerd@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:36:40 +0200 Subject: [PATCH] Replace docker-fixtures with testcontainers --- pom.xml | 6 +- .../plugins/workflow/ArtifactManagerTest.java | 59 ++++++------------- .../workflow/ArtifactManagerTest/Dockerfile | 25 ++++++++ 3 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 src/test/resources/org/jenkinsci/plugins/workflow/ArtifactManagerTest/Dockerfile diff --git a/pom.xml b/pom.xml index 89405fb0..a2cbfb66 100644 --- a/pom.xml +++ b/pom.xml @@ -123,9 +123,9 @@ test - org.jenkins-ci.test - docker-fixtures - 200.v22a_e8766731c + org.testcontainers + testcontainers + 1.21.3 test diff --git a/src/test/java/org/jenkinsci/plugins/workflow/ArtifactManagerTest.java b/src/test/java/org/jenkinsci/plugins/workflow/ArtifactManagerTest.java index 141ac8e8..7713f7af 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/ArtifactManagerTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/ArtifactManagerTest.java @@ -58,7 +58,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; @@ -74,14 +73,14 @@ import jenkins.util.VirtualFile; import org.apache.commons.io.IOUtils; import org.jenkinsci.plugins.workflow.flow.StashManager; -import org.jenkinsci.test.acceptance.docker.Docker; -import org.jenkinsci.test.acceptance.docker.DockerImage; -import org.jenkinsci.test.acceptance.docker.fixtures.JavaContainer; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.LoggerRule; +import org.testcontainers.DockerClientFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; /** * {@link #artifactArchiveAndDelete} and variants allow an implementation of {@link ArtifactManager} plus {@link VirtualFile} to be run through a standard gantlet of tests. @@ -90,21 +89,18 @@ public class ArtifactManagerTest { @Rule public JenkinsRule r = new JenkinsRule(); @Rule public LoggerRule logging = new LoggerRule(); - - private static DockerImage image; - - @BeforeClass public static void doPrepareImage() throws Exception { - image = prepareImage(); + + private static GenericContainer container; + + @BeforeClass public static void doPrepareImage() { + container = prepareImage(); } - /** - * @deprecated Not actually used externally. - */ - @Deprecated - public static @CheckForNull DockerImage prepareImage() throws Exception { - Docker docker = new Docker(); - if (!Functions.isWindows() && docker.isAvailable()) { // TODO: Windows agents on ci.jenkins.io have Docker, but cannot build the image. - return docker.build(JavaContainer.class); + public static @CheckForNull GenericContainer prepareImage() { + if (!Functions.isWindows() && DockerClientFactory.instance().isDockerAvailable()) { // TODO: Windows agents on ci.jenkins.io have Docker, but cannot build the image. + return new GenericContainer<>(new ImageFromDockerfile("java17-ssh", false) + .withFileFromClasspath("Dockerfile", ArtifactManagerTest.class.getName().replace('.', '/') + "/Dockerfile")) + .withExposedPorts(22); } else { System.err.println("No Docker support; falling back to running tests against an agent in a process on the same machine."); return null; @@ -119,14 +115,13 @@ private static void wrapInContainer(@NonNull JenkinsRule r, @CheckForNull Artifa if (factory != null) { ArtifactManagerConfiguration.get().getArtifactManagerFactories().add(factory); } - JavaContainer runningContainer = null; try { DumbSlave agent; - if (image != null) { - runningContainer = image.start(JavaContainer.class).start(); + if (container != null) { + container.start(); StandardUsernameCredentials creds = new UsernamePasswordCredentialsImpl(CredentialsScope.SYSTEM, "test", "desc", "test", "test"); CredentialsProvider.lookupStores(Jenkins.get()).iterator().next().addCredentials(Domain.global(), creds); - agent = new DumbSlave("test-agent", "/home/test/slave", new SSHLauncher(runningContainer.ipBound(22), runningContainer.port(22), "test")); + agent = new DumbSlave("test-agent", "/home/test/slave", new SSHLauncher(container.getHost(), container.getMappedPort(22), "test")); Jenkins.get().addNode(agent); r.waitOnline(agent); } else { @@ -142,8 +137,8 @@ private static void wrapInContainer(@NonNull JenkinsRule r, @CheckForNull Artifa FreeStyleBuild b = r.buildAndAssertSuccess(p); f.apply(agent, p, b, ws); } finally { - if (runningContainer != null) { - runningContainer.close(); + if (container != null) { + container.stop(); } } } @@ -161,10 +156,6 @@ public static void artifactArchive(@NonNull JenkinsRule r, @CheckForNull Artifac assertTrue(b.getArtifactManager().root().child("file").isFile()); }); } - @Deprecated - public static void artifactArchive(@NonNull JenkinsRule r, @CheckForNull ArtifactManagerFactory factory, boolean weirdCharacters, @CheckForNull DockerImage image) throws Exception { - artifactArchive(r, factory, weirdCharacters); - } /** * Test artifact archiving in a plain manager. @@ -180,10 +171,6 @@ public static void artifactArchiveAndDelete(@NonNull JenkinsRule r, @CheckForNul assertFalse(b.getArtifactManager().delete()); }); } - @Deprecated - public static void artifactArchiveAndDelete(@NonNull JenkinsRule r, @CheckForNull ArtifactManagerFactory factory, boolean weirdCharacters, @CheckForNull DockerImage image) throws Exception { - artifactArchiveAndDelete(r, factory, weirdCharacters); - } /** * Test stashing and unstashing with a {@link StashManager.StashAwareArtifactManager} that does not honor deletion requests. @@ -197,10 +184,6 @@ public static void artifactStash(@NonNull JenkinsRule r, @CheckForNull ArtifactM assertTrue(ws.child("file").exists()); })); } - @Deprecated - public static void artifactStash(@NonNull JenkinsRule r, @CheckForNull ArtifactManagerFactory factory, boolean weirdCharacters, @CheckForNull DockerImage image) throws Exception { - artifactStash(r, factory, weirdCharacters); - } /** * Test stashing and unstashing with a {@link StashManager.StashAwareArtifactManager} with standard behavior. @@ -218,10 +201,6 @@ public static void artifactStashAndDelete(@NonNull JenkinsRule r, @CheckForNull assertFalse(ws.child("file").exists()); })); } - @Deprecated - public static void artifactStashAndDelete(@NonNull JenkinsRule r, @CheckForNull ArtifactManagerFactory factory, boolean weirdCharacters, @CheckForNull DockerImage image) throws Exception { - artifactStashAndDelete(r, factory, weirdCharacters); - } /** * Creates a variety of files in a directory structure designed to exercise interesting aspects of {@link VirtualFile}. @@ -471,7 +450,7 @@ private static void assertNonexistent(VirtualFile f) throws IOException { @Test public void standard() throws Exception { logging.record(StandardArtifactManager.class, Level.FINE); // Who knows about weird characters on NTFS; also case-sensitivity could confuse things - artifactArchiveAndDelete(r, null, !Functions.isWindows(), image); + artifactArchiveAndDelete(r, null, !Functions.isWindows()); } } diff --git a/src/test/resources/org/jenkinsci/plugins/workflow/ArtifactManagerTest/Dockerfile b/src/test/resources/org/jenkinsci/plugins/workflow/ArtifactManagerTest/Dockerfile new file mode 100644 index 00000000..dfcf9c21 --- /dev/null +++ b/src/test/resources/org/jenkinsci/plugins/workflow/ArtifactManagerTest/Dockerfile @@ -0,0 +1,25 @@ +FROM ubuntu:noble + +# install requirements +RUN apt-get update -y && \ + apt-get install --no-install-recommends -y \ + openjdk-17-jdk-headless \ + openssh-server \ + locales + +RUN mkdir -p /var/run/sshd + +# create a test user +RUN useradd test -d /home/test && \ + mkdir -p /home/test/.ssh && \ + chown -R test:test /home/test && \ + echo "test:test" | chpasswd + +# https://stackoverflow.com/a/38553499/12916 +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ + dpkg-reconfigure --frontend=noninteractive locales && \ + update-locale LANG=en_US.UTF-8 +ENV LANG en_US.UTF-8 + +# run SSHD in the foreground with error messages to stderr +ENTRYPOINT ["/usr/sbin/sshd", "-D", "-e"]