diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersion.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersion.java index 16014c26e2..789264fe6e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersion.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersion.java @@ -105,7 +105,7 @@ final class ApiVersion { @Override public String toString() { - return "v" + this.major + "." + this.minor; + return this.major + "." + this.minor; } /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersions.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersions.java index 33fbc10e1b..81cd623b9e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersions.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/ApiVersions.java @@ -41,17 +41,24 @@ final class ApiVersions { } /** - * Assert that the specified version is supported by these API versions. - * @param other the version to check against + * Find the latest version among the specified versions that is supported by these API + * versions. + * @param others the versions to check against + * @return the version */ - void assertSupports(ApiVersion other) { - for (ApiVersion apiVersion : this.apiVersions) { - if (apiVersion.supports(other)) { - return; + ApiVersion findLatestSupported(String... others) { + for (int versionsIndex = this.apiVersions.length - 1; versionsIndex >= 0; versionsIndex--) { + ApiVersion apiVersion = this.apiVersions[versionsIndex]; + for (int otherIndex = others.length - 1; otherIndex >= 0; otherIndex--) { + ApiVersion other = ApiVersion.parse(others[otherIndex]); + if (apiVersion.supports(other)) { + return apiVersion; + } } } throw new IllegalStateException( - "Detected platform API version '" + other + "' is not included in supported versions '" + this + "'"); + "Detected platform API versions '" + StringUtils.arrayToCommaDelimitedString(others) + + "' are not included in supported versions '" + this + "'"); } @Override diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderMetadata.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderMetadata.java index 06f8f4a575..25f1885916 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderMetadata.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuilderMetadata.java @@ -36,6 +36,7 @@ import org.springframework.util.StringUtils; * * @author Phillip Webb * @author Andy Wilkinson + * @author Scott Frederick */ class BuilderMetadata extends MappedObject { @@ -184,30 +185,59 @@ class BuilderMetadata extends MappedObject { String getVersion(); /** - * Return the API versions. + * Return the default API versions. * @return the API versions */ Api getApi(); /** - * API versions. + * Return the supported API versions. + * @return the API versions + */ + Apis getApis(); + + /** + * Default API versions. */ interface Api { /** - * Return the buildpack API version. + * Return the default buildpack API version. * @return the buildpack version */ String getBuildpack(); /** - * Return the platform API version. + * Return the default platform API version. * @return the platform version */ String getPlatform(); } + /** + * Supported API versions. + */ + interface Apis { + + /** + * Return the supported buildpack API versions. + * @return the buildpack versions + */ + default String[] getBuildpack() { + return valueAt(this, "/buildpack/supported", String[].class); + } + + /** + * Return the supported platform API versions. + * @return the platform versions + */ + default String[] getPlatform() { + return valueAt(this, "/platform/supported", String[].class); + } + + } + } /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java index 222624efdf..dac0298fca 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java @@ -42,6 +42,8 @@ class Lifecycle implements Closeable { private static final LifecycleVersion LOGGING_MINIMUM_VERSION = LifecycleVersion.parse("0.0.5"); + private static final String PLATFORM_API_VERSION_KEY = "CNB_PLATFORM_API"; + private final BuildLog log; private final DockerApi docker; @@ -79,12 +81,11 @@ class Lifecycle implements Closeable { this.request = request; this.builder = builder; this.lifecycleVersion = LifecycleVersion.parse(builder.getBuilderMetadata().getLifecycle().getVersion()); - this.platformVersion = ApiVersion.parse(builder.getBuilderMetadata().getLifecycle().getApi().getPlatform()); + this.platformVersion = getPlatformVersion(builder.getBuilderMetadata().getLifecycle()); this.layersVolume = createRandomVolumeName("pack-layers-"); this.applicationVolume = createRandomVolumeName("pack-app-"); this.buildCacheVolume = createCacheVolumeName(request, ".build"); this.launchCacheVolume = createCacheVolumeName(request, ".launch"); - checkPlatformVersion(this.platformVersion); } protected VolumeName createRandomVolumeName(String prefix) { @@ -95,8 +96,13 @@ class Lifecycle implements Closeable { return VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", suffix, 6); } - private void checkPlatformVersion(ApiVersion platformVersion) { - ApiVersions.SUPPORTED_PLATFORMS.assertSupports(platformVersion); + private ApiVersion getPlatformVersion(BuilderMetadata.Lifecycle lifecycle) { + if (lifecycle.getApis().getPlatform() != null) { + String[] supportedVersions = lifecycle.getApis().getPlatform(); + return ApiVersions.SUPPORTED_PLATFORMS.findLatestSupported(supportedVersions); + } + String version = lifecycle.getApi().getPlatform(); + return ApiVersions.SUPPORTED_PLATFORMS.findLatestSupported(version); } /** @@ -133,6 +139,7 @@ class Lifecycle implements Closeable { phase.withBinds(this.applicationVolume, Directory.APPLICATION); phase.withBinds(this.buildCacheVolume, Directory.CACHE); phase.withBinds(this.launchCacheVolume, Directory.LAUNCH_CACHE); + phase.withEnv(PLATFORM_API_VERSION_KEY, this.platformVersion.toString()); return phase; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java index f3cc475aa5..ec7c321cd4 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java @@ -46,6 +46,8 @@ class Phase { private final Map binds = new LinkedHashMap<>(); + private final Map env = new LinkedHashMap<>(); + /** * Create a new {@link Phase} instance. * @param name the name of the phase @@ -91,6 +93,15 @@ class Phase { this.binds.put(source, dest); } + /** + * Update this phase with an additional environment variable. + * @param name the variable name + * @param value the variable value + */ + void withEnv(String name, String value) { + this.env.put(name, value); + } + /** * Return the name of the phase. * @return the phase name @@ -116,6 +127,7 @@ class Phase { update.withCommand("/cnb/lifecycle/" + this.name, StringUtils.toStringArray(this.args)); update.withLabel("author", "spring-boot"); this.binds.forEach(update::withBind); + this.env.forEach(update::withEnv); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java index d2d03941a9..1d91194938 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java @@ -39,6 +39,7 @@ import org.springframework.util.StringUtils; * Configuration used when creating a new container. * * @author Phillip Webb + * @author Scott Frederick * @since 2.3.0 */ public class ContainerConfig { @@ -46,7 +47,7 @@ public class ContainerConfig { private final String json; ContainerConfig(String user, ImageReference image, String command, List args, Map labels, - Map binds) throws IOException { + Map binds, Map env) throws IOException { Assert.notNull(image, "Image must not be null"); Assert.hasText(command, "Command must not be empty"); ObjectMapper objectMapper = SharedObjectMapper.get(); @@ -58,6 +59,8 @@ public class ContainerConfig { ArrayNode commandNode = node.putArray("Cmd"); commandNode.add(command); args.forEach(commandNode::add); + ArrayNode envNode = node.putArray("Env"); + env.forEach((name, value) -> envNode.add(name + "=" + value)); ObjectNode labelsNode = node.putObject("Labels"); labels.forEach(labelsNode::put); ObjectNode hostConfigNode = node.putObject("HostConfig"); @@ -109,6 +112,8 @@ public class ContainerConfig { private final Map binds = new LinkedHashMap<>(); + private final Map env = new LinkedHashMap<>(); + Update(ImageReference image) { this.image = image; } @@ -116,7 +121,8 @@ public class ContainerConfig { private ContainerConfig run(Consumer update) { update.accept(this); try { - return new ContainerConfig(this.user, this.image, this.command, this.args, this.labels, this.binds); + return new ContainerConfig(this.user, this.image, this.command, this.args, this.labels, this.binds, + this.env); } catch (IOException ex) { throw new IllegalStateException(ex); @@ -177,6 +183,15 @@ public class ContainerConfig { this.binds.put(source, dest); } + /** + * Update the container config with an additional environment variable. + * @param name the variable name + * @param value the variable value + */ + public void withEnv(String name, String value) { + this.env.put(name, value); + } + } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionTests.java index e2fd3b106f..e679b5bedd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionTests.java @@ -64,7 +64,7 @@ class ApiVersionTests { void assertSupportsWhenDoesNotSupportThrowsException() { assertThatIllegalStateException() .isThrownBy(() -> ApiVersion.parse("1.2").assertSupports(ApiVersion.parse("1.3"))) - .withMessage("Detected platform API version 'v1.3' does not match supported version 'v1.2'"); + .withMessage("Detected platform API version '1.3' does not match supported version '1.2'"); } @Test @@ -99,7 +99,7 @@ class ApiVersionTests { @Test void toStringReturnsString() { - assertThat(ApiVersion.parse("1.2").toString()).isEqualTo("v1.2"); + assertThat(ApiVersion.parse("1.2").toString()).isEqualTo("1.2"); } @Test diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionsTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionsTests.java index d516d25f44..421f2a1910 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionsTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/ApiVersionsTests.java @@ -29,20 +29,45 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; class ApiVersionsTests { @Test - void assertSupportsWhenAllSupports() { - ApiVersions.parse("1.1", "2.2").assertSupports(ApiVersion.parse("1.0")); + void findsLatestWhenOneMatchesMajor() { + ApiVersion version = ApiVersions.parse("1.1", "2.2").findLatestSupported("1.0"); + assertThat(version).isEqualTo(ApiVersion.parse("1.1")); } @Test - void assertSupportsWhenDoesNoneSupportedThrowsException() { + void findsLatestWhenOneMatchesWithReleaseVersions() { + ApiVersion version = ApiVersions.parse("1.1", "1.2").findLatestSupported("1.1"); + assertThat(version).isEqualTo(ApiVersion.parse("1.2")); + } + + @Test + void findsLatestWhenOneMatchesWithPreReleaseVersions() { + ApiVersion version = ApiVersions.parse("0.2", "0.3").findLatestSupported("0.2"); + assertThat(version).isEqualTo(ApiVersion.parse("0.2")); + } + + @Test + void findsLatestWhenMultipleMatchesWithReleaseVersions() { + ApiVersion version = ApiVersions.parse("1.1", "1.2").findLatestSupported("1.1", "1.2"); + assertThat(version).isEqualTo(ApiVersion.parse("1.2")); + } + + @Test + void findsLatestWhenMultipleMatchesWithPreReleaseVersions() { + ApiVersion version = ApiVersions.parse("0.2", "0.3").findLatestSupported("0.2", "0.3"); + assertThat(version).isEqualTo(ApiVersion.parse("0.3")); + } + + @Test + void findLatestWhenNoneSupportedThrowsException() { assertThatIllegalStateException() - .isThrownBy(() -> ApiVersions.parse("1.1", "1.2").assertSupports(ApiVersion.parse("1.3"))) - .withMessage("Detected platform API version 'v1.3' is not included in supported versions 'v1.1,v1.2'"); + .isThrownBy(() -> ApiVersions.parse("1.1", "1.2").findLatestSupported("1.3", "1.4")).withMessage( + "Detected platform API versions '1.3,1.4' are not included in supported versions '1.1,1.2'"); } @Test void toStringReturnsString() { - assertThat(ApiVersions.parse("1.1", "2.2", "3.3").toString()).isEqualTo("v1.1,v2.2,v3.3"); + assertThat(ApiVersions.parse("1.1", "2.2", "3.3").toString()).isEqualTo("1.1,2.2,3.3"); } @Test diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderMetadataTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderMetadataTests.java index d860acf90e..645e956047 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderMetadataTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderMetadataTests.java @@ -16,8 +16,12 @@ package org.springframework.boot.buildpack.platform.build; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.Collections; +import java.util.stream.Collectors; import org.junit.jupiter.api.Test; @@ -76,6 +80,28 @@ class BuilderMetadataTests extends AbstractJsonTests { .withMessage("No 'io.buildpacks.builder.metadata' label found in image config labels 'alpha'"); } + @Test + void fromJsonLoadsMetadataWithoutSupportedApis() throws IOException { + BuilderMetadata metadata = BuilderMetadata.fromJson(getContentAsString("builder-metadata.json")); + assertThat(metadata.getStack().getRunImage().getImage()).isEqualTo("cloudfoundry/run:base-cnb"); + assertThat(metadata.getStack().getRunImage().getMirrors()).isEmpty(); + assertThat(metadata.getLifecycle().getVersion()).isEqualTo("0.7.2"); + assertThat(metadata.getLifecycle().getApi().getBuildpack()).isEqualTo("0.2"); + assertThat(metadata.getLifecycle().getApi().getPlatform()).isEqualTo("0.3"); + assertThat(metadata.getLifecycle().getApis().getBuildpack()).isNull(); + assertThat(metadata.getLifecycle().getApis().getPlatform()).isNull(); + } + + @Test + void fromJsonLoadsMetadataWithSupportedApis() throws IOException { + BuilderMetadata metadata = BuilderMetadata.fromJson(getContentAsString("builder-metadata-supported-apis.json")); + assertThat(metadata.getLifecycle().getVersion()).isEqualTo("0.7.2"); + assertThat(metadata.getLifecycle().getApi().getBuildpack()).isEqualTo("0.2"); + assertThat(metadata.getLifecycle().getApi().getPlatform()).isEqualTo("0.4"); + assertThat(metadata.getLifecycle().getApis().getBuildpack()).containsExactly("0.1", "0.2", "0.3"); + assertThat(metadata.getLifecycle().getApis().getPlatform()).containsExactly("0.3", "0.4"); + } + @Test void copyWithUpdatedCreatedByReturnsNewMetadata() throws IOException { Image image = Image.of(getContent("image.json")); @@ -98,4 +124,9 @@ class BuilderMetadataTests extends AbstractJsonTests { .isEqualTo(metadata.getStack().getRunImage().getImage()); } + private String getContentAsString(String name) { + return new BufferedReader(new InputStreamReader(getContent(name), StandardCharsets.UTF_8)).lines() + .collect(Collectors.joining("\n")); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/LifecycleTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/LifecycleTests.java index 8219640663..b374de3d1a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/LifecycleTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/LifecycleTests.java @@ -129,6 +129,35 @@ class LifecycleTests { verify(this.docker.volume()).delete(name, true); } + @Test + void executeWhenPlatformApiNotSupportedThrowsException() throws Exception { + given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId()); + given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId()); + given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null)); + assertThatIllegalStateException() + .isThrownBy(() -> createLifecycle("builder-metadata-unsupported-api.json").execute()) + .withMessage("Detected platform API versions '0.2' are not included in supported versions '0.3'"); + } + + @Test + void executeWhenMultiplePlatformApisNotSupportedThrowsException() throws Exception { + given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId()); + given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId()); + given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null)); + assertThatIllegalStateException() + .isThrownBy(() -> createLifecycle("builder-metadata-unsupported-apis.json").execute()) + .withMessage("Detected platform API versions '0.4,0.5' are not included in supported versions '0.3'"); + } + + @Test + void executeWhenMultiplePlatformApisSupportedExecutesPhase() throws Exception { + given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId()); + given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId()); + given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null)); + createLifecycle("builder-metadata-supported-apis.json").execute(); + assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator.json")); + } + @Test void closeClearsVolumes() throws Exception { createLifecycle().close(); @@ -159,12 +188,25 @@ class LifecycleTests { private Lifecycle createLifecycle(BuildRequest request) throws IOException { EphemeralBuilder builder = mockEphemeralBuilder(); - return new TestLifecycle(BuildLog.to(this.out), this.docker, request, builder); + return createLifecycle(request, builder); + } + + private Lifecycle createLifecycle(String builderMetadata) throws IOException { + EphemeralBuilder builder = mockEphemeralBuilder(builderMetadata); + return createLifecycle(getTestRequest(), builder); + } + + private Lifecycle createLifecycle(BuildRequest request, EphemeralBuilder ephemeralBuilder) { + return new TestLifecycle(BuildLog.to(this.out), this.docker, request, ephemeralBuilder); } private EphemeralBuilder mockEphemeralBuilder() throws IOException { + return mockEphemeralBuilder("builder-metadata.json"); + } + + private EphemeralBuilder mockEphemeralBuilder(String builderMetadata) throws IOException { EphemeralBuilder builder = mock(EphemeralBuilder.class); - byte[] metadataContent = FileCopyUtils.copyToByteArray(getClass().getResourceAsStream("builder-metadata.json")); + byte[] metadataContent = FileCopyUtils.copyToByteArray(getClass().getResourceAsStream(builderMetadata)); BuilderMetadata metadata = BuilderMetadata.fromJson(new String(metadataContent, StandardCharsets.UTF_8)); given(builder.getName()).willReturn(ImageReference.of("pack.local/ephemeral-builder")); given(builder.getBuilderMetadata()).willReturn(metadata); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java index 60df1db5be..7f824ed0ce 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java @@ -117,4 +117,18 @@ class PhaseTests { verifyNoMoreInteractions(update); } + @Test + void applyWhenWithEnvUpdatesConfigurationWithEnv() { + Phase phase = new Phase("test", false); + phase.withEnv("name1", "value1"); + phase.withEnv("name2", "value2"); + Update update = mock(Update.class); + phase.apply(update); + verify(update).withCommand("/cnb/lifecycle/test"); + verify(update).withLabel("author", "spring-boot"); + verify(update).withEnv("name1", "value1"); + verify(update).withEnv("name2", "value2"); + verifyNoMoreInteractions(update); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfigTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfigTests.java index f72e68fce2..f8bd42f168 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfigTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfigTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException * Tests for {@link ContainerConfig}. * * @author Phillip Webb + * @author Scott Frederick */ class ContainerConfigTests extends AbstractJsonTests { @@ -56,6 +57,8 @@ class ContainerConfigTests extends AbstractJsonTests { update.withArgs("-h"); update.withLabel("spring", "boot"); update.withBind("bind-source", "bind-dest"); + update.withEnv("name1", "value1"); + update.withEnv("name2", "value2"); }); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); containerConfig.writeTo(outputStream); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-supported-apis.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-supported-apis.json new file mode 100644 index 0000000000..4a695f9766 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-supported-apis.json @@ -0,0 +1,43 @@ +{ + "description": "Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang", + "buildpacks": [ + { + "id": "org.cloudfoundry.springboot", + "version": "v1.2.13" + } + ], + "stack": { + "runImage": { + "image": "cloudfoundry/run:base-cnb", + "mirrors": null + } + }, + "lifecycle": { + "version": "0.7.2", + "api": { + "buildpack": "0.2", + "platform": "0.4" + }, + "apis": { + "buildpack": { + "deprecated": [], + "supported": [ + "0.1", + "0.2", + "0.3" + ] + }, + "platform": { + "deprecated": [], + "supported": [ + "0.3", + "0.4" + ] + } + } + }, + "createdBy": { + "name": "Pack CLI", + "version": "v0.9.0 (git sha: d42c384a39f367588f2653f2a99702db910e5ad7)" + } +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-unsupported-api.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-unsupported-api.json new file mode 100644 index 0000000000..f7a7ae9b39 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-unsupported-api.json @@ -0,0 +1,26 @@ +{ + "description": "Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang", + "buildpacks": [ + { + "id": "org.cloudfoundry.springboot", + "version": "v1.2.13" + } + ], + "stack": { + "runImage": { + "image": "cloudfoundry/run:base-cnb", + "mirrors": null + } + }, + "lifecycle": { + "version": "0.7.2", + "api": { + "buildpack": "0.2", + "platform": "0.2" + } + }, + "createdBy": { + "name": "Pack CLI", + "version": "v0.9.0 (git sha: d42c384a39f367588f2653f2a99702db910e5ad7)" + } +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-unsupported-apis.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-unsupported-apis.json new file mode 100644 index 0000000000..d4978b2335 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/builder-metadata-unsupported-apis.json @@ -0,0 +1,43 @@ +{ + "description": "Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang", + "buildpacks": [ + { + "id": "org.cloudfoundry.springboot", + "version": "v1.2.13" + } + ], + "stack": { + "runImage": { + "image": "cloudfoundry/run:base-cnb", + "mirrors": null + } + }, + "lifecycle": { + "version": "0.7.2", + "api": { + "buildpack": "0.2", + "platform": "0.3" + }, + "apis": { + "buildpack": { + "deprecated": [], + "supported": [ + "0.1", + "0.2", + "0.3" + ] + }, + "platform": { + "deprecated": [], + "supported": [ + "0.4", + "0.5" + ] + } + } + }, + "createdBy": { + "name": "Pack CLI", + "version": "v0.9.0 (git sha: d42c384a39f367588f2653f2a99702db910e5ad7)" + } +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator-clean-cache.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator-clean-cache.json index 4f1401b86b..62795c7409 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator-clean-cache.json +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator-clean-cache.json @@ -2,6 +2,7 @@ "User" : "root", "Image" : "pack.local/ephemeral-builder", "Cmd" : [ "/cnb/lifecycle/creator", "-app", "/workspace", "-platform", "/platform", "-run-image", "docker.io/cloudfoundry/run:latest", "-layers", "/layers", "-cache-dir", "/cache", "-launch-cache", "/launch-cache", "-daemon", "-skip-restore", "docker.io/library/my-application:latest" ], + "Env" : [ "CNB_PLATFORM_API=0.3" ], "Labels" : { "author" : "spring-boot" }, diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator.json index 3a70423361..d04ec56db3 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator.json +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/build/lifecycle-creator.json @@ -2,6 +2,7 @@ "User" : "root", "Image" : "pack.local/ephemeral-builder", "Cmd" : [ "/cnb/lifecycle/creator", "-app", "/workspace", "-platform", "/platform", "-run-image", "docker.io/cloudfoundry/run:latest", "-layers", "/layers", "-cache-dir", "/cache", "-launch-cache", "/launch-cache", "-daemon", "docker.io/library/my-application:latest" ], + "Env" : [ "CNB_PLATFORM_API=0.3" ], "Labels" : { "author" : "spring-boot" }, diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/container-config.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/container-config.json index 23abac3589..2c034b7767 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/container-config.json +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/container-config.json @@ -6,6 +6,10 @@ "-l", "-h" ], + "Env": [ + "name1=value1", + "name2=value2" + ], "Labels": { "spring": "boot" },