Polish "Add option to customize cache volume names when building an image"
See gh-28292
This commit is contained in:
@@ -181,10 +181,15 @@ The value supplied will be passed unvalidated to Docker when creating the builde
|
||||
| A list of one or more additional tags to apply to the generated image.
|
||||
|
|
||||
|
||||
| `cacheVolumeNames`
|
||||
| `buildCache`
|
||||
|
|
||||
| Cache volume names that should be used by the builder instead of generating random names.
|
||||
| A cache containing layers created by buildpacks and used by the image building process.
|
||||
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||
|
||||
| `launchCache`
|
||||
|
|
||||
| A cache containing layers created by buildpacks and used by the image launching process.
|
||||
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||
|
||||
|===
|
||||
|
||||
@@ -384,10 +389,30 @@ The publish option can be specified on the command line as well, as shown in thi
|
||||
$ gradle bootBuildImage --imageName=docker.example.com/library/my-app:v1 --publishImage
|
||||
----
|
||||
|
||||
[[build-image.examples.caches]]
|
||||
=== Builder Cache Configuration
|
||||
|
||||
The CNB builder caches layers that are used when building and launching an image.
|
||||
By default, these caches are stored as named volumes in the Docker daemon with names that are derived from the full name of the target image.
|
||||
If the image name changes frequently, for example when the project version is used as a tag in the image name, then the caches can be invalidated frequently.
|
||||
|
||||
The cache volumes can be configured to use alternative names to give more control over cache lifecycle as shown in the following example:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
|
||||
.Groovy
|
||||
----
|
||||
include::../gradle/packaging/boot-build-image-caches.gradle[tags=caches]
|
||||
----
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
include::../gradle/packaging/boot-build-image-caches.gradle.kts[tags=caches]
|
||||
----
|
||||
|
||||
[[build-image.examples.docker]]
|
||||
=== Docker Configuration
|
||||
|
||||
If you need the plugin to communicate with the Docker daemon using a remote connection instead of the default local connection, the connection details can be provided using `docker` properties as shown in the following example:
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '{gradle-project-version}'
|
||||
}
|
||||
|
||||
bootJar {
|
||||
mainClass = 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::cacheVolumeNames[]
|
||||
bootBuildImage {
|
||||
cacheVolumeNames = [
|
||||
"build": "example-build-cachevol",
|
||||
"launch": "example-launch-cachevol"
|
||||
]
|
||||
}
|
||||
// end::cacheVolumeNames[]
|
||||
|
||||
task bootBuildImageCacheVolumeNames {
|
||||
doFirst {
|
||||
bootBuildImage.cacheVolumeNames.each { type, name -> println "$type=$name" }
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage
|
||||
|
||||
plugins {
|
||||
java
|
||||
id("org.springframework.boot") version "{gradle-project-version}"
|
||||
}
|
||||
|
||||
// tag::cacheVolumeNames[]
|
||||
tasks.getByName<BootBuildImage>("bootBuildImage") {
|
||||
cacheVolumeNames = mapOf("build" to "example-build-cachevol",
|
||||
"launch" to "example-launch-cachevol")
|
||||
}
|
||||
// end::cacheVolumeNames[]
|
||||
|
||||
tasks.register("bootBuildImageEnvironment") {
|
||||
doFirst {
|
||||
for((type, name) in tasks.getByName<BootBuildImage>("bootBuildImage").cacheVolumeNames) {
|
||||
print(type + "=" + name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '{gradle-project-version}'
|
||||
}
|
||||
|
||||
bootJar {
|
||||
mainClass = 'com.example.ExampleApplication'
|
||||
}
|
||||
|
||||
// tag::caches[]
|
||||
bootBuildImage {
|
||||
buildCache {
|
||||
volume {
|
||||
name = "cache-${rootProject.name}.build"
|
||||
}
|
||||
}
|
||||
launchCache {
|
||||
volume {
|
||||
name = "cache-${rootProject.name}.launch"
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::caches[]
|
||||
|
||||
task bootBuildImageCaches {
|
||||
doFirst {
|
||||
bootBuildImage.buildCache.asCache().with { println "buildCache=$name" }
|
||||
bootBuildImage.launchCache.asCache().with { println "launchCache=$name" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage
|
||||
|
||||
plugins {
|
||||
java
|
||||
id("org.springframework.boot") version "{gradle-project-version}"
|
||||
}
|
||||
|
||||
// tag::caches[]
|
||||
tasks.getByName<BootBuildImage>("bootBuildImage") {
|
||||
buildCache {
|
||||
volume {
|
||||
name = "cache-${rootProject.name}.build"
|
||||
}
|
||||
}
|
||||
launchCache {
|
||||
volume {
|
||||
name = "cache-${rootProject.name}.launch"
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::caches[]
|
||||
|
||||
tasks.register("bootBuildImageCaches") {
|
||||
doFirst {
|
||||
println("buildCache=" + tasks.getByName<BootBuildImage>("bootBuildImage").buildCache.asCache().volume.name)
|
||||
println("launchCache=" + tasks.getByName<BootBuildImage>("bootBuildImage").launchCache.asCache().volume.name)
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,9 @@ public class BootBuildImage extends DefaultTask {
|
||||
|
||||
private final ListProperty<String> tags;
|
||||
|
||||
private Map<String, String> cacheVolumeNames = new HashMap<>();
|
||||
private final CacheSpec buildCache = new CacheSpec();
|
||||
|
||||
private final CacheSpec launchCache = new CacheSpec();
|
||||
|
||||
private final DockerSpec docker = new DockerSpec();
|
||||
|
||||
@@ -420,41 +422,6 @@ public class BootBuildImage extends DefaultTask {
|
||||
this.tags.addAll(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache volume names that will be used when building the image.
|
||||
* @return the cache volume names
|
||||
*/
|
||||
@Input
|
||||
@Optional
|
||||
public Map<String, String> getCacheVolumeNames() {
|
||||
return this.cacheVolumeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache volume names that will be used when building the image.
|
||||
* @param cacheVolumeNames the cache volume names
|
||||
*/
|
||||
public void setCacheVolumeNames(Map<String, String> cacheVolumeNames) {
|
||||
this.cacheVolumeNames = cacheVolumeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to cache volume names that will be used when building the image.
|
||||
* @param type the type of the entry
|
||||
* @param name the name of the entry
|
||||
*/
|
||||
public void cacheVolumeName(String type, String name) {
|
||||
this.cacheVolumeNames.put(type, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entries to cache volume names that will be used when building the image.
|
||||
* @param entries the entries to add to cache volume names
|
||||
*/
|
||||
public void cacheVolumeNames(Map<String, String> entries) {
|
||||
this.cacheVolumeNames.putAll(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the network the build container will connect to.
|
||||
* @return the network
|
||||
@@ -474,6 +441,62 @@ public class BootBuildImage extends DefaultTask {
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the build cache that will be used when building the image.
|
||||
* @return the cache
|
||||
*/
|
||||
@Nested
|
||||
@Optional
|
||||
public CacheSpec getBuildCache() {
|
||||
return this.buildCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the {@link CacheSpec} for the build cache using the given
|
||||
* {@code action}.
|
||||
* @param action the action
|
||||
*/
|
||||
public void buildCache(Action<CacheSpec> action) {
|
||||
action.execute(this.buildCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the {@link CacheSpec} for the build cache using the given
|
||||
* {@code closure}.
|
||||
* @param closure the closure
|
||||
*/
|
||||
public void buildCache(Closure<?> closure) {
|
||||
buildCache(ConfigureUtil.configureUsing(closure));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the launch cache that will be used when building the image.
|
||||
* @return the cache
|
||||
*/
|
||||
@Nested
|
||||
@Optional
|
||||
public CacheSpec getLaunchCache() {
|
||||
return this.launchCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the {@link CacheSpec} for the launch cache using the given
|
||||
* {@code action}.
|
||||
* @param action the action
|
||||
*/
|
||||
public void launchCache(Action<CacheSpec> action) {
|
||||
action.execute(this.launchCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the {@link CacheSpec} for the launch cache using the given
|
||||
* {@code closure}.
|
||||
* @param closure the closure
|
||||
*/
|
||||
public void launchCache(Closure<?> closure) {
|
||||
launchCache(ConfigureUtil.configureUsing(closure));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Docker configuration the builder will use.
|
||||
* @return docker configuration.
|
||||
@@ -537,7 +560,7 @@ public class BootBuildImage extends DefaultTask {
|
||||
request = customizeBuildpacks(request);
|
||||
request = customizeBindings(request);
|
||||
request = customizeTags(request);
|
||||
request = customizeCacheVolumeNames(request);
|
||||
request = customizeCaches(request);
|
||||
request = request.withNetwork(this.network);
|
||||
return request;
|
||||
}
|
||||
@@ -615,9 +638,12 @@ public class BootBuildImage extends DefaultTask {
|
||||
return request;
|
||||
}
|
||||
|
||||
private BuildRequest customizeCacheVolumeNames(BuildRequest request) {
|
||||
if (this.cacheVolumeNames != null && !this.cacheVolumeNames.isEmpty()) {
|
||||
request = request.withCacheVolumeNames(this.cacheVolumeNames);
|
||||
private BuildRequest customizeCaches(BuildRequest request) {
|
||||
if (this.buildCache.asCache() != null) {
|
||||
request = request.withBuildCache(this.buildCache.asCache());
|
||||
}
|
||||
if (this.launchCache.asCache() != null) {
|
||||
request = request.withLaunchCache(this.launchCache.asCache());
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 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.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import groovy.lang.Closure;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.util.ConfigureUtil;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.build.Cache;
|
||||
|
||||
/**
|
||||
* Configuration for an image building cache.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public class CacheSpec {
|
||||
|
||||
private Cache cache = null;
|
||||
|
||||
CacheSpec() {
|
||||
}
|
||||
|
||||
public Cache asCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a volume cache using the given {@code action}.
|
||||
* @param action the action
|
||||
*/
|
||||
public void volume(Action<VolumeCacheSpec> action) {
|
||||
if (this.cache != null) {
|
||||
throw new GradleException("Each image building cache can be configured only once");
|
||||
}
|
||||
VolumeCacheSpec spec = new VolumeCacheSpec();
|
||||
action.execute(spec);
|
||||
this.cache = Cache.volume(spec.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a volume cache using the given {@code closure}.
|
||||
* @param closure the closure
|
||||
*/
|
||||
public void volume(Closure<?> closure) {
|
||||
if (this.cache != null) {
|
||||
throw new GradleException("Each image building cache can be configured only once");
|
||||
}
|
||||
volume(ConfigureUtil.configureUsing(closure));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for an image building cache stored in a Docker volume.
|
||||
*/
|
||||
public static class VolumeCacheSpec {
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Returns the name of the cache.
|
||||
* @return the cache name
|
||||
*/
|
||||
@Input
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the cache.
|
||||
* @param name the cache name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -316,6 +316,14 @@ class PackagingDocumentationTests {
|
||||
.contains("urn:cnb:builder:paketo-buildpacks/java");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void bootBuildImageWithCaches() {
|
||||
BuildResult result = this.gradleBuild.script("src/docs/gradle/packaging/boot-build-image-caches")
|
||||
.build("bootBuildImageCaches");
|
||||
assertThat(result.getOutput()).containsPattern("buildCache=cache-gradle-[\\d]+.build")
|
||||
.containsPattern("launchCache=cache-gradle-[\\d]+.launch");
|
||||
}
|
||||
|
||||
protected void jarFile(File file) throws IOException {
|
||||
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(file))) {
|
||||
jar.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
|
||||
@@ -40,7 +40,10 @@ import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
|
||||
import org.springframework.boot.buildpack.platform.docker.DockerApi;
|
||||
import org.springframework.boot.buildpack.platform.docker.DockerApi.ImageApi;
|
||||
import org.springframework.boot.buildpack.platform.docker.DockerApi.VolumeApi;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.VolumeName;
|
||||
import org.springframework.boot.buildpack.platform.io.FilePermissions;
|
||||
import org.springframework.boot.gradle.junit.GradleCompatibility;
|
||||
import org.springframework.boot.testsupport.gradle.testkit.GradleBuild;
|
||||
@@ -73,7 +76,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("env: BP_JVM_VERSION=8.*");
|
||||
assertThat(result.getOutput()).contains("Network status: HTTP/2 200");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -91,7 +94,7 @@ class BootBuildImageIntegrationTests {
|
||||
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
|
||||
assertThat(buildLibs.listFiles())
|
||||
.containsExactly(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"));
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -107,7 +110,7 @@ class BootBuildImageIntegrationTests {
|
||||
File buildLibs = new File(this.gradleBuild.getProjectDir(), "build/libs");
|
||||
assertThat(buildLibs.listFiles())
|
||||
.containsExactly(new File(buildLibs, this.gradleBuild.getProjectDir().getName() + ".war"));
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -119,7 +122,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("example/test-image-name");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage("example/test-image-name");
|
||||
removeImages("example/test-image-name");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -131,7 +134,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("example/test-image-custom");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage("example/test-image-custom");
|
||||
removeImages("example/test-image-custom");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -146,7 +149,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("example/test-image-cmd");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage("example/test-image-cmd");
|
||||
removeImages("example/test-image-cmd");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -160,7 +163,7 @@ class BootBuildImageIntegrationTests {
|
||||
result = this.gradleBuild.build("bootBuildImage", "--pullPolicy=IF_NOT_PRESENT");
|
||||
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput()).doesNotContain("Pulled builder image").doesNotContain("Pulled run image");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -173,7 +176,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building")
|
||||
.contains("---> Test Info buildpack done");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -187,7 +190,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
|
||||
assertThat(result.getOutput()).contains("---> Hello World buildpack");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -202,7 +205,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.task(":bootBuildImage").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
|
||||
assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
|
||||
assertThat(result.getOutput()).contains("---> Hello World buildpack");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -215,7 +218,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building")
|
||||
.contains("---> Test Info buildpack done");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -232,7 +235,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("binding: certificates/test1.crt=---certificate one---");
|
||||
assertThat(result.getOutput()).contains("binding: certificates/test2.crt=---certificate two---");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -246,8 +249,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
assertThat(result.getOutput()).contains("example.com/myapp:latest");
|
||||
removeImage(projectName);
|
||||
removeImage("example.com/myapp:latest");
|
||||
removeImages(projectName, "example.com/myapp:latest");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -260,7 +262,7 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -274,7 +276,21 @@ class BootBuildImageIntegrationTests {
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("Network status: curl failed");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImage(projectName);
|
||||
removeImages(projectName);
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void buildsImageWithVolumeCaches() throws IOException {
|
||||
writeMainClass();
|
||||
writeLongNameResource();
|
||||
BuildResult result = this.gradleBuild.build("bootBuildImage", "--pullPolicy=IF_NOT_PRESENT");
|
||||
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("---> Test Info buildpack building");
|
||||
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
|
||||
removeImages(projectName);
|
||||
deleteVolumes("build-cache-volume", "launch-cache-volume");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
@@ -325,6 +341,14 @@ class BootBuildImageIntegrationTests {
|
||||
.containsPattern("example/Invalid-Tag-Name");
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWhenCachesAreConfiguredTwice() throws IOException {
|
||||
writeMainClass();
|
||||
writeLongNameResource();
|
||||
BuildResult result = this.gradleBuild.buildAndFail("bootBuildImage");
|
||||
assertThat(result.getOutput()).containsPattern("Each image building cache can be configured only once");
|
||||
}
|
||||
|
||||
private void writeMainClass() throws IOException {
|
||||
File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/example");
|
||||
examplePackage.mkdirs();
|
||||
@@ -447,9 +471,18 @@ class BootBuildImageIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
private void removeImage(String name) throws IOException {
|
||||
ImageReference imageReference = ImageReference.of(name);
|
||||
new DockerApi().image().remove(imageReference, false);
|
||||
private void removeImages(String... names) throws IOException {
|
||||
ImageApi imageApi = new DockerApi().image();
|
||||
for (String name : names) {
|
||||
imageApi.remove(ImageReference.of(name), false);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteVolumes(String... names) throws IOException {
|
||||
VolumeApi volumeApi = new DockerApi().volume();
|
||||
for (String name : names) {
|
||||
volumeApi.delete(VolumeName.of(name), false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '{version}'
|
||||
}
|
||||
|
||||
sourceCompatibility = '1.8'
|
||||
targetCompatibility = '1.8'
|
||||
|
||||
bootBuildImage {
|
||||
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
|
||||
buildCache {
|
||||
volume {
|
||||
name = "build-cache-volume"
|
||||
}
|
||||
}
|
||||
launchCache {
|
||||
volume {
|
||||
name = "launch-cache-volume"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '{version}'
|
||||
}
|
||||
|
||||
sourceCompatibility = '1.8'
|
||||
targetCompatibility = '1.8'
|
||||
|
||||
bootBuildImage {
|
||||
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
|
||||
buildCache {
|
||||
volume {
|
||||
name = "build-cache-volume1"
|
||||
}
|
||||
volume {
|
||||
name = "build-cache-volum2"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user