From 9311627c8d447010049f07cc367a64754ddad9c0 Mon Sep 17 00:00:00 2001 From: "Richardson, Mark A" Date: Mon, 20 Jan 2025 13:30:38 -0700 Subject: [PATCH] JENKINS-74912 Fix Docker Windows non-C drive mounts --- .../docker/workflow/WithContainerStep.java | 20 +++++++++-- .../workflow/WithContainerStepTest.java | 36 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java b/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java index b3428f7c5..02c86f2da 100644 --- a/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java +++ b/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java @@ -192,8 +192,24 @@ public Execution() { } } else { listener.getLogger().println(node.getDisplayName() + " does not seem to be running inside a container"); - volumes.put(ws, ws); - volumes.put(tmp, tmp); + + if (launcher.isUnix()) { + volumes.put(ws, ws); + volumes.put(tmp, tmp); + } else { + char wsDrive = Character.toUpperCase(ws.charAt(0)); + + if (wsDrive != 'C') { + listener.getLogger().println("Detected workspace on drive '" + wsDrive + "'. Mounting entire drive."); + + // JENKINS-74912 Docker for windows does not support mounting non-root non-C volumes + // Target mount must not end with '/'. Note tmp will be on the same drive. + volumes.put(wsDrive + ":/", wsDrive + ":"); + } else { + volumes.put(ws, ws); + volumes.put(tmp, tmp); + } + } } String command = launcher.isUnix() ? "cat" : "cmd.exe"; diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java index f4cadd884..10d65b1cb 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java @@ -38,6 +38,8 @@ import hudson.util.Secret; import hudson.util.StreamTaskListener; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.Collections; import java.util.logging.Level; @@ -69,6 +71,7 @@ import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; import org.junit.Assume; +import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; import org.junit.ClassRule; import org.junit.Ignore; @@ -515,4 +518,37 @@ private static final class Execution extends SynchronousNonBlockingStepExecution } }); } + + @Issue("JENKINS-74912") + @Test public void windowsRunningWindowsContainerAlternateDriveWorkspace() { + // Run with another drive ("D") if it is mounted + story.addStep(new Statement() { + @Override public void evaluate() throws Throwable { + DockerTestUtil.assumeWindows(); + DockerTestUtil.assumeDocker(DockerTestUtil.DockerOsMode.WINDOWS); + DockerTestUtil.assumeDrive('D'); + + // Manually create instead of using a Rule since not all executions will have the D drive mounted + Path tempDir = Files.createTempDirectory(Path.of("D:/"), "j ws"); + tempDir.toFile().deleteOnExit(); + + // Kernel must match when running Windows containers on docker on Windows + String releaseTag = DockerTestUtil.getWindowsImageTag(); + + WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + p.setDefinition(new CpsFlowDefinition( + "node {\n" + + " ws('" + tempDir.toString().replace("\\", "\\\\") + "') {\n" + + " withDockerContainer('mcr.microsoft.com/windows/nanoserver:" + releaseTag + "') { \n" + + " bat 'echo bar > foo.txt' \n" + + " bat 'echo ran OK' \n" + + " }\n" + + " }\n" + + "}", true)); + WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + story.j.assertLogContains("ran OK", b); + assertTrue("Mounted workspace contains foo.txt", tempDir.resolve("foo.txt").toFile().exists()); + } + }); + } }