From bb9e37e11968420fe7a376f84e303dacf3cd7117 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 31 Mar 2020 20:00:41 -0500 Subject: [PATCH] Use platform API builder image tags CNB builder images are now being tagged in a manner that indicates the version of the platform API implemented. This allows Spring Boot to default to a builder tag that guarantees API compatibility while allowing for updates to bundled buildpacks. Fixes gh-20171 --- .../boot/buildpack/platform/build/BuildRequest.java | 4 +++- .../boot/buildpack/platform/build/BuildRequestTests.java | 4 ++-- .../boot/buildpack/platform/build/BuilderTests.java | 6 +++--- .../src/docs/asciidoc/packaging-oci-image.adoc | 2 +- .../tasks/bundling/BootBuildImageIntegrationTests.java | 6 +++--- ...ImageIntegrationTests-buildsImageWithV1Builder.gradle | 2 +- .../src/docs/asciidoc/packaging-oci-image.adoc | 2 +- .../org/springframework/boot/maven/BuildImageTests.java | 9 +++++---- .../src/intTest/projects/build-image-v1-builder/pom.xml | 2 +- .../java/org/springframework/boot/maven/ImageTests.java | 2 +- 10 files changed, 21 insertions(+), 18 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java index 8b24eba140..7ed6ffdfa4 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java @@ -36,7 +36,9 @@ import org.springframework.util.Assert; */ public class BuildRequest { - private static final ImageReference DEFAULT_BUILDER = ImageReference.of("cloudfoundry/cnb:0.0.53-bionic"); + static final String DEFAULT_BUILDER_IMAGE_NAME = "cloudfoundry/cnb:bionic-platform-api-0.2"; + + private static final ImageReference DEFAULT_BUILDER = ImageReference.of(DEFAULT_BUILDER_IMAGE_NAME); private final ImageReference name; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuildRequestTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuildRequestTests.java index 9a74d4e7aa..b6ad7656d5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuildRequestTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuildRequestTests.java @@ -55,7 +55,7 @@ public class BuildRequestTests { writeTestJarFile(jarFile); BuildRequest request = BuildRequest.forJarFile(jarFile); assertThat(request.getName().toString()).isEqualTo("docker.io/library/my-app:0.0.1"); - assertThat(request.getBuilder().toString()).isEqualTo("docker.io/cloudfoundry/cnb:0.0.53-bionic"); + assertThat(request.getBuilder().toString()).isEqualTo("docker.io/" + BuildRequest.DEFAULT_BUILDER_IMAGE_NAME); assertThat(request.getApplicationContent(Owner.ROOT)).satisfies(this::hasExpectedJarContent); assertThat(request.getEnv()).isEmpty(); } @@ -66,7 +66,7 @@ public class BuildRequestTests { writeTestJarFile(jarFile); BuildRequest request = BuildRequest.forJarFile(ImageReference.of("test-app"), jarFile); assertThat(request.getName().toString()).isEqualTo("docker.io/library/test-app:latest"); - assertThat(request.getBuilder().toString()).isEqualTo("docker.io/cloudfoundry/cnb:0.0.53-bionic"); + assertThat(request.getBuilder().toString()).isEqualTo("docker.io/" + BuildRequest.DEFAULT_BUILDER_IMAGE_NAME); assertThat(request.getApplicationContent(Owner.ROOT)).satisfies(this::hasExpectedJarContent); assertThat(request.getEnv()).isEmpty(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java index 7de9a69a52..e6577206ec 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java @@ -72,7 +72,7 @@ class BuilderTests { DockerApi docker = mockDockerApi(); Image builderImage = loadImage("image.json"); Image runImage = loadImage("run-image.json"); - given(docker.image().pull(eq(ImageReference.of("docker.io/cloudfoundry/cnb:0.0.53-bionic")), any())) + given(docker.image().pull(eq(ImageReference.of("docker.io/" + BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any())) .willAnswer(withPulledImage(builderImage)); given(docker.image().pull(eq(ImageReference.of("docker.io/cloudfoundry/run:full-cnb")), any())) .willAnswer(withPulledImage(runImage)); @@ -97,7 +97,7 @@ class BuilderTests { DockerApi docker = mockDockerApi(); Image builderImage = loadImage("image.json"); Image runImage = loadImage("run-image-with-bad-stack.json"); - given(docker.image().pull(eq(ImageReference.of("docker.io/cloudfoundry/cnb:0.0.53-bionic")), any())) + given(docker.image().pull(eq(ImageReference.of("docker.io/" + BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any())) .willAnswer(withPulledImage(builderImage)); given(docker.image().pull(eq(ImageReference.of("docker.io/cloudfoundry/run:full-cnb")), any())) .willAnswer(withPulledImage(runImage)); @@ -113,7 +113,7 @@ class BuilderTests { DockerApi docker = mockDockerApiLifecycleError(); Image builderImage = loadImage("image.json"); Image runImage = loadImage("run-image.json"); - given(docker.image().pull(eq(ImageReference.of("docker.io/cloudfoundry/cnb:0.0.53-bionic")), any())) + given(docker.image().pull(eq(ImageReference.of("docker.io/" + BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any())) .willAnswer(withPulledImage(builderImage)); given(docker.image().pull(eq(ImageReference.of("docker.io/cloudfoundry/run:full-cnb")), any())) .willAnswer(withPulledImage(runImage)); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 66eb9056c0..b3aa3c687b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -48,7 +48,7 @@ The following table summarizes the available properties and their default values | `builder` | `--builder` | Name of the Builder image to use. -| `cloudfoundry/cnb:0.0.53-bionic` +| `cloudfoundry/cnb:bionic-platform-api-0.2` | `imageName` | `--imageName` diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java index 3ca0cc515e..a9adf5edda 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java @@ -61,7 +61,7 @@ class BootBuildImageIntegrationTests { String projectName = this.gradleBuild.getProjectDir().getName(); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.getOutput()).contains("docker.io/library/" + projectName); - assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.53-bionic"); + assertThat(result.getOutput()).contains("cloudfoundry/cnb:bionic-platform-api"); ImageReference imageReference = ImageReference.of(ImageName.of(projectName)); try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); @@ -78,7 +78,7 @@ class BootBuildImageIntegrationTests { BuildResult result = this.gradleBuild.build("bootBuildImage"); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.getOutput()).contains("example.com/test-image-name"); - assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.53-bionic"); + assertThat(result.getOutput()).contains("cloudfoundry/cnb:bionic-platform-api"); ImageReference imageReference = ImageReference.of(ImageName.of("example.com/test-image-name")); try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); @@ -96,7 +96,7 @@ class BootBuildImageIntegrationTests { String projectName = this.gradleBuild.getProjectDir().getName(); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.getOutput()).contains("docker.io/library/" + projectName); - assertThat(result.getOutput()).contains("cloudfoundry/cnb:0.0.43-bionic"); + assertThat(result.getOutput()).contains("cloudfoundry/cnb:bionic-platform-api-0.1"); ImageReference imageReference = ImageReference.of(ImageName.of(projectName)); try (GenericContainer container = new GenericContainer<>(imageReference.toString())) { container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithV1Builder.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithV1Builder.gradle index 2cf0a0cb07..90183b8fb6 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithV1Builder.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithV1Builder.gradle @@ -7,5 +7,5 @@ sourceCompatibility = '1.8' targetCompatibility = '1.8' bootBuildImage { - builder = "cloudfoundry/cnb:0.0.43-bionic" + builder = "cloudfoundry/cnb:bionic-platform-api-0.1" } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 448bd49a20..39628c95f1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -73,7 +73,7 @@ The following table summarizes the available parameters and their default values | `builder` | Name of the Builder image to use. | `spring-boot.build-image.builder` -| `cloudfoundry/cnb:0.0.53-bionic` +| `cloudfoundry/cnb:bionic-platform-api-0.2` | `name` | {spring-boot-api}/buildpack/platform/docker/type/ImageReference.html#of-java.lang.String-[Image name] for the generated image. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java index 1e7595a0a0..10821df6c7 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java @@ -52,7 +52,7 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { assertThat(jar).isFile(); File original = new File(project, "target/build-image-0.0.1.BUILD-SNAPSHOT.jar.original"); assertThat(original).doesNotExist(); - assertThat(buildLog(project)).contains("Building image").contains("cloudfoundry/cnb:0.0.53-bionic") + assertThat(buildLog(project)).contains("Building image").contains("cloudfoundry/cnb:bionic-platform-api") .contains("docker.io/library/build-image:0.0.1.BUILD-SNAPSHOT") .contains("Successfully built image"); ImageReference imageReference = ImageReference.of(ImageName.of("build-image"), "0.0.1.BUILD-SNAPSHOT"); @@ -93,11 +93,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { 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") + .systemProperty("spring-boot.build-image.builder", "cloudfoundry/cnb:bionic-platform-api-0.1") .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"); + .contains("cloudfoundry/cnb:bionic-platform-api-0.1").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(); @@ -111,7 +111,8 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { @TestTemplate void whenBuildImageIsInvokedWithV1BuilderImage(MavenBuild mavenBuild) { mavenBuild.project("build-image-v1-builder").goals("package").execute((project) -> { - assertThat(buildLog(project)).contains("Building image").contains("cloudfoundry/cnb:0.0.43-bionic") + assertThat(buildLog(project)).contains("Building image") + .contains("cloudfoundry/cnb:bionic-platform-api-0.1") .contains("docker.io/library/build-image-v1-builder:0.0.1.BUILD-SNAPSHOT") .contains("Successfully built image"); ImageReference imageReference = ImageReference diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-v1-builder/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-v1-builder/pom.xml index 0008fb7793..7f5e2f269b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-v1-builder/pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-v1-builder/pom.xml @@ -23,7 +23,7 @@ - cloudfoundry/cnb:0.0.43-bionic + cloudfoundry/cnb:bionic-platform-api-0.1 diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ImageTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ImageTests.java index e09922361b..adb7af0861 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ImageTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ImageTests.java @@ -57,7 +57,7 @@ class ImageTests { void getBuildRequestWhenNoCustomizationsUsesDefaults() { BuildRequest request = new Image().getBuildRequest(createArtifact(), mockAplicationContent()); assertThat(request.getName().toString()).isEqualTo("docker.io/library/my-app:0.0.1-SNAPSHOT"); - assertThat(request.getBuilder().toString()).isEqualTo("docker.io/cloudfoundry/cnb:0.0.53-bionic"); + assertThat(request.getBuilder().toString()).contains("docker.io/cloudfoundry/cnb:bionic-platform-api"); assertThat(request.getEnv()).isEmpty(); assertThat(request.isCleanCache()).isFalse(); assertThat(request.isVerboseLogging()).isFalse();