From 84abcfb043b6196c57a53493466d85422fe34f97 Mon Sep 17 00:00:00 2001 From: "James R. Perkins" Date: Thu, 29 Feb 2024 17:11:15 -0800 Subject: [PATCH] [WFMP-246] Ensure the serverConfig parameter sets the server configuration in the Dockerfile. https://issues.redhat.com/browse/WFMP-246 Signed-off-by: James R. Perkins --- .../provision/ApplicationImageMojo.java | 31 +++-- .../wildfly/plugin/provision/ExecUtil.java | 36 ++++++ .../plugin/provision/PackageServerMojo.java | 5 +- pom.xml | 16 +++ ...stractProvisionConfiguredMojoTestCase.java | 16 ++- tests/standalone-tests/pom.xml | 22 ++++ .../plugin/provision/AbstractImageTest.java | 119 ++++++++++++++++++ .../wildfly/plugin/provision/ImageTest.java | 34 ++--- .../LayersServerConfigImageTest.java | 18 +++ .../provision/ServerConfigImageTest.java | 18 +++ .../image-layers-server-config-pom.xml | 38 ++++++ .../test-project/image-server-config-pom.xml | 35 ++++++ 12 files changed, 350 insertions(+), 38 deletions(-) create mode 100644 tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/AbstractImageTest.java create mode 100644 tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/LayersServerConfigImageTest.java create mode 100644 tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ServerConfigImageTest.java create mode 100644 tests/standalone-tests/src/test/resources/test-project/image-layers-server-config-pom.xml create mode 100644 tests/standalone-tests/src/test/resources/test-project/image-server-config-pom.xml diff --git a/plugin/src/main/java/org/wildfly/plugin/provision/ApplicationImageMojo.java b/plugin/src/main/java/org/wildfly/plugin/provision/ApplicationImageMojo.java index baa16f09..ddcc6890 100644 --- a/plugin/src/main/java/org/wildfly/plugin/provision/ApplicationImageMojo.java +++ b/plugin/src/main/java/org/wildfly/plugin/provision/ApplicationImageMojo.java @@ -13,7 +13,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -22,6 +24,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.wildfly.plugin.common.PropertyNames; +import org.wildfly.plugin.core.Constants; /** * Build (and push) an application image containing the provisioned server and the deployment. @@ -217,13 +220,27 @@ private void generateDockerfile(String runtimeImage, Path targetDir, String wild } String targetName = getDeploymentTargetName(); - Files.writeString(targetDir.resolve("Dockerfile"), - "FROM " + runtimeImage + "\n" + - "COPY --chown=jboss:root " + jbossHome + " $JBOSS_HOME\n" + - "RUN chmod -R ug+rwX $JBOSS_HOME\n" + - "COPY --chown=jboss:root " + getDeploymentContent().getFileName() - + " $JBOSS_HOME/standalone/deployments/" + targetName, - StandardCharsets.UTF_8); + + // Create the Dockerfile content + final StringBuilder dockerfileContent = new StringBuilder(); + dockerfileContent.append("FROM ").append(runtimeImage).append('\n') + .append("COPY --chown=jboss:root ").append(jbossHome).append(" $JBOSS_HOME\n") + .append("RUN chmod -R ug+rwX $JBOSS_HOME\n") + .append("COPY --chown=jboss:root ").append(getDeploymentContent().getFileName()) + .append(" $JBOSS_HOME/standalone/deployments/").append(targetName); + + final List serverArgs = new ArrayList<>(); + if (!layers.isEmpty() && !layersConfigurationFileName.equals(Constants.STANDALONE_XML)) { + serverArgs.add("-c=" + layersConfigurationFileName); + } else if (!serverConfig.equals(Constants.STANDALONE_XML)) { + serverArgs.add("-c=" + serverConfig); + } + + if (!serverArgs.isEmpty()) { + dockerfileContent.append('\n').append("ENV SERVER_ARGS=\"").append(String.join(",", serverArgs)).append('"'); + } + + Files.writeString(targetDir.resolve("Dockerfile"), dockerfileContent, StandardCharsets.UTF_8); } private boolean isImageBinaryAvailable(String imageBinary) { diff --git a/plugin/src/main/java/org/wildfly/plugin/provision/ExecUtil.java b/plugin/src/main/java/org/wildfly/plugin/provision/ExecUtil.java index ed53703c..6aaed655 100644 --- a/plugin/src/main/java/org/wildfly/plugin/provision/ExecUtil.java +++ b/plugin/src/main/java/org/wildfly/plugin/provision/ExecUtil.java @@ -12,10 +12,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.time.Duration; import java.util.concurrent.TimeUnit; import org.apache.maven.plugin.logging.Log; +import org.wildfly.plugin.tools.ConsoleConsumer; public class ExecUtil { @@ -58,6 +60,18 @@ public static boolean exec(Log log, String command, String... args) { return exec(log, new File("."), command, args); } + /** + * Execute the specified command from within the current directory. + * + * @param out the output stream used to consume the console output + * @param command The command + * @param args The command arguments + * @return true if commands where executed successfully + */ + public static boolean exec(final OutputStream out, String command, String... args) { + return exec(out, new File("."), command, args); + } + /** * Execute silently the specified command until the given timeout from within the current directory. * @@ -91,6 +105,28 @@ public static boolean exec(Log log, File directory, String command, } } + /** + * Execute the specified command from within the specified directory. + * The method allows specifying an output filter that processes the command output. + * + * @param out the output stream used to consume the console output + * @param directory The directory + * @param command The command + * @param args The command arguments + * @return true if commands where executed successfully + */ + public static boolean exec(final OutputStream out, final File directory, final String command, + final String... args) { + try { + Process process = startProcess(directory, command, args); + ConsoleConsumer.start(process.getInputStream(), out); + process.waitFor(); + return process.exitValue() == 0; + } catch (InterruptedException e) { + return false; + } + } + /** * Execute the specified command until the given timeout from within the specified directory. * The method allows specifying an output filter that processes the command output. diff --git a/plugin/src/main/java/org/wildfly/plugin/provision/PackageServerMojo.java b/plugin/src/main/java/org/wildfly/plugin/provision/PackageServerMojo.java index 57ebccc8..0fd0f27d 100644 --- a/plugin/src/main/java/org/wildfly/plugin/provision/PackageServerMojo.java +++ b/plugin/src/main/java/org/wildfly/plugin/provision/PackageServerMojo.java @@ -112,9 +112,12 @@ public class PackageServerMojo extends AbstractProvisionServerMojo { * deployment. Defaults to 'standalone.xml'. If {@code layers-configuration-file-name} has been set, * this property is ignored and the deployment is deployed inside the configuration referenced from * {@code layers-configuration-file-name}. + *

+ * The value of this parameter is also ignored if any layers are defined. + *

*/ @Parameter(property = PropertyNames.SERVER_CONFIG, alias = "server-config", defaultValue = STANDALONE_XML) - private String serverConfig; + String serverConfig; /** * Specifies the name used for the deployment. diff --git a/pom.xml b/pom.xml index 08652ea8..72fc6649 100644 --- a/pom.xml +++ b/pom.xml @@ -101,6 +101,10 @@ 4.13.2 5.10.0 + + 2.1.3 + 1.1.5 + 11 11 @@ -427,6 +431,18 @@ ${version.org.wildfly.glow} + + jakarta.json + jakarta.json-api + ${version.jakarta.json-api} + test + + + org.eclipse.parsson + parsson + ${version.org.eclipse.parsson} + test + org.jboss.galleon galleon-core diff --git a/tests/shared/src/main/java/org/wildfly/plugin/tests/AbstractProvisionConfiguredMojoTestCase.java b/tests/shared/src/main/java/org/wildfly/plugin/tests/AbstractProvisionConfiguredMojoTestCase.java index e2f923a9..6791ec09 100644 --- a/tests/shared/src/main/java/org/wildfly/plugin/tests/AbstractProvisionConfiguredMojoTestCase.java +++ b/tests/shared/src/main/java/org/wildfly/plugin/tests/AbstractProvisionConfiguredMojoTestCase.java @@ -125,33 +125,37 @@ protected MavenSession newMavenSession(MavenProject project) { } protected Mojo lookupConfiguredMojo(File pom, String goal) throws Exception { + return lookupConfiguredMojo(pom.toPath(), goal); + } + + protected Mojo lookupConfiguredMojo(final Path pom, final String goal) throws Exception { assertNotNull(pom); - assertTrue(pom.exists()); + assertTrue(Files.exists(pom)); patchPomFile(pom); ProjectBuildingRequest buildingRequest = newMavenSession().getProjectBuildingRequest(); // Need to resolve artifacts for tests that upgrade server components buildingRequest.setResolveDependencies(true); ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); - MavenProject project = projectBuilder.build(pom, buildingRequest).getProject(); + MavenProject project = projectBuilder.build(pom.toFile(), buildingRequest).getProject(); Mojo mojo = lookupConfiguredMojo(project, goal); // For some reasons, the configuration item gets ignored in lookupConfiguredMojo // explicitly configure it - configureMojo(mojo, artifactId, pom); + configureMojo(mojo, artifactId, pom.toFile()); return mojo; } - private void patchPomFile(File pom) throws IOException { + private void patchPomFile(final Path pom) throws IOException { StringBuilder content = new StringBuilder(); - for (String s : Files.readAllLines(pom.toPath())) { + for (String s : Files.readAllLines(pom)) { if (s.contains(TEST_REPLACE_WF_VERSION)) { s = s.replace(TEST_REPLACE_WF_VERSION, System.getProperty(WILDFLY_VERSION)); } content.append(s).append(System.lineSeparator()); } - Files.write(pom.toPath(), content.toString().getBytes()); + Files.write(pom, content.toString().getBytes()); } @Before diff --git a/tests/standalone-tests/pom.xml b/tests/standalone-tests/pom.xml index 07b2121a..85042b21 100644 --- a/tests/standalone-tests/pom.xml +++ b/tests/standalone-tests/pom.xml @@ -72,6 +72,16 @@ maven-resolver-util test + + jakarta.json + jakarta.json-api + test + + + org.eclipse.parsson + parsson + test + @@ -96,6 +106,18 @@ true + + org.apache.maven.plugins + maven-surefire-plugin + + + 1 + false + + diff --git a/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/AbstractImageTest.java b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/AbstractImageTest.java new file mode 100644 index 00000000..bb47afcd --- /dev/null +++ b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/AbstractImageTest.java @@ -0,0 +1,119 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.wildfly.plugin.provision; + +import static org.junit.Assume.assumeNotNull; +import static org.wildfly.plugin.tests.AbstractWildFlyMojoTest.getPomFile; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonReader; +import jakarta.json.JsonString; +import jakarta.json.JsonStructure; +import jakarta.json.JsonValue; +import jakarta.json.JsonWriter; +import jakarta.json.JsonWriterFactory; +import jakarta.json.stream.JsonGenerator; + +import org.apache.maven.plugin.Mojo; +import org.apache.maven.plugin.logging.Log; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.wildfly.plugin.tests.AbstractProvisionConfiguredMojoTestCase; +import org.wildfly.plugin.tests.AbstractWildFlyMojoTest; + +abstract class AbstractImageTest extends AbstractProvisionConfiguredMojoTestCase { + + public AbstractImageTest() { + super("wildfly-maven-plugin"); + } + + @BeforeClass + public static void checkDockerInstallation() { + assumeNotNull("Docker is not present in the installation, skipping the tests", + ExecUtil.resolveImageBinary()); + } + + protected void assertConfigFileName(final String prefix, final String expectedEnvVar) throws Exception { + final String imageName = "wildfly-" + prefix + "-maven-plugin/testing"; + final String binary = ExecUtil.resolveImageBinary(); + try { + final Mojo imageMojo = lookupConfiguredMojo(getPomFile(prefix + "-pom.xml"), "image"); + imageMojo.execute(); + final Path jbossHome = AbstractWildFlyMojoTest.getBaseDir().resolve("target").resolve(prefix); + assertTrue(Files.exists(jbossHome)); + + final ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + assertTrue(ExecUtil.exec(stdout, binary, "inspect", imageName)); + assertEnvironmentSet(stdout, expectedEnvVar); + + } finally { + exec(binary, "rmi", imageName); + } + } + + protected static boolean exec(String command, String... args) { + return ExecUtil.exec((Log) null, new File("."), command, args); + } + + protected static String formatJson(final JsonStructure json) throws IOException { + try (StringWriter writer = new StringWriter()) { + JsonWriterFactory factory = Json.createWriterFactory(Map.of(JsonGenerator.PRETTY_PRINTING, true)); + try (JsonWriter jsonWriter = factory.createWriter(writer)) { + jsonWriter.write(json); + return writer.toString(); + } + } + } + + protected static void assertEnvironmentSet(final ByteArrayOutputStream stdout, final String expectedEnvVar) { + assertEnvironment(stdout, expectedEnvVar, true); + } + + protected static void assertEnvironmentUnset(final ByteArrayOutputStream stdout, final String expectedEnvVar) { + assertEnvironment(stdout, expectedEnvVar, false); + } + + private static void assertEnvironment(final ByteArrayOutputStream stdout, final String expectedEnvVar, + final boolean isSet) { + + try (JsonReader reader = Json.createReader(new ByteArrayInputStream(stdout.toByteArray()))) { + final JsonArray array = reader.readArray(); + Assert.assertFalse("Array was not expected to be empty: " + array, array.isEmpty()); + final JsonObject json = array.getJsonObject(0); + final JsonObject config = json.getJsonObject("Config"); + final JsonArray env = config.getJsonArray("Env"); + boolean found = false; + for (JsonValue value : env) { + Assert.assertEquals(String.format("JSON value %s is not a string type: %s", value, value.getValueType()), + JsonValue.ValueType.STRING, value.getValueType()); + if (((JsonString) value).getString().contains(expectedEnvVar)) { + found = true; + break; + } + } + if (isSet && !found) { + Assert.fail( + String.format("Failed to find %s in environment.%n%s", expectedEnvVar, formatJson(env))); + } + if (!isSet && found) { + Assert.fail( + String.format("Found %s in environment and it should not exist.%n%s", expectedEnvVar, formatJson(env))); + } + } catch (Exception e) { + Assert.fail(String.format("Output from inspect is not valid JSON: %s%nOutput:%n%s", e.getMessage(), stdout)); + } + } +} diff --git a/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ImageTest.java b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ImageTest.java index 9ba42101..69addc88 100644 --- a/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ImageTest.java +++ b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ImageTest.java @@ -4,33 +4,21 @@ */ package org.wildfly.plugin.provision; -import static org.junit.Assume.assumeNotNull; -import static org.wildfly.plugin.provision.ExecUtil.exec; import static org.wildfly.plugin.provision.ExecUtil.execSilentWithTimeout; +import static org.wildfly.plugin.tests.AbstractWildFlyMojoTest.getPomFile; +import java.io.ByteArrayOutputStream; import java.nio.file.Path; import java.time.Duration; import org.apache.maven.plugin.Mojo; import org.apache.maven.plugin.MojoExecutionException; import org.junit.Assume; -import org.junit.BeforeClass; import org.junit.Test; -import org.wildfly.plugin.tests.AbstractProvisionConfiguredMojoTestCase; import org.wildfly.plugin.tests.AbstractWildFlyMojoTest; import org.wildfly.plugin.tests.TestEnvironment; -public class ImageTest extends AbstractProvisionConfiguredMojoTestCase { - - public ImageTest() { - super("wildfly-maven-plugin"); - } - - @BeforeClass - public static void checkDockerInstallation() { - assumeNotNull("Docker is not present in the installation, skipping the tests", - ExecUtil.resolveImageBinary()); - } +public class ImageTest extends AbstractImageTest { @Test public void testBuildImage() throws Exception { @@ -41,29 +29,27 @@ public void testBuildImage() throws Exception { execSilentWithTimeout(Duration.ofMillis(3000), binary, "-v")); assertFalse( - exec(null, - binary, "inspect", "wildfly-maven-plugin/testing")); + exec(binary, "inspect", "wildfly-maven-plugin/testing")); - final Mojo imageMojo = lookupConfiguredMojo(AbstractWildFlyMojoTest.getPomFile("image-pom.xml").toFile(), "image"); + final Mojo imageMojo = lookupConfiguredMojo(getPomFile("image-pom.xml").toFile(), "image"); imageMojo.execute(); Path jbossHome = AbstractWildFlyMojoTest.getBaseDir().resolve("target").resolve("image-server"); assertTrue(jbossHome.toFile().exists()); - assertTrue( - exec(null, - binary, "inspect", "wildfly-maven-plugin/testing")); + final ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + assertTrue(ExecUtil.exec(stdout, binary, "inspect", "wildfly-maven-plugin/testing")); + assertEnvironmentUnset(stdout, "SERVER_ARGS=-c="); } finally { - exec(null, - binary, "rmi", "wildfly-maven-plugin/testing"); + exec(binary, "rmi", "wildfly-maven-plugin/testing"); } } @Test(expected = MojoExecutionException.class) public void testBuildImageWithUnknownDockerBinary() throws Exception { final Mojo imageMojo = lookupConfiguredMojo( - AbstractWildFlyMojoTest.getPomFile("image-unknown-docker-binary-pom.xml").toFile(), "image"); + getPomFile("image-unknown-docker-binary-pom.xml").toFile(), "image"); imageMojo.execute(); } } diff --git a/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/LayersServerConfigImageTest.java b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/LayersServerConfigImageTest.java new file mode 100644 index 00000000..5de4de8b --- /dev/null +++ b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/LayersServerConfigImageTest.java @@ -0,0 +1,18 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.wildfly.plugin.provision; + +import org.junit.Assume; +import org.junit.Test; +import org.wildfly.plugin.tests.TestEnvironment; + +public class LayersServerConfigImageTest extends AbstractImageTest { + + @Test + public void layersConfigurationFileName() throws Exception { + Assume.assumeFalse("This test is flaky on Windows, ignore it on Windows.", TestEnvironment.isWindows()); + assertConfigFileName("image-layers-server-config", "SERVER_ARGS=-c=standalone-core.xml"); + } +} diff --git a/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ServerConfigImageTest.java b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ServerConfigImageTest.java new file mode 100644 index 00000000..170f4ed2 --- /dev/null +++ b/tests/standalone-tests/src/test/java/org/wildfly/plugin/provision/ServerConfigImageTest.java @@ -0,0 +1,18 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.wildfly.plugin.provision; + +import org.junit.Assume; +import org.junit.Test; +import org.wildfly.plugin.tests.TestEnvironment; + +public class ServerConfigImageTest extends AbstractImageTest { + + @Test + public void serverConfig() throws Exception { + Assume.assumeFalse("This test is flaky on Windows, ignore it on Windows.", TestEnvironment.isWindows()); + assertConfigFileName("image-server-config", "SERVER_ARGS=-c=standalone-microprofile.xml"); + } +} diff --git a/tests/standalone-tests/src/test/resources/test-project/image-layers-server-config-pom.xml b/tests/standalone-tests/src/test/resources/test-project/image-layers-server-config-pom.xml new file mode 100644 index 00000000..7d7229da --- /dev/null +++ b/tests/standalone-tests/src/test/resources/test-project/image-layers-server-config-pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + testing + testing + 0.1.0-SNAPSHOT + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + wildfly@maven(org.jboss.universe:community-universe)#WF_VERSION + + + + jaxrs-server + + image-layers-server-config + test.war + + wildfly-image-layers-server-config-maven-plugin + + standalone-core.xml + + + + + + \ No newline at end of file diff --git a/tests/standalone-tests/src/test/resources/test-project/image-server-config-pom.xml b/tests/standalone-tests/src/test/resources/test-project/image-server-config-pom.xml new file mode 100644 index 00000000..8be2707b --- /dev/null +++ b/tests/standalone-tests/src/test/resources/test-project/image-server-config-pom.xml @@ -0,0 +1,35 @@ + + + + 4.0.0 + testing + testing + 0.1.0-SNAPSHOT + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + wildfly@maven(org.jboss.universe:community-universe)#WF_VERSION + + + image-server-config + test.war + + wildfly-image-server-config-maven-plugin + + standalone-microprofile.xml + + + + + + \ No newline at end of file