Skip to content

Commit 3085350

Browse files
Merge pull request #27486 from Meijuh
* pr/27486: Polish "Add network option for image building" Add network option for image building Closes gh-27486
2 parents e737388 + 2178c28 commit 3085350

File tree

23 files changed

+317
-15
lines changed

23 files changed

+317
-15
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: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* @author Phillip Webb
3737
* @author Scott Frederick
3838
* @author Andrey Shlykov
39+
* @author Jeroen Meijer
3940
* @since 2.3.0
4041
*/
4142
public class BuildRequest {
@@ -68,6 +69,8 @@ public class BuildRequest {
6869

6970
private final List<Binding> bindings;
7071

72+
private final String network;
73+
7174
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent) {
7275
Assert.notNull(name, "Name must not be null");
7376
Assert.notNull(applicationContent, "ApplicationContent must not be null");
@@ -83,12 +86,13 @@ public class BuildRequest {
8386
this.creator = Creator.withVersion("");
8487
this.buildpacks = Collections.emptyList();
8588
this.bindings = Collections.emptyList();
89+
this.network = null;
8690
}
8791

8892
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent, ImageReference builder,
8993
ImageReference runImage, Creator creator, Map<String, String> env, boolean cleanCache,
9094
boolean verboseLogging, PullPolicy pullPolicy, boolean publish, List<BuildpackReference> buildpacks,
91-
List<Binding> bindings) {
95+
List<Binding> bindings, String network) {
9296
this.name = name;
9397
this.applicationContent = applicationContent;
9498
this.builder = builder;
@@ -101,6 +105,7 @@ public class BuildRequest {
101105
this.publish = publish;
102106
this.buildpacks = buildpacks;
103107
this.bindings = bindings;
108+
this.network = network;
104109
}
105110

106111
/**
@@ -112,7 +117,7 @@ public BuildRequest withBuilder(ImageReference builder) {
112117
Assert.notNull(builder, "Builder must not be null");
113118
return new BuildRequest(this.name, this.applicationContent, builder.inTaggedOrDigestForm(), this.runImage,
114119
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
115-
this.buildpacks, this.bindings);
120+
this.buildpacks, this.bindings, this.network);
116121
}
117122

118123
/**
@@ -123,7 +128,7 @@ public BuildRequest withBuilder(ImageReference builder) {
123128
public BuildRequest withRunImage(ImageReference runImageName) {
124129
return new BuildRequest(this.name, this.applicationContent, this.builder, runImageName.inTaggedOrDigestForm(),
125130
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
126-
this.buildpacks, this.bindings);
131+
this.buildpacks, this.bindings, this.network);
127132
}
128133

129134
/**
@@ -134,7 +139,8 @@ public BuildRequest withRunImage(ImageReference runImageName) {
134139
public BuildRequest withCreator(Creator creator) {
135140
Assert.notNull(creator, "Creator must not be null");
136141
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, creator, this.env,
137-
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings);
142+
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
143+
this.network);
138144
}
139145

140146
/**
@@ -150,7 +156,7 @@ public BuildRequest withEnv(String name, String value) {
150156
env.put(name, value);
151157
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
152158
Collections.unmodifiableMap(env), this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
153-
this.buildpacks, this.bindings);
159+
this.buildpacks, this.bindings, this.network);
154160
}
155161

156162
/**
@@ -164,7 +170,7 @@ public BuildRequest withEnv(Map<String, String> env) {
164170
updatedEnv.putAll(env);
165171
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
166172
Collections.unmodifiableMap(updatedEnv), this.cleanCache, this.verboseLogging, this.pullPolicy,
167-
this.publish, this.buildpacks, this.bindings);
173+
this.publish, this.buildpacks, this.bindings, this.network);
168174
}
169175

170176
/**
@@ -174,7 +180,8 @@ public BuildRequest withEnv(Map<String, String> env) {
174180
*/
175181
public BuildRequest withCleanCache(boolean cleanCache) {
176182
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
177-
cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings);
183+
cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
184+
this.network);
178185
}
179186

180187
/**
@@ -184,7 +191,8 @@ public BuildRequest withCleanCache(boolean cleanCache) {
184191
*/
185192
public BuildRequest withVerboseLogging(boolean verboseLogging) {
186193
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
187-
this.cleanCache, verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings);
194+
this.cleanCache, verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
195+
this.network);
188196
}
189197

190198
/**
@@ -194,7 +202,8 @@ public BuildRequest withVerboseLogging(boolean verboseLogging) {
194202
*/
195203
public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
196204
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
197-
this.cleanCache, this.verboseLogging, pullPolicy, this.publish, this.buildpacks, this.bindings);
205+
this.cleanCache, this.verboseLogging, pullPolicy, this.publish, this.buildpacks, this.bindings,
206+
this.network);
198207
}
199208

200209
/**
@@ -204,7 +213,8 @@ public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
204213
*/
205214
public BuildRequest withPublish(boolean publish) {
206215
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
207-
this.cleanCache, this.verboseLogging, this.pullPolicy, publish, this.buildpacks, this.bindings);
216+
this.cleanCache, this.verboseLogging, this.pullPolicy, publish, this.buildpacks, this.bindings,
217+
this.network);
208218
}
209219

210220
/**
@@ -227,7 +237,8 @@ public BuildRequest withBuildpacks(BuildpackReference... buildpacks) {
227237
public BuildRequest withBuildpacks(List<BuildpackReference> buildpacks) {
228238
Assert.notNull(buildpacks, "Buildpacks must not be null");
229239
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
230-
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, buildpacks, this.bindings);
240+
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, buildpacks, this.bindings,
241+
this.network);
231242
}
232243

233244
/**
@@ -250,7 +261,20 @@ public BuildRequest withBindings(Binding... bindings) {
250261
public BuildRequest withBindings(List<Binding> bindings) {
251262
Assert.notNull(bindings, "Bindings must not be null");
252263
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
253-
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, bindings);
264+
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, bindings,
265+
this.network);
266+
}
267+
268+
/**
269+
* Return a new {@link BuildRequest} with an updated network setting.
270+
* @param network the network the build container will connect to
271+
* @return an updated build request
272+
* @since 2.6.0
273+
*/
274+
public BuildRequest withNetwork(String network) {
275+
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
276+
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
277+
network);
254278
}
255279

256280
/**
@@ -353,6 +377,15 @@ public List<Binding> getBindings() {
353377
return this.bindings;
354378
}
355379

380+
/**
381+
* Return the network the build container will connect to.
382+
* @return the network
383+
* @since 2.6.0
384+
*/
385+
public String getNetwork() {
386+
return this.network;
387+
}
388+
356389
/**
357390
* Factory method to create a new {@link BuildRequest} from a JAR file.
358391
* @param jarFile the source jar file

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
*
3939
* @author Phillip Webb
4040
* @author Scott Frederick
41+
* @author Jeroen Meijer
4142
*/
4243
class Lifecycle implements Closeable {
4344

@@ -147,6 +148,9 @@ private Phase createPhase() {
147148
this.request.getBindings().forEach(phase::withBinding);
148149
}
149150
phase.withEnv(PLATFORM_API_VERSION_KEY, this.platformVersion.toString());
151+
if (this.request.getNetwork() != null) {
152+
phase.withNetworkMode(this.request.getNetwork());
153+
}
150154
return phase;
151155
}
152156

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
*
3232
* @author Phillip Webb
3333
* @author Scott Frederick
34+
* @author Jeroen Meijer
3435
*/
3536
class Phase {
3637

@@ -48,6 +49,8 @@ class Phase {
4849

4950
private final Map<String, String> env = new LinkedHashMap<>();
5051

52+
private String networkMode;
53+
5154
/**
5255
* Create a new {@link Phase} instance.
5356
* @param name the name of the phase
@@ -101,6 +104,14 @@ void withEnv(String name, String value) {
101104
this.env.put(name, value);
102105
}
103106

107+
/**
108+
* Update this phase with the network the build container will connect to.
109+
* @param networkMode the network
110+
*/
111+
void withNetworkMode(String networkMode) {
112+
this.networkMode = networkMode;
113+
}
114+
104115
/**
105116
* Return the name of the phase.
106117
* @return the phase name
@@ -127,6 +138,9 @@ void apply(ContainerConfig.Update update) {
127138
update.withLabel("author", "spring-boot");
128139
this.bindings.forEach(update::withBinding);
129140
this.env.forEach(update::withEnv);
141+
if (this.networkMode != null) {
142+
update.withNetworkMode(this.networkMode);
143+
}
130144
}
131145

132146
}

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,15 @@
4040
*
4141
* @author Phillip Webb
4242
* @author Scott Frederick
43+
* @author Jeroen Meijer
4344
* @since 2.3.0
4445
*/
4546
public class ContainerConfig {
4647

4748
private final String json;
4849

4950
ContainerConfig(String user, ImageReference image, String command, List<String> args, Map<String, String> labels,
50-
List<Binding> bindings, Map<String, String> env) throws IOException {
51+
List<Binding> bindings, Map<String, String> env, String networkMode) throws IOException {
5152
Assert.notNull(image, "Image must not be null");
5253
Assert.hasText(command, "Command must not be empty");
5354
ObjectMapper objectMapper = SharedObjectMapper.get();
@@ -64,6 +65,9 @@ public class ContainerConfig {
6465
ObjectNode labelsNode = node.putObject("Labels");
6566
labels.forEach(labelsNode::put);
6667
ObjectNode hostConfigNode = node.putObject("HostConfig");
68+
if (networkMode != null) {
69+
hostConfigNode.put("NetworkMode", networkMode);
70+
}
6771
ArrayNode bindsNode = hostConfigNode.putArray("Binds");
6872
bindings.forEach((binding) -> bindsNode.add(binding.toString()));
6973
this.json = objectMapper.writeValueAsString(node);
@@ -114,6 +118,8 @@ public static class Update {
114118

115119
private final Map<String, String> env = new LinkedHashMap<>();
116120

121+
private String networkMode;
122+
117123
Update(ImageReference image) {
118124
this.image = image;
119125
}
@@ -122,7 +128,7 @@ private ContainerConfig run(Consumer<Update> update) {
122128
update.accept(this);
123129
try {
124130
return new ContainerConfig(this.user, this.image, this.command, this.args, this.labels, this.bindings,
125-
this.env);
131+
this.env, this.networkMode);
126132
}
127133
catch (IOException ex) {
128134
throw new IllegalStateException(ex);
@@ -182,6 +188,15 @@ public void withEnv(String name, String value) {
182188
this.env.put(name, value);
183189
}
184190

191+
/**
192+
* Update the container config with the network that the build container will
193+
* connect to.
194+
* @param networkMode the network
195+
*/
196+
public void withNetworkMode(String networkMode) {
197+
this.networkMode = networkMode;
198+
}
199+
185200
}
186201

187202
}

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuildRequestTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
*
4646
* @author Phillip Webb
4747
* @author Scott Frederick
48+
* @author Jeroen Meijer
4849
*/
4950
public class BuildRequestTests {
5051

@@ -199,6 +200,12 @@ void withBindingsWhenBindingsIsNullThrowsException() throws IOException {
199200
.withMessage("Bindings must not be null");
200201
}
201202

203+
@Test
204+
void withNetworkUpdatesNetwork() throws IOException {
205+
BuildRequest request = BuildRequest.forJarFile(writeTestJarFile("my-app-0.0.1.jar")).withNetwork("test");
206+
assertThat(request.getNetwork()).isEqualTo("test");
207+
}
208+
202209
private void hasExpectedJarContent(TarArchive archive) {
203210
try {
204211
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/LifecycleTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
*
6363
* @author Phillip Webb
6464
* @author Scott Frederick
65+
* @author Jeroen Meijer
6566
*/
6667
class LifecycleTests {
6768

@@ -188,6 +189,17 @@ void closeClearsVolumes() throws Exception {
188189
verify(this.docker.volume()).delete(VolumeName.of("pack-app-aaaaaaaaaa"), true);
189190
}
190191

192+
@Test
193+
void executeWithNetworkExecutesPhases() throws Exception {
194+
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
195+
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
196+
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
197+
BuildRequest request = getTestRequest().withNetwork("test");
198+
createLifecycle(request).execute();
199+
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-network.json"));
200+
assertThat(this.out.toString()).contains("Successfully built image 'docker.io/library/my-application:latest'");
201+
}
202+
191203
private DockerApi mockDockerApi() {
192204
DockerApi docker = mock(DockerApi.class);
193205
ImageApi imageApi = mock(ImageApi.class);

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
*
3333
* @author Phillip Webb
3434
* @author Scott Frederick
35+
* @author Jeroen Meijer
3536
*/
3637
class PhaseTests {
3738

@@ -132,4 +133,16 @@ void applyWhenWithEnvUpdatesConfigurationWithEnv() {
132133
verifyNoMoreInteractions(update);
133134
}
134135

136+
@Test
137+
void applyWhenWithNetworkModeUpdatesConfigurationWithNetworkMode() {
138+
Phase phase = new Phase("test", true);
139+
phase.withNetworkMode("test");
140+
Update update = mock(Update.class);
141+
phase.apply(update);
142+
verify(update).withCommand("/cnb/lifecycle/test");
143+
verify(update).withNetworkMode("test");
144+
verify(update).withLabel("author", "spring-boot");
145+
verifyNoMoreInteractions(update);
146+
}
147+
135148
}

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfigTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
*
3333
* @author Phillip Webb
3434
* @author Scott Frederick
35+
* @author Jeroen Meijer
3536
*/
3637
class ContainerConfigTests extends AbstractJsonTests {
3738

@@ -59,6 +60,7 @@ void writeToWritesJson() throws Exception {
5960
update.withBinding(Binding.from("bind-source", "bind-dest"));
6061
update.withEnv("name1", "value1");
6162
update.withEnv("name2", "value2");
63+
update.withNetworkMode("test");
6264
});
6365
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
6466
containerConfig.writeTo(outputStream);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"User" : "root",
3+
"Image" : "pack.local/ephemeral-builder",
4+
"Cmd" : [ "/cnb/lifecycle/creator", "-app", "/workspace", "-platform", "/platform", "-run-image", "docker.io/cloudfoundry/run:latest", "-layers", "/layers", "-cache-dir", "/cache", "-launch-cache", "/launch-cache", "-daemon", "-process-type=web", "docker.io/library/my-application:latest" ],
5+
"Env" : [ "CNB_PLATFORM_API=0.4" ],
6+
"Labels" : {
7+
"author" : "spring-boot"
8+
},
9+
"HostConfig" : {
10+
"NetworkMode" : "test",
11+
"Binds" : [ "/var/run/docker.sock:/var/run/docker.sock", "pack-layers-aaaaaaaaaa:/layers", "pack-app-aaaaaaaaaa:/workspace", "pack-cache-b35197ac41ea.build:/cache", "pack-cache-b35197ac41ea.launch:/launch-cache" ]
12+
}
13+
}

0 commit comments

Comments
 (0)