Add option to customize cache volume names when building an image

This commit adds configuration to the Maven and Gradle plugins to
allow specifying the names of build and launch cache volumes provided
to the CNB builder.

See gh-28292
This commit is contained in:
Julian Liebig
2021-10-11 17:59:45 +02:00
committed by Scott Frederick
parent 9d6a0cfd24
commit dc36346285
8 changed files with 171 additions and 17 deletions

View File

@@ -38,6 +38,7 @@ import org.springframework.util.Assert;
* @author Andrey Shlykov
* @author Jeroen Meijer
* @author Rafael Ceccone
* @author Julian Liebig
* @since 2.3.0
*/
public class BuildRequest {
@@ -74,6 +75,8 @@ public class BuildRequest {
private final List<ImageReference> tags;
private final Map<String, String> cacheVolumeNames;
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent) {
Assert.notNull(name, "Name must not be null");
Assert.notNull(applicationContent, "ApplicationContent must not be null");
@@ -91,12 +94,13 @@ public class BuildRequest {
this.bindings = Collections.emptyList();
this.network = null;
this.tags = Collections.emptyList();
this.cacheVolumeNames = Collections.emptyMap();
}
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent, ImageReference builder,
ImageReference runImage, Creator creator, Map<String, String> env, boolean cleanCache,
boolean verboseLogging, PullPolicy pullPolicy, boolean publish, List<BuildpackReference> buildpacks,
List<Binding> bindings, String network, List<ImageReference> tags) {
List<Binding> bindings, String network, List<ImageReference> tags, Map<String, String> cacheVolumeNames) {
this.name = name;
this.applicationContent = applicationContent;
this.builder = builder;
@@ -111,6 +115,7 @@ public class BuildRequest {
this.bindings = bindings;
this.network = network;
this.tags = tags;
this.cacheVolumeNames = cacheVolumeNames;
}
/**
@@ -122,7 +127,7 @@ public class BuildRequest {
Assert.notNull(builder, "Builder must not be null");
return new BuildRequest(this.name, this.applicationContent, builder.inTaggedOrDigestForm(), this.runImage,
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
this.buildpacks, this.bindings, this.network, this.tags);
this.buildpacks, this.bindings, this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -133,7 +138,7 @@ public class BuildRequest {
public BuildRequest withRunImage(ImageReference runImageName) {
return new BuildRequest(this.name, this.applicationContent, this.builder, runImageName.inTaggedOrDigestForm(),
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
this.buildpacks, this.bindings, this.network, this.tags);
this.buildpacks, this.bindings, this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -145,7 +150,7 @@ public class BuildRequest {
Assert.notNull(creator, "Creator must not be null");
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -161,7 +166,7 @@ public class BuildRequest {
env.put(name, value);
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
Collections.unmodifiableMap(env), this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
this.buildpacks, this.bindings, this.network, this.tags);
this.buildpacks, this.bindings, this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -175,7 +180,7 @@ public class BuildRequest {
updatedEnv.putAll(env);
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
Collections.unmodifiableMap(updatedEnv), this.cleanCache, this.verboseLogging, this.pullPolicy,
this.publish, this.buildpacks, this.bindings, this.network, this.tags);
this.publish, this.buildpacks, this.bindings, this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -186,7 +191,7 @@ public class BuildRequest {
public BuildRequest withCleanCache(boolean cleanCache) {
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -197,7 +202,7 @@ public class BuildRequest {
public BuildRequest withVerboseLogging(boolean verboseLogging) {
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -208,7 +213,7 @@ public class BuildRequest {
public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, pullPolicy, this.publish, this.buildpacks, this.bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -219,7 +224,7 @@ public class BuildRequest {
public BuildRequest withPublish(boolean publish) {
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, publish, this.buildpacks, this.bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -243,7 +248,7 @@ public class BuildRequest {
Assert.notNull(buildpacks, "Buildpacks must not be null");
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, buildpacks, this.bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -267,7 +272,7 @@ public class BuildRequest {
Assert.notNull(bindings, "Bindings must not be null");
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, bindings,
this.network, this.tags);
this.network, this.tags, this.cacheVolumeNames);
}
/**
@@ -279,7 +284,7 @@ public class BuildRequest {
public BuildRequest withNetwork(String network) {
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
network, this.tags);
network, this.tags, this.cacheVolumeNames);
}
/**
@@ -301,7 +306,39 @@ public class BuildRequest {
Assert.notNull(tags, "Tags must not be null");
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
this.network, tags);
this.network, tags, this.cacheVolumeNames);
}
/**
* Return a new {@link BuildRequest} with an additional cache volume name.
* @param type the cache volume type
* @param name the cache volume name
* @return an updated build request
*/
public BuildRequest withCacheVolumeName(String type, String name) {
Assert.hasText(type, "Type must not be empty");
Assert.state((type.equals("build") || type.equals("launch")), "Type must be either 'build' or 'launch'");
Assert.hasText(name, "Name must not be empty");
Map<String, String> cacheVolumeNames = new LinkedHashMap<>(this.cacheVolumeNames);
cacheVolumeNames.put(type, name);
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
this.network, this.tags, Collections.unmodifiableMap(cacheVolumeNames));
}
/**
* Return a new {@link BuildRequest} with additional cache volume names.
* @param entries the additional cache volume names
* @return an updated build request
*/
public BuildRequest withCacheVolumeNames(Map<String, String> entries) {
Assert.notNull(entries, "Entries must not be null");
Assert.state(!entries.isEmpty(), "Entries must not be empty");
BuildRequest request = null;
for (Map.Entry<String, String> entry : entries.entrySet()) {
request = withCacheVolumeName(entry.getKey(), entry.getValue());
}
return request;
}
/**
@@ -421,6 +458,14 @@ public class BuildRequest {
return this.tags;
}
/**
* Return the custom cache volume names that should be used by the lifecycle.
* @return the cache volume names
*/
public Map<String, String> getCacheVolumeNames() {
return this.cacheVolumeNames;
}
/**
* Factory method to create a new {@link BuildRequest} from a JAR file.
* @param jarFile the source jar file

View File

@@ -39,6 +39,7 @@ import org.springframework.util.Assert;
* @author Phillip Webb
* @author Scott Frederick
* @author Jeroen Meijer
* @author Julian Liebig
*/
class Lifecycle implements Closeable {
@@ -86,8 +87,8 @@ class Lifecycle implements Closeable {
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");
this.buildCacheVolume = createCacheVolumeName(request, "build");
this.launchCacheVolume = createCacheVolumeName(request, "launch");
}
protected VolumeName createRandomVolumeName(String prefix) {
@@ -95,7 +96,10 @@ class Lifecycle implements Closeable {
}
private VolumeName createCacheVolumeName(BuildRequest request, String suffix) {
return VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", suffix, 6);
if (!request.getCacheVolumeNames().isEmpty() && request.getCacheVolumeNames().containsKey(suffix)) {
return VolumeName.of(request.getCacheVolumeNames().get(suffix));
}
return VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6);
}
private ApiVersion getPlatformVersion(BuilderMetadata.Lifecycle lifecycle) {