Commit 32d378a3 authored by Scott Frederick's avatar Scott Frederick

Use test harness for image building integration tests

This commit modifies the integration tests for the Maven and Gradle
image building goal and task to use a custom builder as a test harness
to verify that the plugins invoke the builder as expected.

Fixes gh-25838
parent b3af6d64
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -29,8 +29,6 @@ import org.gradle.testkit.runner.BuildResult; ...@@ -29,8 +29,6 @@ import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome; import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.springframework.boot.buildpack.platform.docker.DockerApi; import org.springframework.boot.buildpack.platform.docker.DockerApi;
import org.springframework.boot.buildpack.platform.docker.type.ImageName; import org.springframework.boot.buildpack.platform.docker.type.ImageName;
...@@ -61,14 +59,10 @@ class BootBuildImageIntegrationTests { ...@@ -61,14 +59,10 @@ class BootBuildImageIntegrationTests {
String projectName = this.gradleBuild.getProjectDir().getName(); String projectName = this.gradleBuild.getProjectDir().getName();
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.getOutput()).contains("docker.io/library/" + projectName); assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
assertThat(result.getOutput()).contains("paketo-buildpacks/builder"); assertThat(result.getOutput()).contains("---> Test Info buildpack building");
ImageReference imageReference = ImageReference.of(ImageName.of(projectName)); assertThat(result.getOutput()).contains("env: BP_JVM_VERSION=8.*");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) { assertThat(result.getOutput()).contains("---> Test Info buildpack done");
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); removeImage(projectName);
}
finally {
new DockerApi().image().remove(imageReference, false);
}
} }
@TestTemplate @TestTemplate
...@@ -78,14 +72,10 @@ class BootBuildImageIntegrationTests { ...@@ -78,14 +72,10 @@ class BootBuildImageIntegrationTests {
BuildResult result = this.gradleBuild.build("bootBuildImage"); BuildResult result = this.gradleBuild.build("bootBuildImage");
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.getOutput()).contains("example/test-image-name"); assertThat(result.getOutput()).contains("example/test-image-name");
assertThat(result.getOutput()).contains("paketo-buildpacks/builder"); assertThat(result.getOutput()).contains("---> Test Info buildpack building");
ImageReference imageReference = ImageReference.of(ImageName.of("example/test-image-name")); assertThat(result.getOutput()).contains("env: BP_JVM_VERSION=8.*");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) { assertThat(result.getOutput()).contains("---> Test Info buildpack done");
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); removeImage("example/test-image-name");
}
finally {
new DockerApi().image().remove(imageReference, false);
}
} }
@TestTemplate @TestTemplate
...@@ -95,15 +85,12 @@ class BootBuildImageIntegrationTests { ...@@ -95,15 +85,12 @@ class BootBuildImageIntegrationTests {
BuildResult result = this.gradleBuild.build("bootBuildImage"); BuildResult result = this.gradleBuild.build("bootBuildImage");
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.getOutput()).contains("example/test-image-custom"); assertThat(result.getOutput()).contains("example/test-image-custom");
assertThat(result.getOutput()).contains("paketobuildpacks/builder:full"); assertThat(result.getOutput())
assertThat(result.getOutput()).contains("paketobuildpacks/run:full-cnb"); .contains("projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1");
ImageReference imageReference = ImageReference.of(ImageName.of("example/test-image-custom")); assertThat(result.getOutput()).contains("projects.registry.vmware.com/springboot/run:tiny-cnb");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) { assertThat(result.getOutput()).contains("---> Test Info buildpack building");
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); assertThat(result.getOutput()).contains("---> Test Info buildpack done");
} removeImage("example/test-image-custom");
finally {
new DockerApi().image().remove(imageReference, false);
}
} }
@TestTemplate @TestTemplate
...@@ -111,18 +98,16 @@ class BootBuildImageIntegrationTests { ...@@ -111,18 +98,16 @@ class BootBuildImageIntegrationTests {
writeMainClass(); writeMainClass();
writeLongNameResource(); writeLongNameResource();
BuildResult result = this.gradleBuild.build("bootBuildImage", "--imageName=example/test-image-cmd", BuildResult result = this.gradleBuild.build("bootBuildImage", "--imageName=example/test-image-cmd",
"--builder=paketobuildpacks/builder:full", "--runImage=paketobuildpacks/run:full-cnb"); "--builder=projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1",
"--runImage=projects.registry.vmware.com/springboot/run:tiny-cnb");
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.getOutput()).contains("example/test-image-cmd"); assertThat(result.getOutput()).contains("example/test-image-cmd");
assertThat(result.getOutput()).contains("paketobuildpacks/builder:full"); assertThat(result.getOutput())
assertThat(result.getOutput()).contains("paketobuildpacks/run:full-cnb"); .contains("projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1");
ImageReference imageReference = ImageReference.of(ImageName.of("example/test-image-cmd")); assertThat(result.getOutput()).contains("projects.registry.vmware.com/springboot/run:tiny-cnb");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) { assertThat(result.getOutput()).contains("---> Test Info buildpack building");
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); assertThat(result.getOutput()).contains("---> Test Info buildpack done");
} removeImage("example/test-image-cmd");
finally {
new DockerApi().image().remove(imageReference, false);
}
} }
@TestTemplate @TestTemplate
...@@ -140,6 +125,7 @@ class BootBuildImageIntegrationTests { ...@@ -140,6 +125,7 @@ class BootBuildImageIntegrationTests {
writeLongNameResource(); writeLongNameResource();
BuildResult result = this.gradleBuild.buildAndFail("bootBuildImage"); BuildResult result = this.gradleBuild.buildAndFail("bootBuildImage");
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.FAILED); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.FAILED);
assertThat(result.getOutput()).contains("Forced builder failure");
assertThat(result.getOutput()).containsPattern("Builder lifecycle '.*' failed with status code"); assertThat(result.getOutput()).containsPattern("Builder lifecycle '.*' failed with status code");
} }
...@@ -170,17 +156,12 @@ class BootBuildImageIntegrationTests { ...@@ -170,17 +156,12 @@ class BootBuildImageIntegrationTests {
String projectName = this.gradleBuild.getProjectDir().getName(); String projectName = this.gradleBuild.getProjectDir().getName();
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(result.getOutput()).contains("docker.io/library/" + projectName); assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
assertThat(result.getOutput()).contains("paketo-buildpacks/builder"); assertThat(result.getOutput()).contains("---> Test Info buildpack building");
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs"); File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
assertThat(buildLibs.listFiles()) assertThat(buildLibs.listFiles())
.containsExactly(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war")); .containsExactly(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"));
ImageReference imageReference = ImageReference.of(ImageName.of(projectName)); removeImage(projectName);
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
new DockerApi().image().remove(imageReference, false);
}
} }
private void writeMainClass() { private void writeMainClass() {
...@@ -222,4 +203,9 @@ class BootBuildImageIntegrationTests { ...@@ -222,4 +203,9 @@ class BootBuildImageIntegrationTests {
} }
} }
private void removeImage(String name) throws IOException {
ImageReference imageReference = ImageReference.of(ImageName.of(name));
new DockerApi().image().remove(imageReference, false);
}
} }
...@@ -8,6 +8,6 @@ targetCompatibility = '1.8' ...@@ -8,6 +8,6 @@ targetCompatibility = '1.8'
bootBuildImage { bootBuildImage {
imageName = "example/test-image-custom" imageName = "example/test-image-custom"
builder = "paketobuildpacks/builder:full" builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
runImage = "paketobuildpacks/run:full-cnb" runImage = "projects.registry.vmware.com/springboot/run:tiny-cnb"
} }
...@@ -8,4 +8,5 @@ targetCompatibility = '1.8' ...@@ -8,4 +8,5 @@ targetCompatibility = '1.8'
bootBuildImage { bootBuildImage {
imageName = "example/test-image-name" imageName = "example/test-image-name"
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
} }
...@@ -9,3 +9,7 @@ bootBuildImage { ...@@ -9,3 +9,7 @@ bootBuildImage {
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
targetCompatibility = '1.8' targetCompatibility = '1.8'
bootBuildImage {
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
}
\ No newline at end of file
...@@ -7,5 +7,6 @@ sourceCompatibility = '1.8' ...@@ -7,5 +7,6 @@ sourceCompatibility = '1.8'
targetCompatibility = '1.8' targetCompatibility = '1.8'
bootBuildImage { bootBuildImage {
environment = ["BP_JVM_VERSION": "13.9.9"] builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
environment = ["FORCE_FAILURE": "true"]
} }
...@@ -9,3 +9,7 @@ targetCompatibility = '1.8' ...@@ -9,3 +9,7 @@ targetCompatibility = '1.8'
bootJar { bootJar {
launchScript() launchScript()
} }
bootBuildImage {
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
}
...@@ -9,3 +9,7 @@ if (project.hasProperty('applyWarPlugin')) { ...@@ -9,3 +9,7 @@ if (project.hasProperty('applyWarPlugin')) {
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
targetCompatibility = '1.8' targetCompatibility = '1.8'
bootBuildImage {
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
}
...@@ -16,21 +16,15 @@ ...@@ -16,21 +16,15 @@
package org.springframework.boot.maven; package org.springframework.boot.maven;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Random; import java.util.Random;
import java.util.stream.Collectors;
import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.springframework.boot.buildpack.platform.docker.DockerApi; import org.springframework.boot.buildpack.platform.docker.DockerApi;
import org.springframework.boot.buildpack.platform.docker.type.ImageName; import org.springframework.boot.buildpack.platform.docker.type.ImageName;
...@@ -56,16 +50,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -56,16 +50,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
assertThat(jar).isFile(); assertThat(jar).isFile();
File original = new File(project, "target/build-image-0.0.1.BUILD-SNAPSHOT.jar.original"); File original = new File(project, "target/build-image-0.0.1.BUILD-SNAPSHOT.jar.original");
assertThat(original).doesNotExist(); assertThat(original).doesNotExist();
assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image:0.0.1.BUILD-SNAPSHOT")
.contains("Successfully built image"); .contains("---> Test Info buildpack building").contains("env: BP_JVM_VERSION=8.*")
ImageReference imageReference = ImageReference.of(ImageName.of("build-image"), "0.0.1.BUILD-SNAPSHOT"); .contains("---> Test Info buildpack done").contains("Successfully built image");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) { removeImage("build-image", "0.0.1.BUILD-SNAPSHOT");
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -79,15 +68,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -79,15 +68,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
assertThat(classifier).doesNotExist(); assertThat(classifier).doesNotExist();
assertThat(buildLog(project)).contains("Building image") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-classifier:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-classifier:0.0.1.BUILD-SNAPSHOT")
.contains("Successfully built image"); .contains("---> Test Info buildpack building").contains("env: BP_JVM_VERSION=8.*")
ImageReference imageReference = ImageReference.of(ImageName.of("build-image-classifier"), .contains("---> Test Info buildpack done").contains("Successfully built image");
"0.0.1.BUILD-SNAPSHOT"); removeImage("build-image-classifier", "0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -103,15 +86,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -103,15 +86,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
assertThat(original).doesNotExist(); assertThat(original).doesNotExist();
assertThat(buildLog(project)).contains("Building image") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-classifier-source:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-classifier-source:0.0.1.BUILD-SNAPSHOT")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference.of(ImageName.of("build-image-classifier-source"), removeImage("build-image-classifier-source", "0.0.1.BUILD-SNAPSHOT");
"0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -124,17 +101,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -124,17 +101,11 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
File original = new File(project, File original = new File(project,
"target/build-image-with-repackage-0.0.1.BUILD-SNAPSHOT.jar.original"); "target/build-image-with-repackage-0.0.1.BUILD-SNAPSHOT.jar.original");
assertThat(original).isFile(); assertThat(original).isFile();
assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-with-repackage:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-with-repackage:0.0.1.BUILD-SNAPSHOT")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference.of(ImageName.of("build-image-with-repackage"), removeImage("build-image-with-repackage", "0.0.1.BUILD-SNAPSHOT");
"0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -150,15 +121,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -150,15 +121,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
assertThat(original).isFile(); assertThat(original).isFile();
assertThat(buildLog(project)).contains("Building image") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-classifier-with-repackage:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-classifier-with-repackage:0.0.1.BUILD-SNAPSHOT")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference removeImage("build-image-classifier-with-repackage", "0.0.1.BUILD-SNAPSHOT");
.of(ImageName.of("build-image-classifier-with-repackage"), "0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -174,15 +139,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -174,15 +139,9 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
assertThat(original).isFile(); assertThat(original).isFile();
assertThat(buildLog(project)).contains("Building image").contains( assertThat(buildLog(project)).contains("Building image").contains(
"docker.io/library/build-image-classifier-source-with-repackage:0.0.1.BUILD-SNAPSHOT") "docker.io/library/build-image-classifier-source-with-repackage:0.0.1.BUILD-SNAPSHOT")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference removeImage("build-image-classifier-source-with-repackage", "0.0.1.BUILD-SNAPSHOT");
.of(ImageName.of("build-image-classifier-source-with-repackage"), "0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -198,53 +157,40 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -198,53 +157,40 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
assertThat(original).doesNotExist(); assertThat(original).doesNotExist();
assertThat(buildLog(project)).contains("Building image") assertThat(buildLog(project)).contains("Building image")
.contains("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT") .contains("example.com/test/build-image:0.0.1.BUILD-SNAPSHOT")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference removeImage("example.com/test/build-image", "0.0.1.BUILD-SNAPSHOT");
.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 @TestTemplate
void whenBuildImageIsInvokedWithCommandLineParameters(MavenBuild mavenBuild) { void whenBuildImageIsInvokedWithCommandLineParameters(MavenBuild mavenBuild) {
mavenBuild.project("build-image").goals("package") mavenBuild.project("build-image-cmd-line").goals("package")
.systemProperty("spring-boot.build-image.imageName", "example.com/test/cmd-property-name:v1") .systemProperty("spring-boot.build-image.imageName", "example.com/test/cmd-property-name:v1")
.systemProperty("spring-boot.build-image.builder", "paketobuildpacks/builder:full") .systemProperty("spring-boot.build-image.builder",
.systemProperty("spring-boot.build-image.runImage", "paketobuildpacks/run:full-cnb") "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1")
.systemProperty("spring-boot.build-image.runImage",
"projects.registry.vmware.com/springboot/run:tiny-cnb")
.execute((project) -> { .execute((project) -> {
assertThat(buildLog(project)).contains("Building image") assertThat(buildLog(project)).contains("Building image")
.contains("example.com/test/cmd-property-name:v1").contains("paketobuildpacks/builder:full") .contains("example.com/test/cmd-property-name:v1").contains("spring-boot-cnb-builder:0.0.1")
.contains("paketobuildpacks/run:full-cnb").contains("Successfully built image"); .contains("projects.registry.vmware.com/springboot/run:tiny-cnb")
ImageReference imageReference = ImageReference.of("example.com/test/cmd-property-name:v1"); .contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) { .contains("Successfully built image");
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start(); removeImage("example.com/test/cmd-property-name", "v1");
}
finally {
removeImage(imageReference);
}
}); });
} }
@TestTemplate @TestTemplate
void whenBuildImageIsInvokedWithCustomBuilderImageAndRunImage(MavenBuild mavenBuild) { void whenBuildImageIsInvokedWithCustomBuilderImageAndRunImage(MavenBuild mavenBuild) {
mavenBuild.project("build-image-custom-builder").goals("package").execute((project) -> { mavenBuild.project("build-image-custom-builder").goals("package").execute((project) -> {
assertThat(buildLog(project)).contains("Building image").contains("paketobuildpacks/builder:full") assertThat(buildLog(project)).contains("Building image")
.contains("paketobuildpacks/run:full-cnb")
.contains("docker.io/library/build-image-v2-builder:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-v2-builder:0.0.1.BUILD-SNAPSHOT")
.contains("projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1")
.contains("projects.registry.vmware.com/springboot/run:tiny-cnb")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference removeImage("docker.io/library/build-image-v2-builder", "0.0.1.BUILD-SNAPSHOT");
.of("docker.io/library/build-image-v2-builder:0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -252,45 +198,25 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -252,45 +198,25 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
void whenBuildImageIsInvokedWithEmptyEnvEntry(MavenBuild mavenBuild) { void whenBuildImageIsInvokedWithEmptyEnvEntry(MavenBuild mavenBuild) {
mavenBuild.project("build-image-empty-env-entry").goals("package").prepare(this::writeLongNameResource) mavenBuild.project("build-image-empty-env-entry").goals("package").prepare(this::writeLongNameResource)
.execute((project) -> { .execute((project) -> {
assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-empty-env-entry:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-empty-env-entry:0.0.1.BUILD-SNAPSHOT")
.contains("---> Test Info buildpack building").contains("---> Test Info buildpack done")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference.of(ImageName.of("build-image-empty-env-entry"), removeImage("build-image-empty-env-entry", "0.0.1.BUILD-SNAPSHOT");
"0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
}
finally {
removeImage(imageReference);
}
}); });
} }
@TestTemplate @TestTemplate
void whenBuildImageIsInvokedWithZipPackaging(MavenBuild mavenBuild) { void whenBuildImageIsInvokedWithZipPackaging(MavenBuild mavenBuild) {
mavenBuild.project("build-image-zip-packaging"); mavenBuild.project("build-image-zip-packaging").goals("package").prepare(this::writeLongNameResource)
mavenBuild.goals("package"); .execute((project) -> {
mavenBuild.prepare(this::writeLongNameResource);
mavenBuild.execute((project) -> {
File jar = new File(project, "target/build-image-zip-packaging-0.0.1.BUILD-SNAPSHOT.jar"); File jar = new File(project, "target/build-image-zip-packaging-0.0.1.BUILD-SNAPSHOT.jar");
assertThat(jar).isFile(); assertThat(jar).isFile();
assertThat(buildLog(project)).contains("Building image").contains("paketo-buildpacks/builder") assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-zip-packaging:0.0.1.BUILD-SNAPSHOT") .contains("docker.io/library/build-image-zip-packaging:0.0.1.BUILD-SNAPSHOT")
.contains("Main-Class: org.springframework.boot.loader.PropertiesLauncher")
.contains("Successfully built image"); .contains("Successfully built image");
ImageReference imageReference = ImageReference.of(ImageName.of("build-image-zip-packaging"), removeImage("build-image-zip-packaging", "0.0.1.BUILD-SNAPSHOT");
"0.0.1.BUILD-SNAPSHOT");
try (GenericContainer<?> container = new GenericContainer<>(imageReference.toString())) {
container.waitingFor(Wait.forLogMessage("Launched\\n", 1)).start();
container.copyFileFromContainer("/workspace/META-INF/MANIFEST.MF", (inputStream) -> {
String text = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines()
.collect(Collectors.joining("\n"));
assertThat(text).contains("Main-Class: org.springframework.boot.loader.PropertiesLauncher");
return null;
});
}
finally {
removeImage(imageReference);
}
}); });
} }
...@@ -298,6 +224,7 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -298,6 +224,7 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
void failsWhenBuilderFails(MavenBuild mavenBuild) { void failsWhenBuilderFails(MavenBuild mavenBuild) {
mavenBuild.project("build-image-builder-error").goals("package") mavenBuild.project("build-image-builder-error").goals("package")
.executeAndFail((project) -> assertThat(buildLog(project)).contains("Building image") .executeAndFail((project) -> assertThat(buildLog(project)).contains("Building image")
.contains("---> Test Info buildpack building").contains("Forced builder failure")
.containsPattern("Builder lifecycle '.*' failed with status code")); .containsPattern("Builder lifecycle '.*' failed with status code"));
} }
...@@ -327,7 +254,8 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests { ...@@ -327,7 +254,8 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
} }
} }
private void removeImage(ImageReference imageReference) { private void removeImage(String name, String version) {
ImageReference imageReference = ImageReference.of(ImageName.of(name), version);
try { try {
new DockerApi().image().remove(imageReference, false); new DockerApi().image().remove(imageReference, false);
} }
......
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
</goals> </goals>
<configuration> <configuration>
<image> <image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
<env> <env>
<BP_JVM_VERSION>13.9.9</BP_JVM_VERSION> <FORCE_FAILURE>true</FORCE_FAILURE>
</env> </env>
</image> </image>
</configuration> </configuration>
......
...@@ -43,6 +43,11 @@ ...@@ -43,6 +43,11 @@
<goals> <goals>
<goal>build-image</goal> <goal>build-image</goal>
</goals> </goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
......
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
<goals> <goals>
<goal>build-image</goal> <goal>build-image</goal>
</goals> </goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
......
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
<goals> <goals>
<goal>build-image</goal> <goal>build-image</goal>
</goals> </goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
<goals> <goals>
<goal>build-image</goal> <goal>build-image</goal>
</goals> </goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot.maven.it</groupId>
<artifactId>build-image</artifactId>
<version>0.0.1.BUILD-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>@java.version@</maven.compiler.source>
<maven.compiler.target>@java.version@</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.test;
public class SampleApplication {
public static void main(String[] args) throws Exception {
System.out.println("Launched");
synchronized(args) {
args.wait(); // Prevent exit"
}
}
}
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
</goals> </goals>
<configuration> <configuration>
<image> <image>
<builder>paketobuildpacks/builder:full</builder> <builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
<runImage>paketobuildpacks/run:full-cnb</runImage> <runImage>projects.registry.vmware.com/springboot/run:tiny-cnb</runImage>
</image> </image>
</configuration> </configuration>
</execution> </execution>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
</goals> </goals>
<configuration> <configuration>
<image> <image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
<name>example.com/test/build-image:${project.version}</name> <name>example.com/test/build-image:${project.version}</name>
</image> </image>
</configuration> </configuration>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
</goals> </goals>
<configuration> <configuration>
<image> <image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
<env> <env>
<EMPTY_KEY></EMPTY_KEY> <EMPTY_KEY></EMPTY_KEY>
</env> </env>
......
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
</goals> </goals>
<configuration> <configuration>
<finalName>final-name</finalName> <finalName>final-name</finalName>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
......
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
<goals> <goals>
<goal>build-image</goal> <goal>build-image</goal>
</goals> </goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
</executions> </executions>
<configuration> <configuration>
<layout>ZIP</layout> <layout>ZIP</layout>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
......
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
<goals> <goals>
<goal>build-image</goal> <goal>build-image</goal>
</goals> </goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
</image>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
......
= Spring Boot Test Builder
This directory contains a Cloud Native Buildpacks https://buildpacks.io/docs/concepts/components/builder/[builder] and https://buildpacks.io/docs/concepts/components/buildpack/[buildpack] that is used by integration tests to verify the behavior of the Spring Boot build plugins.
== Creating the builder
* Install the https://buildpacks.io/docs/install-pack/[pack CLI]
* Authenticate to projects.registry.vmware.com via `docker login`
* Use the `build.sh` create the necessary images and push them to the registry
#!/usr/bin/env bash
set -x -eo pipefail
docker pull paketobuildpacks/build:tiny-cnb
docker tag paketobuildpacks/build:tiny-cnb projects.registry.vmware.com/springboot/build:tiny-cnb
docker push projects.registry.vmware.com/springboot/build:tiny-cnb
docker pull paketobuildpacks/run:tiny-cnb
docker tag paketobuildpacks/run:tiny-cnb projects.registry.vmware.com/springboot/run:tiny-cnb
docker push projects.registry.vmware.com/springboot/run:tiny-cnb
cd builder
pack builder create projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1 --config builder.toml
docker push projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1
cd -
\ No newline at end of file
# Buildpacks to include in builder
[[buildpacks]]
id = "spring-boot/test-info"
version = "0.0.1"
uri = "../buildpacks/test-info"
# Order used for detection
[[order]]
[[order.group]]
id = "spring-boot/test-info"
version = "0.0.1"
# Stack that will be used by the builder
[stack]
id = "io.paketo.stacks.tiny"
build-image = "projects.registry.vmware.com/springboot/build:tiny-cnb"
run-image = "projects.registry.vmware.com/springboot/run:tiny-cnb"
#!/usr/bin/env bash
set -eo pipefail
echo "---> Test Info buildpack building"
# INPUT ARGUMENTS
platform_dir=$2
env_dir=${platform_dir}/env
bindings_dir=${platform_dir}/bindings
if [[ -f ${env_dir}/FORCE_FAILURE ]]; then
echo "Forced builder failure"
exit 1
fi
if compgen -G "${env_dir}/*" > /dev/null; then
for var in ${env_dir}/*; do
echo "env: $(basename ${var})=$(<${var})"
done
fi
if compgen -G "${bindings_dir}/*" > /dev/null; then
for binding in ${bindings_dir}/*; do
for f in ${binding}/*; do
echo "binding: $(basename ${binding})/$(basename ${f})=$(<${f})"
done
done
fi
echo "META-INF/MANIFEST.MF: "
if [[ -f META-INF/MANIFEST.MF ]]; then
cat META-INF/MANIFEST.MF
fi
echo "---> Test Info buildpack done"
#!/usr/bin/env bash
set -eo pipefail
# 1. CHECK IF APPLICABLE
if [[ ! -f META-INF/MANIFEST.MF ]]; then
exit 100
fi
# 2. GET ARGS
plan_path=$2
# 3. DECLARE DEPENDENCIES (OPTIONAL)
cat >> "${plan_path}" <<EOL
# Buildpack provides this dependency
#
# NOTE: The dependency is provided during the 'build' process.
#
[[provides]]
name = "test-info"
# Buildpack requires this dependency
#
# NOTE: Everything aside from 'name' is simply additional information that the providing buildpack can use to resolve
# the dependency.
#
[[requires]]
name = "test-info"
EOL
\ No newline at end of file
# Buildpack API version
api = "0.2"
# Buildpack ID and metadata
[buildpack]
id = "spring-boot/test-info"
version = "0.0.1"
name = "Spring Boot Test Info Buildpack"
homepage = "https://github.com/spring-projects/spring-boot"
# Stacks that the buildpack will work with
[[stacks]]
id = "io.paketo.stacks.tiny"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment