From 7cda685ee6002afae61c6841f3ed0fa412cd0688 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Fri, 21 Jan 2022 16:52:13 +0200 Subject: [PATCH] Allow `mandrel` and `graalvm` as values of `quarkus.native.builder-image` This change makes it easier for developers to choose the variant of the builder image they want to use without having to worry about which version is the currently supported one. Quarkus will figure that out on their behalf. Closes #18129 --- build-parent/pom.xml | 2 +- .../quarkus/deployment/pkg/NativeConfig.java | 22 +++++++- .../NativeImageBuildContainerRunner.java | 8 +-- .../pkg/steps/UpxCompressionBuildStep.java | 4 +- .../deployment/pkg/NativeConfigTest.java | 29 ++++++++++ .../NativeImageBuildContainerRunnerTest.java | 56 +++++++++++++++++++ docs/src/main/asciidoc/platform.adoc | 2 +- 7 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 core/deployment/src/test/java/io/quarkus/deployment/pkg/NativeConfigTest.java create mode 100644 core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunnerTest.java diff --git a/build-parent/pom.xml b/build-parent/pom.xml index 52f86226eaac2..334ecce7a42b5 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -140,7 +140,7 @@ 3.1 - quay.io/quarkus/ubi-quarkus-native-image:21.3-java11 + graalvm sh ${maven.multiModuleProjectDirectory}/.github/docker-prune.${script.extension} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java index 9d1e469b5610e..ab6fd146cbbcd 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/NativeConfig.java @@ -195,11 +195,23 @@ public boolean isContainerBuild() { } /** - * The docker image to use to do the image build + * The docker image to use to do the image build. It can be one of `graalvm`, `mandrel`, or the full image path, e.g. + * {@code quay.io/quarkus/ubi-quarkus-mandrel:21.3-java17}. */ @ConfigItem(defaultValue = "${platform.quarkus.native.builder-image}") public String builderImage; + public String getEffectiveBuilderImage() { + final String builderImageName = this.builderImage.toUpperCase(); + if (builderImageName.equals(BuilderImageProvider.GRAALVM.name())) { + return "quay.io/quarkus/ubi-quarkus-native-image:21.3-java11"; + } else if (builderImageName.equals(BuilderImageProvider.MANDREL.name())) { + return "quay.io/quarkus/ubi-quarkus-mandrel:21.3-java11"; + } else { + return this.builderImage; + } + } + /** * The container runtime (e.g. docker) that is used to do an image based build. If this is set then * a container build is always done. @@ -429,4 +441,12 @@ public String getExecutableName() { return this.name().toLowerCase(); } } + + /** + * Supported Builder Image providers/distributions + */ + public static enum BuilderImageProvider { + GRAALVM, + MANDREL; + } } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java index d3f1e486f49cf..21cf66e779abb 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunner.java @@ -46,15 +46,15 @@ public void setup(boolean processInheritIODisabled) { // we pull the docker image in order to give users an indication of which step the process is at // it's not strictly necessary we do this, however if we don't the subsequent version command // will appear to block and no output will be shown - log.info("Checking image status " + nativeConfig.builderImage); + log.info("Checking image status " + nativeConfig.getEffectiveBuilderImage()); Process pullProcess = null; try { final ProcessBuilder pb = new ProcessBuilder( - Arrays.asList(containerRuntime.getExecutableName(), "pull", nativeConfig.builderImage)); + Arrays.asList(containerRuntime.getExecutableName(), "pull", nativeConfig.getEffectiveBuilderImage())); pullProcess = ProcessUtil.launchProcess(pb, processInheritIODisabled); pullProcess.waitFor(); } catch (IOException | InterruptedException e) { - throw new RuntimeException("Failed to pull builder image " + nativeConfig.builderImage, e); + throw new RuntimeException("Failed to pull builder image " + nativeConfig.getEffectiveBuilderImage(), e); } finally { if (pullProcess != null) { pullProcess.destroy(); @@ -121,7 +121,7 @@ protected List getContainerRuntimeBuildArgs() { protected String[] buildCommand(String dockerCmd, List containerRuntimeArgs, List command) { return Stream .of(Stream.of(containerRuntime.getExecutableName()), Stream.of(dockerCmd), Stream.of(baseContainerRuntimeArgs), - containerRuntimeArgs.stream(), Stream.of(nativeConfig.builderImage), command.stream()) + containerRuntimeArgs.stream(), Stream.of(nativeConfig.getEffectiveBuilderImage()), command.stream()) .flatMap(Function.identity()).toArray(String[]::new); } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/UpxCompressionBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/UpxCompressionBuildStep.java index 099bc9ab306db..27b702c80613c 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/UpxCompressionBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/UpxCompressionBuildStep.java @@ -48,7 +48,7 @@ public void compress(NativeConfig nativeConfig, NativeImageBuildItem image, throw new IllegalStateException("Unable to compress the native executable"); } } else if (nativeConfig.isContainerBuild()) { - log.infof("Running UPX from a container using the builder image: " + nativeConfig.builderImage); + log.infof("Running UPX from a container using the builder image: " + nativeConfig.getEffectiveBuilderImage()); if (!runUpxInContainer(image, nativeConfig)) { throw new IllegalStateException("Unable to compress the native executable"); } @@ -131,7 +131,7 @@ private boolean runUpxInContainer(NativeImageBuildItem nativeImage, NativeConfig Collections.addAll(commandLine, "-v", volumeOutputPath + ":" + NativeImageBuildStep.CONTAINER_BUILD_VOLUME_PATH + ":z"); - commandLine.add(nativeConfig.builderImage); + commandLine.add(nativeConfig.getEffectiveBuilderImage()); commandLine.add(level); commandLine.addAll(extraArgs); diff --git a/core/deployment/src/test/java/io/quarkus/deployment/pkg/NativeConfigTest.java b/core/deployment/src/test/java/io/quarkus/deployment/pkg/NativeConfigTest.java new file mode 100644 index 0000000000000..640667b990cf3 --- /dev/null +++ b/core/deployment/src/test/java/io/quarkus/deployment/pkg/NativeConfigTest.java @@ -0,0 +1,29 @@ +package io.quarkus.deployment.pkg; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class NativeConfigTest { + + @Test + public void testBuilderImageProperlyDetected() { + NativeConfig nativeConfig = new NativeConfig(); + nativeConfig.builderImage = "graalvm"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("ubi-quarkus-native-image")).isTrue(); + nativeConfig.builderImage = "GraalVM"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("ubi-quarkus-native-image")).isTrue(); + nativeConfig.builderImage = "GRAALVM"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("ubi-quarkus-native-image")).isTrue(); + nativeConfig.builderImage = "mandrel"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("ubi-quarkus-mandrel")).isTrue(); + nativeConfig.builderImage = "Mandrel"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("ubi-quarkus-mandrel")).isTrue(); + nativeConfig.builderImage = "MANDREL"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("ubi-quarkus-mandrel")).isTrue(); + nativeConfig.builderImage = "aRandomString"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("aRandomString")).isTrue(); + nativeConfig.builderImage = "aRandomStr32ng"; + assertThat(nativeConfig.getEffectiveBuilderImage().contains("aRandomString")).isFalse(); + } +} 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 new file mode 100644 index 0000000000000..200352653c202 --- /dev/null +++ b/core/deployment/src/test/java/io/quarkus/deployment/pkg/steps/NativeImageBuildContainerRunnerTest.java @@ -0,0 +1,56 @@ +package io.quarkus.deployment.pkg.steps; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.file.Path; +import java.util.Collections; +import java.util.Optional; + +import org.junit.jupiter.api.Test; + +import io.quarkus.deployment.pkg.NativeConfig; + +class NativeImageBuildContainerRunnerTest { + + @Test + void testBuilderImageBeingPickedUp() { + NativeConfig nativeConfig = new NativeConfig(); + nativeConfig.containerRuntime = Optional.empty(); + boolean found; + NativeImageBuildLocalContainerRunner localRunner; + String[] command; + + nativeConfig.builderImage = "graalvm"; + localRunner = new NativeImageBuildLocalContainerRunner(nativeConfig, Path.of("/tmp")); + command = localRunner.buildCommand("docker", Collections.emptyList(), Collections.emptyList()); + found = false; + for (String part : command) { + if (part.contains("ubi-quarkus-native-image")) { + found = true; + } + } + assertThat(found).isTrue(); + + nativeConfig.builderImage = "mandrel"; + localRunner = new NativeImageBuildLocalContainerRunner(nativeConfig, Path.of("/tmp")); + command = localRunner.buildCommand("docker", Collections.emptyList(), Collections.emptyList()); + found = false; + for (String part : command) { + if (part.contains("ubi-quarkus-mandrel")) { + found = true; + } + } + assertThat(found).isTrue(); + + nativeConfig.builderImage = "RandomString"; + localRunner = new NativeImageBuildLocalContainerRunner(nativeConfig, Path.of("/tmp")); + command = localRunner.buildCommand("docker", Collections.emptyList(), Collections.emptyList()); + found = false; + for (String part : command) { + if (part.equals("RandomString")) { + found = true; + } + } + assertThat(found).isTrue(); + } +} diff --git a/docs/src/main/asciidoc/platform.adoc b/docs/src/main/asciidoc/platform.adoc index d7ce35d2a031c..8fe9f9415ed69 100644 --- a/docs/src/main/asciidoc/platform.adoc +++ b/docs/src/main/asciidoc/platform.adoc @@ -122,7 +122,7 @@ public class NativeConfig { ---- In this case the default value for `quarkus.native.builder-image` will be provided by the platform. The user will still be able to set the desired value for `quarkus.native.builder-image` in its `application.properties`, of course. But in case it's not customized by the user, the default value will be coming from the platform properties. -A platform properties file for the example above would contain (the actual value is provided as an example): +A platform properties file for the example above would contain: [source,text,subs=attributes+] ----