Add support for CNB platform API 0.4

This commit adds support for platform API 0.4 when invoking a CNB
builder in the Maven and Gradle plugins. If the builder advertises
that it supports platform API 0.4 then that version will be
requested when invoking lifecycle phases. Otherwise the plugins
will fall back to requesting platform API 0.3.

Requesting platform API 0.4 when invoking builder lifecycle phases
has the primary benefit of making it easier to pass command-line
arguments to the default process in the generated image.

Fixes gh-23692
This commit is contained in:
Scott Frederick 2020-10-19 17:33:40 -05:00
parent 38b1954ab1
commit 38984985d4
10 changed files with 183 additions and 12 deletions

View File

@ -32,7 +32,7 @@ final class ApiVersions {
/**
* The platform API versions supported by this release.
*/
static final ApiVersions SUPPORTED_PLATFORMS = new ApiVersions(ApiVersion.of(0, 3));
static final ApiVersions SUPPORTED_PLATFORMS = new ApiVersions(ApiVersion.of(0, 3), ApiVersion.of(0, 4));
private final ApiVersion[] apiVersions;

View File

@ -134,6 +134,9 @@ class Lifecycle implements Closeable {
if (this.request.isCleanCache()) {
phase.withArgs("-skip-restore");
}
if (requiresProcessTypeDefault()) {
phase.withArgs("-process-type=web");
}
phase.withArgs(this.request.getName());
phase.withBinds(this.layersVolume, Directory.LAYERS);
phase.withBinds(this.applicationVolume, Directory.APPLICATION);
@ -147,6 +150,10 @@ class Lifecycle implements Closeable {
return this.request.isVerboseLogging() && this.lifecycleVersion.isEqualOrGreaterThan(LOGGING_MINIMUM_VERSION);
}
private boolean requiresProcessTypeDefault() {
return this.platformVersion.supports(ApiVersion.of(0, 4));
}
private void run(Phase phase) throws IOException {
Consumer<LogUpdateEvent> logConsumer = this.log.runningPhase(this.request, phase.getName());
ContainerConfig containerConfig = ContainerConfig.of(this.builder.getName(), phase::apply);

View File

@ -87,7 +87,7 @@ class BuilderMetadataTests extends AbstractJsonTests {
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().getApi().getPlatform()).isEqualTo("0.4");
assertThat(metadata.getLifecycle().getApis().getBuildpack()).isNull();
assertThat(metadata.getLifecycle().getApis().getPlatform()).isNull();
}

View File

@ -88,6 +88,16 @@ class LifecycleTests {
assertThat(this.out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'");
}
@Test
void executeExecutesPhasesWithPlatformApi03() 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-platform-api-0.3.json").execute();
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-platform-api-0.3.json"));
assertThat(this.out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'");
}
@Test
void executeOnlyUploadsContentOnce() throws Exception {
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
@ -136,7 +146,7 @@ class LifecycleTests {
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'");
.withMessage("Detected platform API versions '0.2' are not included in supported versions '0.3,0.4'");
}
@Test
@ -145,8 +155,8 @@ class LifecycleTests {
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'");
.isThrownBy(() -> createLifecycle("builder-metadata-unsupported-apis.json").execute()).withMessage(
"Detected platform API versions '0.5,0.6' are not included in supported versions '0.3,0.4'");
}
@Test

View File

@ -0,0 +1,142 @@
{
"description": "Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang",
"buildpacks": [
{
"id": "org.cloudfoundry.googlestackdriver",
"version": "v1.1.11"
},
{
"id": "org.cloudfoundry.springboot",
"version": "v1.2.13"
},
{
"id": "org.cloudfoundry.debug",
"version": "v1.2.11"
},
{
"id": "org.cloudfoundry.tomcat",
"version": "v1.3.18"
},
{
"id": "org.cloudfoundry.go",
"version": "v0.0.4"
},
{
"id": "org.cloudfoundry.openjdk",
"version": "v1.2.14"
},
{
"id": "org.cloudfoundry.buildsystem",
"version": "v1.2.15"
},
{
"id": "org.cloudfoundry.jvmapplication",
"version": "v1.1.12"
},
{
"id": "org.cloudfoundry.springautoreconfiguration",
"version": "v1.1.11"
},
{
"id": "org.cloudfoundry.archiveexpanding",
"version": "v1.0.102"
},
{
"id": "org.cloudfoundry.jmx",
"version": "v1.1.12"
},
{
"id": "org.cloudfoundry.nodejs",
"version": "v2.0.8"
},
{
"id": "org.cloudfoundry.jdbc",
"version": "v1.1.14"
},
{
"id": "org.cloudfoundry.procfile",
"version": "v1.1.12"
},
{
"id": "org.cloudfoundry.dotnet-core",
"version": "v0.0.6"
},
{
"id": "org.cloudfoundry.azureapplicationinsights",
"version": "v1.1.12"
},
{
"id": "org.cloudfoundry.distzip",
"version": "v1.1.12"
},
{
"id": "org.cloudfoundry.dep",
"version": "0.0.101"
},
{
"id": "org.cloudfoundry.go-compiler",
"version": "0.0.105"
},
{
"id": "org.cloudfoundry.go-mod",
"version": "0.0.89"
},
{
"id": "org.cloudfoundry.node-engine",
"version": "0.0.163"
},
{
"id": "org.cloudfoundry.npm",
"version": "0.1.3"
},
{
"id": "org.cloudfoundry.yarn-install",
"version": "0.1.10"
},
{
"id": "org.cloudfoundry.dotnet-core-aspnet",
"version": "0.0.118"
},
{
"id": "org.cloudfoundry.dotnet-core-build",
"version": "0.0.68"
},
{
"id": "org.cloudfoundry.dotnet-core-conf",
"version": "0.0.115"
},
{
"id": "org.cloudfoundry.dotnet-core-runtime",
"version": "0.0.127"
},
{
"id": "org.cloudfoundry.dotnet-core-sdk",
"version": "0.0.122"
},
{
"id": "org.cloudfoundry.icu",
"version": "0.0.43"
},
{
"id": "org.cloudfoundry.node-engine",
"version": "0.0.158"
}
],
"stack": {
"runImage": {
"image": "cloudfoundry/run:base-cnb",
"mirrors": null
}
},
"lifecycle": {
"version": "0.7.2",
"api": {
"buildpack": "0.2",
"platform": "0.3"
}
},
"createdBy": {
"name": "Pack CLI",
"version": "v0.9.0 (git sha: d42c384a39f367588f2653f2a99702db910e5ad7)"
}
}

View File

@ -132,7 +132,7 @@
"version": "0.7.2",
"api": {
"buildpack": "0.2",
"platform": "0.3"
"platform": "0.4"
}
},
"createdBy": {

View File

@ -1,8 +1,8 @@
{
"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" ],
"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", "-process-type=web", "docker.io/library/my-application:latest" ],
"Env" : [ "CNB_PLATFORM_API=0.4" ],
"Labels" : {
"author" : "spring-boot"
},

View File

@ -0,0 +1,12 @@
{
"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"
},
"HostConfig" : {
"Binds" : [ "/var/run/docker.sock:/var/run/docker.sock", "pack-layers-aaaaaaaaaa:/layers", "pack-app-aaaaaaaaaa:/workspace", "pack-cache-b35197ac41ea.build:/cache", "pack-cache-b35197ac41ea.launch:/launch-cache" ]
}
}

View File

@ -1,8 +1,8 @@
{
"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" ],
"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", "-process-type=web", "docker.io/library/my-application:latest" ],
"Env" : [ "CNB_PLATFORM_API=0.4" ],
"Labels" : {
"author" : "spring-boot"
},