diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java index 8e7352ba8184f..49d64e6e45251 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/AppCDSBuildStep.java @@ -29,7 +29,7 @@ import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem; import io.quarkus.deployment.steps.MainClassBuildStep; import io.quarkus.runtime.LaunchMode; -import io.quarkus.runtime.util.ContainerRuntimeUtil; +import io.quarkus.runtime.util.ContainerRuntimeUtil.ContainerRuntime; import io.quarkus.utilities.JavaBinFinder; public class AppCDSBuildStep { @@ -39,7 +39,6 @@ public class AppCDSBuildStep { public static final String CLASSES_LIST_FILE_NAME = "classes.lst"; private static final String CONTAINER_IMAGE_BASE_BUILD_DIR = "/tmp/quarkus"; private static final String CONTAINER_IMAGE_APPCDS_DIR = CONTAINER_IMAGE_BASE_BUILD_DIR + "/appcds"; - public static final ContainerRuntimeUtil.ContainerRuntime CONTAINER_RUNTIME = detectContainerRuntime(false); @BuildStep(onlyIf = AppCDSRequired.class) public void requested(OutputTargetBuildItem outputTarget, BuildProducer producer) @@ -204,12 +203,10 @@ private Path createClassesList(JarBuildItem jarResult, // generate the classes file on the host private List dockerRunCommands(OutputTargetBuildItem outputTarget, String containerImage, String containerWorkingDir) { - if (CONTAINER_RUNTIME == ContainerRuntimeUtil.ContainerRuntime.UNAVAILABLE) { - throw new IllegalStateException("No container runtime was found. " - + "Make sure you have either Docker or Podman installed in your environment."); - } + ContainerRuntime containerRuntime = detectContainerRuntime(true); + List command = new ArrayList<>(10); - command.add(CONTAINER_RUNTIME.getExecutableName()); + command.add(containerRuntime.getExecutableName()); command.add("run"); command.add("-v"); command.add(outputTarget.getOutputDirectory().toAbsolutePath().toString() + ":" + CONTAINER_IMAGE_BASE_BUILD_DIR diff --git a/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunnerTest.java b/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunnerTest.java index 4fc2f9698b783..498130d4b71ac 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunnerTest.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunnerTest.java @@ -1,6 +1,5 @@ package io.quarkus.deployment.pkg.steps; -import static io.quarkus.deployment.pkg.steps.AppCDSBuildStep.CONTAINER_RUNTIME; import static org.assertj.core.api.Assertions.assertThat; import java.nio.file.Path; @@ -19,10 +18,8 @@ class NativeImageBuildContainerRunnerTest { @DisabledIfSystemProperty(named = "avoid-containers", matches = "true") @Test void testBuilderImageBeingPickedUp() { - if (CONTAINER_RUNTIME == ContainerRuntimeUtil.ContainerRuntime.UNAVAILABLE) { - throw new IllegalStateException("No container runtime was found. " - + "Make sure you have either Docker or Podman installed in your environment."); - } + ContainerRuntimeUtil.ContainerRuntime containerRuntime = ContainerRuntimeUtil.detectContainerRuntime(true); + NativeConfig nativeConfig = new NativeConfig(); nativeConfig.containerRuntime = Optional.empty(); boolean found; @@ -31,7 +28,7 @@ void testBuilderImageBeingPickedUp() { nativeConfig.builderImage = "graalvm"; localRunner = new NativeImageBuildLocalContainerRunner(nativeConfig, Path.of("/tmp")); - command = localRunner.buildCommand(CONTAINER_RUNTIME.getExecutableName(), Collections.emptyList(), + command = localRunner.buildCommand(containerRuntime.getExecutableName(), Collections.emptyList(), Collections.emptyList()); found = false; for (String part : command) { @@ -44,7 +41,7 @@ void testBuilderImageBeingPickedUp() { nativeConfig.builderImage = "mandrel"; localRunner = new NativeImageBuildLocalContainerRunner(nativeConfig, Path.of("/tmp")); - command = localRunner.buildCommand(CONTAINER_RUNTIME.getExecutableName(), Collections.emptyList(), + command = localRunner.buildCommand(containerRuntime.getExecutableName(), Collections.emptyList(), Collections.emptyList()); found = false; for (String part : command) { @@ -57,7 +54,7 @@ void testBuilderImageBeingPickedUp() { nativeConfig.builderImage = "RandomString"; localRunner = new NativeImageBuildLocalContainerRunner(nativeConfig, Path.of("/tmp")); - command = localRunner.buildCommand(CONTAINER_RUNTIME.getExecutableName(), Collections.emptyList(), + command = localRunner.buildCommand(containerRuntime.getExecutableName(), Collections.emptyList(), Collections.emptyList()); found = false; for (String part : command) { diff --git a/core/runtime/src/main/java/io/quarkus/runtime/util/ContainerRuntimeUtil.java b/core/runtime/src/main/java/io/quarkus/runtime/util/ContainerRuntimeUtil.java index 9ac79ff44719a..2be3cbf76bdaa 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/util/ContainerRuntimeUtil.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/util/ContainerRuntimeUtil.java @@ -5,9 +5,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; +import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -19,18 +17,14 @@ public final class ContainerRuntimeUtil { private static final Logger log = Logger.getLogger(ContainerRuntimeUtil.class); - private static final String DOCKER_EXECUTABLE = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class) + private static final String CONTAINER_EXECUTABLE = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class) .getOptionalValue("quarkus.native.container-runtime", String.class).orElse(null); - /* - * Caching the value in a file helps us only as much as one JVM execution is concerned. - * Test suite's pom.xml sets things like -Djava.io.tmpdir="${project.build.directory}", - * so the file could appear in /tmp/ or C:\Users\karm\AppData\Local\Temp\ or in fact in - * quarkus/integration-tests/something/target. - * There is no point in reaching it in `Path.of(Paths.get("").toAbsolutePath().toString(), "target", - * "quarkus_container_runtime.txt")` - * as the file is deleted between JVM executions anyway. + + /** + * Static variable is not used because the class gets loaded by different classloaders at + * runtime and the container runtime would be detected again and again unnecessarily. */ - static final Path CONTAINER_RUNTIME = Path.of(System.getProperty("java.io.tmpdir"), "quarkus_container_runtime.txt"); + private static final String CONTAINER_RUNTIME_SYS_PROP = "quarkus-local-container-runtime"; private ContainerRuntimeUtil() { } @@ -47,86 +41,85 @@ public static ContainerRuntime detectContainerRuntime() { } public static ContainerRuntime detectContainerRuntime(boolean required) { - final ContainerRuntime containerRuntime = loadConfig(); + final ContainerRuntime containerRuntime = loadContainerRuntimeFromSystemProperty(); if (containerRuntime != null) { return containerRuntime; } else { // Docker version 19.03.14, build 5eb3275d40 - final String dockerVersionOutput = getVersionOutputFor(ContainerRuntime.DOCKER); - boolean dockerAvailable = dockerVersionOutput.contains("Docker version"); + String dockerVersionOutput; + boolean dockerAvailable; // Check if Podman is installed // podman version 2.1.1 - final String podmanVersionOutput = getVersionOutputFor(ContainerRuntime.PODMAN); - boolean podmanAvailable = podmanVersionOutput.startsWith("podman version"); - if (DOCKER_EXECUTABLE != null) { - if (DOCKER_EXECUTABLE.trim().equalsIgnoreCase("docker") && dockerAvailable) { - storeConfig(ContainerRuntime.DOCKER); - return ContainerRuntime.DOCKER; - } else if (DOCKER_EXECUTABLE.trim().equalsIgnoreCase("podman") && podmanAvailable) { - storeConfig(ContainerRuntime.PODMAN); - return ContainerRuntime.PODMAN; - } else { - log.warn("quarkus.native.container-runtime config property must be set to either podman or docker " + - "and the executable must be available. Ignoring it."); + String podmanVersionOutput; + boolean podmanAvailable; + if (CONTAINER_EXECUTABLE != null) { + if (CONTAINER_EXECUTABLE.trim().equalsIgnoreCase("docker")) { + dockerVersionOutput = getVersionOutputFor(ContainerRuntime.DOCKER); + dockerAvailable = dockerVersionOutput.contains("Docker version"); + if (dockerAvailable) { + storeContainerRuntimeInSystemProperty(ContainerRuntime.DOCKER); + return ContainerRuntime.DOCKER; + } } + if (CONTAINER_EXECUTABLE.trim().equalsIgnoreCase("podman")) { + podmanVersionOutput = getVersionOutputFor(ContainerRuntime.PODMAN); + podmanAvailable = podmanVersionOutput.startsWith("podman version"); + if (podmanAvailable) { + storeContainerRuntimeInSystemProperty(ContainerRuntime.PODMAN); + return ContainerRuntime.PODMAN; + } + } + log.warn("quarkus.native.container-runtime config property must be set to either podman or docker " + + "and the executable must be available. Ignoring it."); } + dockerVersionOutput = getVersionOutputFor(ContainerRuntime.DOCKER); + dockerAvailable = dockerVersionOutput.contains("Docker version"); if (dockerAvailable) { // Check if "docker" is an alias to "podman" - if (dockerVersionOutput.equals(podmanVersionOutput)) { - storeConfig(ContainerRuntime.PODMAN); + if (dockerVersionOutput.startsWith("podman version")) { + storeContainerRuntimeInSystemProperty(ContainerRuntime.PODMAN); return ContainerRuntime.PODMAN; } - storeConfig(ContainerRuntime.DOCKER); + storeContainerRuntimeInSystemProperty(ContainerRuntime.DOCKER); return ContainerRuntime.DOCKER; - } else if (podmanAvailable) { - storeConfig(ContainerRuntime.PODMAN); + } + podmanVersionOutput = getVersionOutputFor(ContainerRuntime.PODMAN); + podmanAvailable = podmanVersionOutput.startsWith("podman version"); + if (podmanAvailable) { + storeContainerRuntimeInSystemProperty(ContainerRuntime.PODMAN); return ContainerRuntime.PODMAN; - } else { - if (required) { - throw new IllegalStateException("No container runtime was found. " - + "Make sure you have either Docker or Podman installed in your environment."); - } else { - storeConfig(ContainerRuntime.UNAVAILABLE); - return ContainerRuntime.UNAVAILABLE; - } } + + storeContainerRuntimeInSystemProperty(ContainerRuntime.UNAVAILABLE); + + if (required) { + throw new IllegalStateException("No container runtime was found. " + + "Make sure you have either Docker or Podman installed in your environment."); + } + + return ContainerRuntime.UNAVAILABLE; } } - private static ContainerRuntime loadConfig() { - try { - if (Files.isReadable(CONTAINER_RUNTIME)) { - final String runtime = Files.readString(CONTAINER_RUNTIME, StandardCharsets.UTF_8); - if (ContainerRuntime.DOCKER.name().equalsIgnoreCase(runtime)) { - return ContainerRuntime.DOCKER; - } else if (ContainerRuntime.PODMAN.name().equalsIgnoreCase(runtime)) { - return ContainerRuntime.PODMAN; - } else if (ContainerRuntime.UNAVAILABLE.name().equalsIgnoreCase(runtime)) { - return ContainerRuntime.UNAVAILABLE; - } else { - log.warnf("The file %s contains an unknown value %s. Ignoring it.", - CONTAINER_RUNTIME.toAbsolutePath(), runtime); - return null; - } - } else { - return null; - } - } catch (IOException e) { - log.warnf("Error reading file %s. Ignoring it. See: %s", - CONTAINER_RUNTIME.toAbsolutePath(), e); + private static ContainerRuntime loadContainerRuntimeFromSystemProperty() { + final String runtime = System.getProperty(CONTAINER_RUNTIME_SYS_PROP); + + if (runtime == null) { return null; } - } - private static void storeConfig(ContainerRuntime containerRuntime) { - try { - Files.writeString(CONTAINER_RUNTIME, containerRuntime.name(), StandardCharsets.UTF_8, - StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - CONTAINER_RUNTIME.toFile().deleteOnExit(); - } catch (IOException e) { - log.warnf("Error writing to file %s. Ignoring it. See: %s", - CONTAINER_RUNTIME.toAbsolutePath(), e); + ContainerRuntime containerRuntime = ContainerRuntime.valueOf(runtime); + + if (containerRuntime == null) { + log.warnf("System property %s contains an unknown value %s. Ignoring it.", + CONTAINER_RUNTIME_SYS_PROP, runtime); } + + return containerRuntime; + } + + private static void storeContainerRuntimeInSystemProperty(ContainerRuntime containerRuntime) { + System.setProperty(CONTAINER_RUNTIME_SYS_PROP, containerRuntime.name()); } private static String getVersionOutputFor(ContainerRuntime containerRuntime) { @@ -135,8 +128,14 @@ private static String getVersionOutputFor(ContainerRuntime containerRuntime) { final ProcessBuilder pb = new ProcessBuilder(containerRuntime.getExecutableName(), "--version") .redirectErrorStream(true); versionProcess = pb.start(); - versionProcess.waitFor(); - return new String(versionProcess.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + final int timeoutS = 10; + if (versionProcess.waitFor(timeoutS, TimeUnit.SECONDS)) { + return new String(versionProcess.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + } else { + log.debugf("Failure. It took command %s more than %d seconds to execute.", containerRuntime.getExecutableName(), + timeoutS); + return ""; + } } catch (IOException | InterruptedException e) { // If an exception is thrown in the process, just return an empty String log.debugf(e, "Failure to read version output from %s", containerRuntime.getExecutableName()); @@ -200,6 +199,10 @@ public enum ContainerRuntime { private Boolean rootless; public String getExecutableName() { + if (this == UNAVAILABLE) { + throw new IllegalStateException("Cannot get an executable name when no container runtime is available"); + } + return this.name().toLowerCase(); } @@ -216,5 +219,15 @@ public boolean isRootless() { } return rootless; } + + public static ContainerRuntime of(String value) { + for (ContainerRuntime containerRuntime : values()) { + if (containerRuntime.name().equalsIgnoreCase(value)) { + return containerRuntime; + } + } + + return null; + } } } diff --git a/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java index 99d5420a51d92..6e10784ef2a04 100644 --- a/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java +++ b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerConfig.java @@ -50,9 +50,10 @@ public class DockerConfig { /** * Name of binary used to execute the docker commands. + * This setting can override the global container runtime detection. */ - @ConfigItem(defaultValue = "docker") - public String executableName; + @ConfigItem + public Optional executableName; /** * Configuration for Docker Buildx options diff --git a/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java index f6a5d79ab181d..a3933d6d3faa1 100644 --- a/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java +++ b/extensions/container-image/container-image-docker/deployment/src/main/java/io/quarkus/container/image/docker/deployment/DockerProcessor.java @@ -4,6 +4,7 @@ import static io.quarkus.container.image.deployment.util.EnablementUtil.buildContainerImageNeeded; import static io.quarkus.container.image.deployment.util.EnablementUtil.pushContainerImageNeeded; import static io.quarkus.container.util.PathsUtil.findMainSourcesRoot; +import static io.quarkus.runtime.util.ContainerRuntimeUtil.detectContainerRuntime; import java.io.BufferedReader; import java.io.IOException; @@ -87,9 +88,10 @@ public void dockerBuildFromJar(DockerConfig dockerConfig, throw new RuntimeException("Unable to build docker image. Please check your docker installation"); } - var dockerfilePaths = getDockerfilePaths(dockerConfig, false, packageConfig, out); - var dockerFileBaseInformationProvider = DockerFileBaseInformationProvider.impl(); - var dockerFileBaseInformation = dockerFileBaseInformationProvider.determine(dockerfilePaths.getDockerfilePath()); + DockerfilePaths dockerfilePaths = getDockerfilePaths(dockerConfig, false, packageConfig, out); + DockerFileBaseInformationProvider dockerFileBaseInformationProvider = DockerFileBaseInformationProvider.impl(); + Optional dockerFileBaseInformation = dockerFileBaseInformationProvider + .determine(dockerfilePaths.getDockerfilePath()); if ((compiledJavaVersion.getJavaVersion().isJava17OrHigher() == CompiledJavaVersionBuildItem.JavaVersion.Status.TRUE) && dockerFileBaseInformation.isPresent() && (dockerFileBaseInformation.get().getJavaVersion() < 17)) { @@ -168,11 +170,11 @@ private String createContainerImage(ContainerImageConfig containerImageConfig, D boolean pushContainerImage, PackageConfig packageConfig) { - var useBuildx = dockerConfig.buildx.useBuildx(); + boolean useBuildx = dockerConfig.buildx.useBuildx(); - // useBuildx: Whether or not any of the buildx parameters are set + // useBuildx: Whether any of the buildx parameters are set // - // pushImages: Whether or not the user requested the built images to be pushed to a registry + // pushImages: Whether the user requested the built images to be pushed to a registry // Pushing images is different based on if you're using buildx or not. // If not using any of the buildx params (useBuildx == false), then the flow is as it was before: // @@ -196,12 +198,13 @@ private String createContainerImage(ContainerImageConfig containerImageConfig, D } if (buildContainerImage) { - log.infof("Executing the following command to build docker image: '%s %s'", dockerConfig.executableName, + final String executableName = dockerConfig.executableName.orElse(detectContainerRuntime(true).getExecutableName()); + log.infof("Executing the following command to build docker image: '%s %s'", executableName, String.join(" ", dockerArgs)); - boolean buildSuccessful = ExecUtil.exec(out.getOutputDirectory().toFile(), reader, dockerConfig.executableName, + boolean buildSuccessful = ExecUtil.exec(out.getOutputDirectory().toFile(), reader, executableName, dockerArgs); if (!buildSuccessful) { - throw dockerException(dockerArgs); + throw dockerException(executableName, dockerArgs); } dockerConfig.buildx.platform @@ -234,7 +237,7 @@ private String createContainerImage(ContainerImageConfig containerImageConfig, D private void loginToRegistryIfNeeded(ContainerImageConfig containerImageConfig, ContainerImageInfoBuildItem containerImageInfo, DockerConfig dockerConfig) { - var registry = containerImageInfo.getRegistry() + String registry = containerImageInfo.getRegistry() .orElseGet(() -> { log.info("No container image registry was set, so 'docker.io' will be used"); return "docker.io"; @@ -242,11 +245,13 @@ private void loginToRegistryIfNeeded(ContainerImageConfig containerImageConfig, // Check if we need to login first if (containerImageConfig.username.isPresent() && containerImageConfig.password.isPresent()) { - boolean loginSuccessful = ExecUtil.exec(dockerConfig.executableName, "login", registry, "-u", + final String executableName = dockerConfig.executableName.orElse(detectContainerRuntime(true).getExecutableName()); + boolean loginSuccessful = ExecUtil.exec(executableName, "login", registry, "-u", containerImageConfig.username.get(), "-p" + containerImageConfig.password.get()); if (!loginSuccessful) { - throw dockerException(new String[] { "-u", containerImageConfig.username.get(), "-p", "********" }); + throw dockerException(executableName, + new String[] { "-u", containerImageConfig.username.get(), "-p", "********" }); } } } @@ -254,15 +259,17 @@ private void loginToRegistryIfNeeded(ContainerImageConfig containerImageConfig, private String[] getDockerArgs(String image, DockerfilePaths dockerfilePaths, ContainerImageConfig containerImageConfig, DockerConfig dockerConfig, ContainerImageInfoBuildItem containerImageInfo, boolean pushImages) { List dockerArgs = new ArrayList<>(6 + dockerConfig.buildArgs.size()); - var useBuildx = dockerConfig.buildx.useBuildx(); + boolean useBuildx = dockerConfig.buildx.useBuildx(); if (useBuildx) { + final String executableName = dockerConfig.executableName.orElse(detectContainerRuntime(true).getExecutableName()); // Check the executable. If not 'docker', then fail the build - if (!DOCKER.equals(dockerConfig.executableName)) { + if (!DOCKER.equals(executableName)) { throw new IllegalArgumentException( String.format( - "The 'buildx' properties are specific to 'executable-name=docker' and can not be used with the '%s' executable name. Either remove the `buildx` properties or the `executable-name` property.", - dockerConfig.executableName)); + "The 'buildx' properties are specific to 'executable-name=docker' and can not be used with " + + "the '%s' executable name. Either remove the `buildx` properties or the `executable-name` property.", + executableName)); } dockerArgs.add("buildx"); @@ -315,27 +322,30 @@ private String[] getDockerArgs(String image, DockerfilePaths dockerfilePaths, Co } private void createAdditionalTags(String image, List additionalImageTags, DockerConfig dockerConfig) { + final String executableName = dockerConfig.executableName.orElse(detectContainerRuntime(true).getExecutableName()); for (String additionalTag : additionalImageTags) { String[] tagArgs = { "tag", image, additionalTag }; - boolean tagSuccessful = ExecUtil.exec(dockerConfig.executableName, tagArgs); + boolean tagSuccessful = ExecUtil.exec(executableName, tagArgs); if (!tagSuccessful) { - throw dockerException(tagArgs); + throw dockerException(executableName, tagArgs); } } } private void pushImage(String image, DockerConfig dockerConfig) { + final String executableName = dockerConfig.executableName.orElse(detectContainerRuntime(true).getExecutableName()); String[] pushArgs = { "push", image }; - boolean pushSuccessful = ExecUtil.exec(dockerConfig.executableName, pushArgs); + boolean pushSuccessful = ExecUtil.exec(executableName, pushArgs); if (!pushSuccessful) { - throw dockerException(pushArgs); + throw dockerException(executableName, pushArgs); } log.info("Successfully pushed docker image " + image); } - private RuntimeException dockerException(String[] dockerArgs) { + private RuntimeException dockerException(String executableName, String[] dockerArgs) { return new RuntimeException( - "Execution of 'docker " + String.join(" ", dockerArgs) + "' failed. See docker output for more details"); + "Execution of '" + executableName + " " + String.join(" ", dockerArgs) + + "' failed. See docker output for more details"); } private DockerfilePaths getDockerfilePaths(DockerConfig dockerConfig, boolean forNative, @@ -464,7 +474,7 @@ public static ProvidedDockerfile get(Path dockerfilePath, Path outputDirectory) : mainSourcesRoot.getValue().resolve(dockerfilePath); if (!effectiveDockerfilePath.toFile().exists()) { throw new IllegalArgumentException( - "Specified Dockerfile path " + effectiveDockerfilePath.toAbsolutePath().toString() + " does not exist"); + "Specified Dockerfile path " + effectiveDockerfilePath.toAbsolutePath() + " does not exist"); } return new ProvidedDockerfile( effectiveDockerfilePath, diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java index e9987475c21f0..a721afa2ba601 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java @@ -52,6 +52,7 @@ import io.quarkus.paths.PathList; import io.quarkus.runtime.configuration.ProfileManager; import io.quarkus.runtime.logging.LoggingSetupRecorder; +import io.quarkus.runtime.util.ContainerRuntimeUtil; import io.quarkus.test.common.ArtifactLauncher; import io.quarkus.test.common.LauncherUtil; import io.quarkus.test.common.PathTestHelper; @@ -64,7 +65,6 @@ public final class IntegrationTestUtil { public static final int DEFAULT_PORT = 8081; public static final int DEFAULT_HTTPS_PORT = 8444; public static final long DEFAULT_WAIT_TIME_SECONDS = 60; - private static final String DOCKER_BINARY = detectContainerRuntime().getExecutableName(); private IntegrationTestUtil() { } @@ -336,9 +336,13 @@ public void accept(String s, String s2) { private static void createNetworkIfNecessary( final ArtifactLauncher.InitContext.DevServicesLaunchResult devServicesLaunchResult) { if (devServicesLaunchResult.manageNetwork() && (devServicesLaunchResult.networkId() != null)) { + ContainerRuntimeUtil.ContainerRuntime containerRuntime = detectContainerRuntime(true); + try { int networkCreateResult = new ProcessBuilder().redirectError(DISCARD).redirectOutput(DISCARD) - .command(DOCKER_BINARY, "network", "create", devServicesLaunchResult.networkId()).start().waitFor(); + .command(containerRuntime.getExecutableName(), "network", "create", + devServicesLaunchResult.networkId()) + .start().waitFor(); if (networkCreateResult > 0) { throw new RuntimeException("Creating container network '" + devServicesLaunchResult.networkId() + "' completed unsuccessfully"); @@ -349,7 +353,9 @@ private static void createNetworkIfNecessary( public void run() { try { new ProcessBuilder().redirectError(DISCARD).redirectOutput(DISCARD) - .command(DOCKER_BINARY, "network", "rm", devServicesLaunchResult.networkId()).start() + .command(containerRuntime.getExecutableName(), "network", "rm", + devServicesLaunchResult.networkId()) + .start() .waitFor(); } catch (InterruptedException | IOException ignored) { System.out.println(