Add command-line properties for Maven build-image options
This commit adds support for setting the image name and builder parameters of the Maven spring-boot:build-image goal using command-line properties as an alternative to plugin configuration in pom.xml. Per Maven conventions, a value in pom.xml configuration will override a command-line property when both are provided. Fixes gh-20520
This commit is contained in:
@@ -40,29 +40,34 @@ By default, the plugin chooses a builder image.
|
||||
The name of the generated image is deduced from project properties.
|
||||
|
||||
The `image` parameter allows to configure how the builder should operate on the project.
|
||||
The following table summarizes the available properties and their default values:
|
||||
The following table summarizes the available parameters and their default values:
|
||||
|
||||
|===
|
||||
| Property | Description | Default value
|
||||
| Parameter | Description | User property | Default value
|
||||
|
||||
| `builder`
|
||||
| Name of the Builder image to use.
|
||||
| `spring-boot.build-image.builder`
|
||||
| `cloudfoundry/cnb:0.0.53-bionic`
|
||||
|
||||
| `name`
|
||||
| {spring-boot-api}/buildpack/platform/docker/type/ImageReference.html#of-java.lang.String-[Image name] for the generated image.
|
||||
| `spring-boot.build-image.imageName`
|
||||
| `docker.io/library/${project.artifactId}:${project.version}`
|
||||
|
||||
| `env`
|
||||
| Environment variables that should be passed to the builder.
|
||||
|
|
||||
|
|
||||
|
||||
| `cleanCache`
|
||||
| Whether to clean the cache before building.
|
||||
|
|
||||
| `false`
|
||||
|
||||
| `verboseLogging`
|
||||
| Enables verbose logging of builder operations.
|
||||
|
|
||||
| `false`
|
||||
|===
|
||||
|
||||
@@ -79,7 +84,7 @@ include::goals/build-image.adoc[leveloffset=+1]
|
||||
|
||||
[[build-image-example-custom-image-builder]]
|
||||
==== Custom Image Builder
|
||||
If you need to customize the builder used to create the image, configure yours as shown in the following example:
|
||||
If you need to customize the builder used to create the image, configure the plugin as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
@@ -103,6 +108,13 @@ If you need to customize the builder used to create the image, configure yours a
|
||||
|
||||
This configuration will use a builder image with the name `mine/java-cnb-builder` and the tag `latest`.
|
||||
|
||||
The builder can be specified on the command line as well, as shown in this example:
|
||||
|
||||
[indent=0]
|
||||
----
|
||||
$ mvn spring-boot:build-image -Dspring-boot.build-image:builder=mine/java-cnb-builder
|
||||
----
|
||||
|
||||
If the builder exposes configuration options, those can be set using the `env` attributes, as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
@@ -158,4 +170,12 @@ You can take control over the name, as shown in the following example:
|
||||
----
|
||||
|
||||
Note that this configuration does not provide an explicit tag so `latest` is used.
|
||||
It is possible to specify a tag as well, either using `${project.version}`, any property available in the build or a hardcoded version.
|
||||
It is possible to specify a tag as well, either using `${project.version}`, any property available in the build or a hardcoded version.
|
||||
|
||||
The image name can be specified on the command line as well, as shown in this example:
|
||||
|
||||
[indent=0]
|
||||
----
|
||||
$ mvn spring-boot:build-image -Dspring-boot.build-image:imageName=example.com/library/v1
|
||||
----
|
||||
|
||||
|
||||
@@ -67,21 +67,45 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
|
||||
|
||||
@TestTemplate
|
||||
void whenBuildImageIsInvokedWithCustomImageName(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("build-image-custom-name").goals("package").execute((project) -> {
|
||||
File jar = new File(project, "target/build-image-custom-name-0.0.1.BUILD-SNAPSHOT.jar");
|
||||
assertThat(jar).isFile();
|
||||
File original = new File(project, "target/build-image-custom-name-0.0.1.BUILD-SNAPSHOT.jar.original");
|
||||
assertThat(original).doesNotExist();
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT").contains("Successfully built image");
|
||||
ImageReference imageReference = ImageReference.of("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT");
|
||||
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
|
||||
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
|
||||
}
|
||||
finally {
|
||||
removeImage(imageReference);
|
||||
}
|
||||
});
|
||||
mavenBuild.project("build-image-custom-name").goals("package")
|
||||
.systemProperty("spring-boot.build-image.imageName", "example.com/test/property-ignored:pom-preferred")
|
||||
.execute((project) -> {
|
||||
File jar = new File(project, "target/build-image-custom-name-0.0.1.BUILD-SNAPSHOT.jar");
|
||||
assertThat(jar).isFile();
|
||||
File original = new File(project,
|
||||
"target/build-image-custom-name-0.0.1.BUILD-SNAPSHOT.jar.original");
|
||||
assertThat(original).doesNotExist();
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT")
|
||||
.contains("Successfully built image");
|
||||
ImageReference imageReference = ImageReference
|
||||
.of("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT");
|
||||
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
|
||||
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
|
||||
}
|
||||
finally {
|
||||
removeImage(imageReference);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void whenBuildImageIsInvokedWithCommandLineParameters(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("build-image").goals("package")
|
||||
.systemProperty("spring-boot.build-image.imageName", "example.com/test/cmd-property-name:v1")
|
||||
.systemProperty("spring-boot.build-image.builder", "cloudfoundry/cnb:0.0.43-bionic")
|
||||
.execute((project) -> {
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("example.com/test/cmd-property-name:v1")
|
||||
.contains("cloudfoundry/cnb:0.0.43-bionic").contains("Successfully built image");
|
||||
ImageReference imageReference = ImageReference.of("example.com/test/cmd-property-name:v1");
|
||||
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
|
||||
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
|
||||
}
|
||||
finally {
|
||||
removeImage(imageReference);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
|
||||
@@ -81,8 +81,8 @@ public abstract class AbstractPackagerMojo extends AbstractDependencyFilterMojo
|
||||
|
||||
/**
|
||||
* The type of archive (which corresponds to how the dependencies are laid out inside
|
||||
* it). Possible values are JAR, LAYERED_JAR, WAR, ZIP, DIR, NONE. Defaults to a guess
|
||||
* based on the archive type.
|
||||
* it). Possible values are JAR, WAR, ZIP, DIR, NONE. Defaults to a guess based on the
|
||||
* archive type.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Parameter(property = "spring-boot.repackage.layout")
|
||||
|
||||
@@ -101,6 +101,20 @@ public class BuildImageMojo extends AbstractPackagerMojo {
|
||||
@Parameter
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* Alias for {@link Image#name to support configuration via command-line property.
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Parameter(property = "spring-boot.build-image.imageName", readonly = true)
|
||||
String imageName;
|
||||
|
||||
/**
|
||||
* Alias for {@link Image#builder to support configuration via command-line property.
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Parameter(property = "spring-boot.build-image.builder", readonly = true)
|
||||
String imageBuilder;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException {
|
||||
if (this.project.getPackaging().equals("pom")) {
|
||||
@@ -129,6 +143,12 @@ public class BuildImageMojo extends AbstractPackagerMojo {
|
||||
private BuildRequest getBuildRequest(Libraries libraries) {
|
||||
Function<Owner, TarArchive> content = (owner) -> getApplicationContent(owner, libraries);
|
||||
Image image = (this.image != null) ? this.image : new Image();
|
||||
if (image.name == null && this.imageName != null) {
|
||||
image.setName(this.imageName);
|
||||
}
|
||||
if (image.builder == null && this.imageBuilder != null) {
|
||||
image.setBuilder(this.imageBuilder);
|
||||
}
|
||||
return customize(image.getBuildRequest(this.project.getArtifact(), content));
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.util.StringUtils;
|
||||
* Image configuration options.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class Image {
|
||||
@@ -61,6 +62,14 @@ public class Image {
|
||||
*/
|
||||
boolean verboseLogging;
|
||||
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
void setBuilder(String builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
BuildRequest getBuildRequest(Artifact artifact, Function<Owner, TarArchive> applicationContent) {
|
||||
return customize(BuildRequest.of(getOrDeduceName(artifact), applicationContent));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user