Skip to content

Commit

Permalink
Add support for build workspace option when building images
Browse files Browse the repository at this point in the history
Closes gh-37478
  • Loading branch information
scottfrederick committed Sep 20, 2023
1 parent d8576f3 commit 4433fcd
Show file tree
Hide file tree
Showing 19 changed files with 239 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public class BuildRequest {

private final List<ImageReference> tags;

private final Cache buildWorkspace;

private final Cache buildCache;

private final Cache launchCache;
Expand All @@ -102,6 +104,7 @@ public class BuildRequest {
this.bindings = Collections.emptyList();
this.network = null;
this.tags = Collections.emptyList();
this.buildWorkspace = null;
this.buildCache = null;
this.launchCache = null;
this.createdDate = null;
Expand All @@ -111,8 +114,8 @@ public class BuildRequest {
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, Cache buildCache, Cache launchCache,
Instant createdDate, String applicationDirectory) {
List<Binding> bindings, String network, List<ImageReference> tags, Cache buildWorkspace, Cache buildCache,
Cache launchCache, Instant createdDate, String applicationDirectory) {
this.name = name;
this.applicationContent = applicationContent;
this.builder = builder;
Expand All @@ -127,6 +130,7 @@ public class BuildRequest {
this.bindings = bindings;
this.network = network;
this.tags = tags;
this.buildWorkspace = buildWorkspace;
this.buildCache = buildCache;
this.launchCache = launchCache;
this.createdDate = createdDate;
Expand All @@ -142,8 +146,8 @@ public BuildRequest withBuilder(ImageReference builder) {
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.buildCache, this.launchCache,
this.createdDate, this.applicationDirectory);
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
this.launchCache, this.createdDate, this.applicationDirectory);
}

/**
Expand All @@ -154,8 +158,8 @@ public BuildRequest withBuilder(ImageReference builder) {
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.buildCache, this.launchCache,
this.createdDate, this.applicationDirectory);
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
this.launchCache, this.createdDate, this.applicationDirectory);
}

/**
Expand All @@ -167,7 +171,7 @@ public BuildRequest withCreator(Creator creator) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -184,8 +188,8 @@ public BuildRequest withEnv(String name, String value) {
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.buildCache, this.launchCache,
this.createdDate, this.applicationDirectory);
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
this.launchCache, this.createdDate, this.applicationDirectory);
}

/**
Expand All @@ -199,8 +203,8 @@ public BuildRequest withEnv(Map<String, String> env) {
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.buildCache,
this.launchCache, this.createdDate, this.applicationDirectory);
this.publish, this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace,
this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
}

/**
Expand All @@ -211,7 +215,7 @@ public BuildRequest withEnv(Map<String, String> env) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -223,7 +227,7 @@ public BuildRequest withCleanCache(boolean cleanCache) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -235,7 +239,7 @@ public BuildRequest withVerboseLogging(boolean verboseLogging) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -247,7 +251,7 @@ public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -272,7 +276,7 @@ public BuildRequest withBuildpacks(List<BuildpackReference> buildpacks) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -297,7 +301,7 @@ public BuildRequest withBindings(List<Binding> bindings) {
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.buildCache, this.launchCache, this.createdDate,
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

Expand All @@ -310,7 +314,8 @@ public BuildRequest withBindings(List<Binding> bindings) {
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, this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

/**
Expand All @@ -332,7 +337,21 @@ public BuildRequest withTags(List<ImageReference> tags) {
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.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
this.network, tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

/**
* Return a new {@link BuildRequest} with an updated build workspace.
* @param buildWorkspace the build workspace
* @return an updated build request
*/
public BuildRequest withBuildWorkspace(Cache buildWorkspace) {
Assert.notNull(buildWorkspace, "BuildWorkspace 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, this.tags, buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

/**
Expand All @@ -344,7 +363,8 @@ public BuildRequest withBuildCache(Cache buildCache) {
Assert.notNull(buildCache, "BuildCache 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, this.tags, buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
this.network, this.tags, this.buildWorkspace, buildCache, this.launchCache, this.createdDate,
this.applicationDirectory);
}

/**
Expand All @@ -356,7 +376,8 @@ public BuildRequest withLaunchCache(Cache launchCache) {
Assert.notNull(launchCache, "LaunchCache 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, this.tags, this.buildCache, launchCache, this.createdDate, this.applicationDirectory);
this.network, this.tags, this.buildWorkspace, this.buildCache, launchCache, this.createdDate,
this.applicationDirectory);
}

/**
Expand All @@ -368,8 +389,8 @@ public BuildRequest withCreatedDate(String createdDate) {
Assert.notNull(createdDate, "CreatedDate 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, this.tags, this.buildCache, this.launchCache, parseCreatedDate(createdDate),
this.applicationDirectory);
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache,
parseCreatedDate(createdDate), this.applicationDirectory);
}

private Instant parseCreatedDate(String createdDate) {
Expand All @@ -393,7 +414,8 @@ public BuildRequest withApplicationDirectory(String applicationDirectory) {
Assert.notNull(applicationDirectory, "ApplicationDirectory 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, this.tags, this.buildCache, this.launchCache, this.createdDate, applicationDirectory);
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
applicationDirectory);
}

/**
Expand Down Expand Up @@ -513,6 +535,10 @@ public List<ImageReference> getTags() {
return this.tags;
}

public Cache getBuildWorkspace() {
return this.buildWorkspace;
}

/**
* Return the custom build cache that should be used by the lifecycle.
* @return the build cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Consumer;

import com.sun.jna.Platform;
Expand Down Expand Up @@ -70,9 +72,9 @@ class Lifecycle implements Closeable {

private final ApiVersion platformVersion;

private final VolumeName layersVolume;
private final Cache layers;

private final VolumeName applicationVolume;
private final Cache application;

private final Cache buildCache;

Expand Down Expand Up @@ -101,17 +103,13 @@ class Lifecycle implements Closeable {
this.builder = builder;
this.lifecycleVersion = LifecycleVersion.parse(builder.getBuilderMetadata().getLifecycle().getVersion());
this.platformVersion = getPlatformVersion(builder.getBuilderMetadata().getLifecycle());
this.layersVolume = createRandomVolumeName("pack-layers-");
this.applicationVolume = createRandomVolumeName("pack-app-");
this.layers = getLayersBindingSource(request);
this.application = getApplicationBindingSource(request);
this.buildCache = getBuildCache(request);
this.launchCache = getLaunchCache(request);
this.applicationDirectory = getApplicationDirectory(request);
}

protected VolumeName createRandomVolumeName(String prefix) {
return VolumeName.random(prefix);
}

private Cache getBuildCache(BuildRequest request) {
if (request.getBuildCache() != null) {
return request.getBuildCache();
Expand All @@ -130,11 +128,6 @@ private String getApplicationDirectory(BuildRequest request) {
return (request.getApplicationDirectory() != null) ? request.getApplicationDirectory() : Directory.APPLICATION;
}

private Cache createVolumeCache(BuildRequest request, String suffix) {
return Cache.volume(
VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6));
}

private ApiVersion getPlatformVersion(BuilderMetadata.Lifecycle lifecycle) {
if (lifecycle.getApis().getPlatform() != null) {
String[] supportedVersions = lifecycle.getApis().getPlatform();
Expand All @@ -153,12 +146,7 @@ void execute() throws IOException {
this.executed = true;
this.log.executingLifecycle(this.request, this.lifecycleVersion, this.buildCache);
if (this.request.isCleanCache()) {
if (this.buildCache.getVolume() != null) {
deleteVolume(this.buildCache.getVolume().getVolumeName());
}
if (this.buildCache.getBind() != null) {
deleteBind(this.buildCache.getBind().getSource());
}
deleteCache(this.buildCache);
}
run(createPhase());
this.log.executedLifecycle(this.request);
Expand All @@ -183,8 +171,8 @@ private Phase createPhase() {
phase.withArgs("-process-type=web");
}
phase.withArgs(this.request.getName());
phase.withBinding(Binding.from(this.layersVolume, Directory.LAYERS));
phase.withBinding(Binding.from(this.applicationVolume, this.applicationDirectory));
phase.withBinding(Binding.from(getCacheBindingSource(this.layers), Directory.LAYERS));
phase.withBinding(Binding.from(getCacheBindingSource(this.application), this.applicationDirectory));
phase.withBinding(Binding.from(getCacheBindingSource(this.buildCache), Directory.CACHE));
phase.withBinding(Binding.from(getCacheBindingSource(this.launchCache), Directory.LAUNCH_CACHE));
if (this.request.getBindings() != null) {
Expand All @@ -200,10 +188,42 @@ private Phase createPhase() {
return phase;
}

private Cache getLayersBindingSource(BuildRequest request) {
if (request.getBuildWorkspace() != null) {
return getBuildWorkspaceBindingSource(request.getBuildWorkspace(), "layers");
}
return createVolumeCache("pack-layers-");
}

private Cache getApplicationBindingSource(BuildRequest request) {
if (request.getBuildWorkspace() != null) {
return getBuildWorkspaceBindingSource(request.getBuildWorkspace(), "app");
}
return createVolumeCache("pack-app-");
}

private Cache getBuildWorkspaceBindingSource(Cache buildWorkspace, String suffix) {
return (buildWorkspace.getVolume() != null) ? Cache.volume(buildWorkspace.getVolume().getName() + "-" + suffix)
: Cache.bind(buildWorkspace.getBind().getSource() + "-" + suffix);
}

private String getCacheBindingSource(Cache cache) {
return (cache.getVolume() != null) ? cache.getVolume().getName() : cache.getBind().getSource();
}

private Cache createVolumeCache(String prefix) {
return Cache.volume(createRandomVolumeName(prefix));
}

private Cache createVolumeCache(BuildRequest request, String suffix) {
return Cache.volume(
VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6));
}

protected VolumeName createRandomVolumeName(String prefix) {
return VolumeName.random(prefix);
}

private void configureDaemonAccess(Phase phase) {
if (this.dockerHost != null) {
if (this.dockerHost.isRemote()) {
Expand Down Expand Up @@ -255,6 +275,9 @@ private ContainerReference createContainer(ContainerConfig config) throws IOExce
return this.docker.container().create(config);
}
try {
if (this.application.getBind() != null) {
Files.createDirectories(Path.of(this.application.getBind().getSource()));
}
TarArchive applicationContent = this.request.getApplicationContent(this.builder.getBuildOwner());
return this.docker.container()
.create(config, ContainerContent.of(applicationContent, this.applicationDirectory));
Expand All @@ -266,8 +289,17 @@ private ContainerReference createContainer(ContainerConfig config) throws IOExce

@Override
public void close() throws IOException {
deleteVolume(this.layersVolume);
deleteVolume(this.applicationVolume);
deleteCache(this.layers);
deleteCache(this.application);
}

private void deleteCache(Cache cache) throws IOException {
if (cache.getVolume() != null) {
deleteVolume(cache.getVolume().getVolumeName());
}
if (cache.getBind() != null) {
deleteBind(cache.getBind().getSource());
}
}

private void deleteVolume(VolumeName name) throws IOException {
Expand Down
Loading

0 comments on commit 4433fcd

Please sign in to comment.