Skip to content

Commit 4433fcd

Browse files
Add support for build workspace option when building images
Closes gh-37478
1 parent d8576f3 commit 4433fcd

File tree

19 files changed

+239
-58
lines changed

19 files changed

+239
-58
lines changed

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public class BuildRequest {
7777

7878
private final List<ImageReference> tags;
7979

80+
private final Cache buildWorkspace;
81+
8082
private final Cache buildCache;
8183

8284
private final Cache launchCache;
@@ -102,6 +104,7 @@ public class BuildRequest {
102104
this.bindings = Collections.emptyList();
103105
this.network = null;
104106
this.tags = Collections.emptyList();
107+
this.buildWorkspace = null;
105108
this.buildCache = null;
106109
this.launchCache = null;
107110
this.createdDate = null;
@@ -111,8 +114,8 @@ public class BuildRequest {
111114
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent, ImageReference builder,
112115
ImageReference runImage, Creator creator, Map<String, String> env, boolean cleanCache,
113116
boolean verboseLogging, PullPolicy pullPolicy, boolean publish, List<BuildpackReference> buildpacks,
114-
List<Binding> bindings, String network, List<ImageReference> tags, Cache buildCache, Cache launchCache,
115-
Instant createdDate, String applicationDirectory) {
117+
List<Binding> bindings, String network, List<ImageReference> tags, Cache buildWorkspace, Cache buildCache,
118+
Cache launchCache, Instant createdDate, String applicationDirectory) {
116119
this.name = name;
117120
this.applicationContent = applicationContent;
118121
this.builder = builder;
@@ -127,6 +130,7 @@ public class BuildRequest {
127130
this.bindings = bindings;
128131
this.network = network;
129132
this.tags = tags;
133+
this.buildWorkspace = buildWorkspace;
130134
this.buildCache = buildCache;
131135
this.launchCache = launchCache;
132136
this.createdDate = createdDate;
@@ -142,8 +146,8 @@ public BuildRequest withBuilder(ImageReference builder) {
142146
Assert.notNull(builder, "Builder must not be null");
143147
return new BuildRequest(this.name, this.applicationContent, builder.inTaggedOrDigestForm(), this.runImage,
144148
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
145-
this.buildpacks, this.bindings, this.network, this.tags, this.buildCache, this.launchCache,
146-
this.createdDate, this.applicationDirectory);
149+
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
150+
this.launchCache, this.createdDate, this.applicationDirectory);
147151
}
148152

149153
/**
@@ -154,8 +158,8 @@ public BuildRequest withBuilder(ImageReference builder) {
154158
public BuildRequest withRunImage(ImageReference runImageName) {
155159
return new BuildRequest(this.name, this.applicationContent, this.builder, runImageName.inTaggedOrDigestForm(),
156160
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
157-
this.buildpacks, this.bindings, this.network, this.tags, this.buildCache, this.launchCache,
158-
this.createdDate, this.applicationDirectory);
161+
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
162+
this.launchCache, this.createdDate, this.applicationDirectory);
159163
}
160164

161165
/**
@@ -167,7 +171,7 @@ public BuildRequest withCreator(Creator creator) {
167171
Assert.notNull(creator, "Creator must not be null");
168172
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, creator, this.env,
169173
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
170-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
174+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
171175
this.applicationDirectory);
172176
}
173177

@@ -184,8 +188,8 @@ public BuildRequest withEnv(String name, String value) {
184188
env.put(name, value);
185189
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
186190
Collections.unmodifiableMap(env), this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
187-
this.buildpacks, this.bindings, this.network, this.tags, this.buildCache, this.launchCache,
188-
this.createdDate, this.applicationDirectory);
191+
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
192+
this.launchCache, this.createdDate, this.applicationDirectory);
189193
}
190194

191195
/**
@@ -199,8 +203,8 @@ public BuildRequest withEnv(Map<String, String> env) {
199203
updatedEnv.putAll(env);
200204
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
201205
Collections.unmodifiableMap(updatedEnv), this.cleanCache, this.verboseLogging, this.pullPolicy,
202-
this.publish, this.buildpacks, this.bindings, this.network, this.tags, this.buildCache,
203-
this.launchCache, this.createdDate, this.applicationDirectory);
206+
this.publish, this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace,
207+
this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
204208
}
205209

206210
/**
@@ -211,7 +215,7 @@ public BuildRequest withEnv(Map<String, String> env) {
211215
public BuildRequest withCleanCache(boolean cleanCache) {
212216
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
213217
cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
214-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
218+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
215219
this.applicationDirectory);
216220
}
217221

@@ -223,7 +227,7 @@ public BuildRequest withCleanCache(boolean cleanCache) {
223227
public BuildRequest withVerboseLogging(boolean verboseLogging) {
224228
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
225229
this.cleanCache, verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
226-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
230+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
227231
this.applicationDirectory);
228232
}
229233

@@ -235,7 +239,7 @@ public BuildRequest withVerboseLogging(boolean verboseLogging) {
235239
public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
236240
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
237241
this.cleanCache, this.verboseLogging, pullPolicy, this.publish, this.buildpacks, this.bindings,
238-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
242+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
239243
this.applicationDirectory);
240244
}
241245

@@ -247,7 +251,7 @@ public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
247251
public BuildRequest withPublish(boolean publish) {
248252
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
249253
this.cleanCache, this.verboseLogging, this.pullPolicy, publish, this.buildpacks, this.bindings,
250-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
254+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
251255
this.applicationDirectory);
252256
}
253257

@@ -272,7 +276,7 @@ public BuildRequest withBuildpacks(List<BuildpackReference> buildpacks) {
272276
Assert.notNull(buildpacks, "Buildpacks must not be null");
273277
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
274278
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, buildpacks, this.bindings,
275-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
279+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
276280
this.applicationDirectory);
277281
}
278282

@@ -297,7 +301,7 @@ public BuildRequest withBindings(List<Binding> bindings) {
297301
Assert.notNull(bindings, "Bindings must not be null");
298302
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
299303
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, bindings,
300-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
304+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
301305
this.applicationDirectory);
302306
}
303307

@@ -310,7 +314,8 @@ public BuildRequest withBindings(List<Binding> bindings) {
310314
public BuildRequest withNetwork(String network) {
311315
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
312316
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
313-
network, this.tags, this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
317+
network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
318+
this.applicationDirectory);
314319
}
315320

316321
/**
@@ -332,7 +337,21 @@ public BuildRequest withTags(List<ImageReference> tags) {
332337
Assert.notNull(tags, "Tags must not be null");
333338
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
334339
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
335-
this.network, tags, this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
340+
this.network, tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
341+
this.applicationDirectory);
342+
}
343+
344+
/**
345+
* Return a new {@link BuildRequest} with an updated build workspace.
346+
* @param buildWorkspace the build workspace
347+
* @return an updated build request
348+
*/
349+
public BuildRequest withBuildWorkspace(Cache buildWorkspace) {
350+
Assert.notNull(buildWorkspace, "BuildWorkspace must not be null");
351+
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
352+
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
353+
this.network, this.tags, buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
354+
this.applicationDirectory);
336355
}
337356

338357
/**
@@ -344,7 +363,8 @@ public BuildRequest withBuildCache(Cache buildCache) {
344363
Assert.notNull(buildCache, "BuildCache must not be null");
345364
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
346365
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
347-
this.network, this.tags, buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
366+
this.network, this.tags, this.buildWorkspace, buildCache, this.launchCache, this.createdDate,
367+
this.applicationDirectory);
348368
}
349369

350370
/**
@@ -356,7 +376,8 @@ public BuildRequest withLaunchCache(Cache launchCache) {
356376
Assert.notNull(launchCache, "LaunchCache must not be null");
357377
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
358378
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
359-
this.network, this.tags, this.buildCache, launchCache, this.createdDate, this.applicationDirectory);
379+
this.network, this.tags, this.buildWorkspace, this.buildCache, launchCache, this.createdDate,
380+
this.applicationDirectory);
360381
}
361382

362383
/**
@@ -368,8 +389,8 @@ public BuildRequest withCreatedDate(String createdDate) {
368389
Assert.notNull(createdDate, "CreatedDate must not be null");
369390
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
370391
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
371-
this.network, this.tags, this.buildCache, this.launchCache, parseCreatedDate(createdDate),
372-
this.applicationDirectory);
392+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache,
393+
parseCreatedDate(createdDate), this.applicationDirectory);
373394
}
374395

375396
private Instant parseCreatedDate(String createdDate) {
@@ -393,7 +414,8 @@ public BuildRequest withApplicationDirectory(String applicationDirectory) {
393414
Assert.notNull(applicationDirectory, "ApplicationDirectory must not be null");
394415
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
395416
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
396-
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate, applicationDirectory);
417+
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
418+
applicationDirectory);
397419
}
398420

399421
/**
@@ -513,6 +535,10 @@ public List<ImageReference> getTags() {
513535
return this.tags;
514536
}
515537

538+
public Cache getBuildWorkspace() {
539+
return this.buildWorkspace;
540+
}
541+
516542
/**
517543
* Return the custom build cache that should be used by the lifecycle.
518544
* @return the build cache

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
import java.io.Closeable;
2020
import java.io.IOException;
21+
import java.nio.file.Files;
2122
import java.nio.file.Path;
23+
import java.util.List;
2224
import java.util.function.Consumer;
2325

2426
import com.sun.jna.Platform;
@@ -70,9 +72,9 @@ class Lifecycle implements Closeable {
7072

7173
private final ApiVersion platformVersion;
7274

73-
private final VolumeName layersVolume;
75+
private final Cache layers;
7476

75-
private final VolumeName applicationVolume;
77+
private final Cache application;
7678

7779
private final Cache buildCache;
7880

@@ -101,17 +103,13 @@ class Lifecycle implements Closeable {
101103
this.builder = builder;
102104
this.lifecycleVersion = LifecycleVersion.parse(builder.getBuilderMetadata().getLifecycle().getVersion());
103105
this.platformVersion = getPlatformVersion(builder.getBuilderMetadata().getLifecycle());
104-
this.layersVolume = createRandomVolumeName("pack-layers-");
105-
this.applicationVolume = createRandomVolumeName("pack-app-");
106+
this.layers = getLayersBindingSource(request);
107+
this.application = getApplicationBindingSource(request);
106108
this.buildCache = getBuildCache(request);
107109
this.launchCache = getLaunchCache(request);
108110
this.applicationDirectory = getApplicationDirectory(request);
109111
}
110112

111-
protected VolumeName createRandomVolumeName(String prefix) {
112-
return VolumeName.random(prefix);
113-
}
114-
115113
private Cache getBuildCache(BuildRequest request) {
116114
if (request.getBuildCache() != null) {
117115
return request.getBuildCache();
@@ -130,11 +128,6 @@ private String getApplicationDirectory(BuildRequest request) {
130128
return (request.getApplicationDirectory() != null) ? request.getApplicationDirectory() : Directory.APPLICATION;
131129
}
132130

133-
private Cache createVolumeCache(BuildRequest request, String suffix) {
134-
return Cache.volume(
135-
VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6));
136-
}
137-
138131
private ApiVersion getPlatformVersion(BuilderMetadata.Lifecycle lifecycle) {
139132
if (lifecycle.getApis().getPlatform() != null) {
140133
String[] supportedVersions = lifecycle.getApis().getPlatform();
@@ -153,12 +146,7 @@ void execute() throws IOException {
153146
this.executed = true;
154147
this.log.executingLifecycle(this.request, this.lifecycleVersion, this.buildCache);
155148
if (this.request.isCleanCache()) {
156-
if (this.buildCache.getVolume() != null) {
157-
deleteVolume(this.buildCache.getVolume().getVolumeName());
158-
}
159-
if (this.buildCache.getBind() != null) {
160-
deleteBind(this.buildCache.getBind().getSource());
161-
}
149+
deleteCache(this.buildCache);
162150
}
163151
run(createPhase());
164152
this.log.executedLifecycle(this.request);
@@ -183,8 +171,8 @@ private Phase createPhase() {
183171
phase.withArgs("-process-type=web");
184172
}
185173
phase.withArgs(this.request.getName());
186-
phase.withBinding(Binding.from(this.layersVolume, Directory.LAYERS));
187-
phase.withBinding(Binding.from(this.applicationVolume, this.applicationDirectory));
174+
phase.withBinding(Binding.from(getCacheBindingSource(this.layers), Directory.LAYERS));
175+
phase.withBinding(Binding.from(getCacheBindingSource(this.application), this.applicationDirectory));
188176
phase.withBinding(Binding.from(getCacheBindingSource(this.buildCache), Directory.CACHE));
189177
phase.withBinding(Binding.from(getCacheBindingSource(this.launchCache), Directory.LAUNCH_CACHE));
190178
if (this.request.getBindings() != null) {
@@ -200,10 +188,42 @@ private Phase createPhase() {
200188
return phase;
201189
}
202190

191+
private Cache getLayersBindingSource(BuildRequest request) {
192+
if (request.getBuildWorkspace() != null) {
193+
return getBuildWorkspaceBindingSource(request.getBuildWorkspace(), "layers");
194+
}
195+
return createVolumeCache("pack-layers-");
196+
}
197+
198+
private Cache getApplicationBindingSource(BuildRequest request) {
199+
if (request.getBuildWorkspace() != null) {
200+
return getBuildWorkspaceBindingSource(request.getBuildWorkspace(), "app");
201+
}
202+
return createVolumeCache("pack-app-");
203+
}
204+
205+
private Cache getBuildWorkspaceBindingSource(Cache buildWorkspace, String suffix) {
206+
return (buildWorkspace.getVolume() != null) ? Cache.volume(buildWorkspace.getVolume().getName() + "-" + suffix)
207+
: Cache.bind(buildWorkspace.getBind().getSource() + "-" + suffix);
208+
}
209+
203210
private String getCacheBindingSource(Cache cache) {
204211
return (cache.getVolume() != null) ? cache.getVolume().getName() : cache.getBind().getSource();
205212
}
206213

214+
private Cache createVolumeCache(String prefix) {
215+
return Cache.volume(createRandomVolumeName(prefix));
216+
}
217+
218+
private Cache createVolumeCache(BuildRequest request, String suffix) {
219+
return Cache.volume(
220+
VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6));
221+
}
222+
223+
protected VolumeName createRandomVolumeName(String prefix) {
224+
return VolumeName.random(prefix);
225+
}
226+
207227
private void configureDaemonAccess(Phase phase) {
208228
if (this.dockerHost != null) {
209229
if (this.dockerHost.isRemote()) {
@@ -255,6 +275,9 @@ private ContainerReference createContainer(ContainerConfig config) throws IOExce
255275
return this.docker.container().create(config);
256276
}
257277
try {
278+
if (this.application.getBind() != null) {
279+
Files.createDirectories(Path.of(this.application.getBind().getSource()));
280+
}
258281
TarArchive applicationContent = this.request.getApplicationContent(this.builder.getBuildOwner());
259282
return this.docker.container()
260283
.create(config, ContainerContent.of(applicationContent, this.applicationDirectory));
@@ -266,8 +289,17 @@ private ContainerReference createContainer(ContainerConfig config) throws IOExce
266289

267290
@Override
268291
public void close() throws IOException {
269-
deleteVolume(this.layersVolume);
270-
deleteVolume(this.applicationVolume);
292+
deleteCache(this.layers);
293+
deleteCache(this.application);
294+
}
295+
296+
private void deleteCache(Cache cache) throws IOException {
297+
if (cache.getVolume() != null) {
298+
deleteVolume(cache.getVolume().getVolumeName());
299+
}
300+
if (cache.getBind() != null) {
301+
deleteBind(cache.getBind().getSource());
302+
}
271303
}
272304

273305
private void deleteVolume(VolumeName name) throws IOException {

0 commit comments

Comments
 (0)