Polish "Add network option for image building"

See gh-27486
pull/27659/head
Scott Frederick 3 years ago
parent 8e6d03b221
commit 2178c281e9

@ -265,6 +265,12 @@ public class BuildRequest {
this.network); this.network);
} }
/**
* Return a new {@link BuildRequest} with an updated network setting.
* @param network the network the build container will connect to
* @return an updated build request
* @since 2.6.0
*/
public BuildRequest withNetwork(String network) { public BuildRequest withNetwork(String network) {
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env, 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.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
@ -371,6 +377,11 @@ public class BuildRequest {
return this.bindings; return this.bindings;
} }
/**
* Return the network the build container will connect to.
* @return the network
* @since 2.6.0
*/
public String getNetwork() { public String getNetwork() {
return this.network; return this.network;
} }

@ -148,7 +148,9 @@ class Lifecycle implements Closeable {
this.request.getBindings().forEach(phase::withBinding); this.request.getBindings().forEach(phase::withBinding);
} }
phase.withEnv(PLATFORM_API_VERSION_KEY, this.platformVersion.toString()); phase.withEnv(PLATFORM_API_VERSION_KEY, this.platformVersion.toString());
if (this.request.getNetwork() != null) {
phase.withNetworkMode(this.request.getNetwork()); phase.withNetworkMode(this.request.getNetwork());
}
return phase; return phase;
} }

@ -104,6 +104,10 @@ class Phase {
this.env.put(name, value); this.env.put(name, value);
} }
/**
* Update this phase with the network the build container will connect to.
* @param networkMode the network
*/
void withNetworkMode(String networkMode) { void withNetworkMode(String networkMode) {
this.networkMode = networkMode; this.networkMode = networkMode;
} }
@ -134,7 +138,9 @@ class Phase {
update.withLabel("author", "spring-boot"); update.withLabel("author", "spring-boot");
this.bindings.forEach(update::withBinding); this.bindings.forEach(update::withBinding);
this.env.forEach(update::withEnv); this.env.forEach(update::withEnv);
if (this.networkMode != null) {
update.withNetworkMode(this.networkMode); update.withNetworkMode(this.networkMode);
} }
}
} }

@ -188,6 +188,11 @@ public class ContainerConfig {
this.env.put(name, value); this.env.put(name, value);
} }
/**
* Update the container config with the network that the build container will
* connect to.
* @param networkMode the network
*/
public void withNetworkMode(String networkMode) { public void withNetworkMode(String networkMode) {
this.networkMode = networkMode; this.networkMode = networkMode;
} }

@ -57,7 +57,6 @@ class PhaseTests {
phase.apply(update); phase.apply(update);
verify(update).withCommand("/cnb/lifecycle/test", NO_ARGS); verify(update).withCommand("/cnb/lifecycle/test", NO_ARGS);
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }
@ -71,7 +70,6 @@ class PhaseTests {
verify(update).withBinding(Binding.from("/var/run/docker.sock", "/var/run/docker.sock")); verify(update).withBinding(Binding.from("/var/run/docker.sock", "/var/run/docker.sock"));
verify(update).withCommand("/cnb/lifecycle/test", NO_ARGS); verify(update).withCommand("/cnb/lifecycle/test", NO_ARGS);
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }
@ -83,7 +81,6 @@ class PhaseTests {
phase.apply(update); phase.apply(update);
verify(update).withCommand("/cnb/lifecycle/test", "-log-level", "debug"); verify(update).withCommand("/cnb/lifecycle/test", "-log-level", "debug");
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }
@ -95,7 +92,6 @@ class PhaseTests {
phase.apply(update); phase.apply(update);
verify(update).withCommand("/cnb/lifecycle/test"); verify(update).withCommand("/cnb/lifecycle/test");
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }
@ -107,7 +103,6 @@ class PhaseTests {
phase.apply(update); phase.apply(update);
verify(update).withCommand("/cnb/lifecycle/test", "a", "b", "c"); verify(update).withCommand("/cnb/lifecycle/test", "a", "b", "c");
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }
@ -121,7 +116,6 @@ class PhaseTests {
verify(update).withCommand("/cnb/lifecycle/test"); verify(update).withCommand("/cnb/lifecycle/test");
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withBinding(Binding.from(volumeName, "/test")); verify(update).withBinding(Binding.from(volumeName, "/test"));
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }
@ -136,7 +130,6 @@ class PhaseTests {
verify(update).withLabel("author", "spring-boot"); verify(update).withLabel("author", "spring-boot");
verify(update).withEnv("name1", "value1"); verify(update).withEnv("name1", "value1");
verify(update).withEnv("name2", "value2"); verify(update).withEnv("name2", "value2");
verify(update).withNetworkMode(null);
verifyNoMoreInteractions(update); verifyNoMoreInteractions(update);
} }

@ -155,6 +155,12 @@ Where `<options>` can contain:
* `volume-opt=key=value` to specify key-value pairs consisting of an option name and its value * `volume-opt=key=value` to specify key-value pairs consisting of an option name and its value
| |
| `network`
| `--network`
| The https://docs.docker.com/network/#network-drivers[network driver] the builder container will be configured to use.
The value supplied will be passed unvalidated to Docker when creating the builder container.
|
| `cleanCache` | `cleanCache`
| `--cleanCache` | `--cleanCache`
| Whether to clean the cache before building. | Whether to clean the cache before building.
@ -170,13 +176,6 @@ Where `<options>` can contain:
| Whether to publish the generated image to a Docker registry. | Whether to publish the generated image to a Docker registry.
| `false` | `false`
| `network`
| `--network`
| The network the build container will connect to. The value supplied for this option will be passed
unvalidated as `HostConfig.NetworkMode` to the configuration which creates the build container,
see https://docs.docker.com/engine/api/v1.41/#operation/ContainerCreate[Docker's engine API].
Using this option is similar to running `docker build --network ...`.
|
|=== |===
NOTE: The plugin detects the target Java compatibility of the project using the JavaPlugin's `targetCompatibility` property. NOTE: The plugin detects the target Java compatibility of the project using the JavaPlugin's `targetCompatibility` property.

@ -71,6 +71,7 @@ class BootBuildImageIntegrationTests {
assertThat(result.getOutput()).contains("docker.io/library/" + projectName); assertThat(result.getOutput()).contains("docker.io/library/" + projectName);
assertThat(result.getOutput()).contains("---> Test Info buildpack building"); assertThat(result.getOutput()).contains("---> Test Info buildpack building");
assertThat(result.getOutput()).contains("env: BP_JVM_VERSION=8.*"); 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"); assertThat(result.getOutput()).contains("---> Test Info buildpack done");
removeImage(projectName); removeImage(projectName);
} }
@ -247,6 +248,20 @@ class BootBuildImageIntegrationTests {
removeImage(projectName); removeImage(projectName);
} }
@TestTemplate
void buildsImageWithNetworkModeNone() 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("Network status: curl failed");
assertThat(result.getOutput()).contains("---> Test Info buildpack done");
removeImage(projectName);
}
@TestTemplate @TestTemplate
void failsWithBuilderError() throws IOException { void failsWithBuilderError() throws IOException {
writeMainClass(); writeMainClass();

@ -0,0 +1,16 @@
plugins {
id 'java'
id 'org.springframework.boot' version '{version}'
}
if (project.hasProperty('applyWarPlugin')) {
apply plugin: 'war'
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
bootBuildImage {
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1"
network = "none"
}

@ -163,6 +163,12 @@ Where `<options>` can contain:
* `volume-opt=key=value` to specify key-value pairs consisting of an option name and its value * `volume-opt=key=value` to specify key-value pairs consisting of an option name and its value
| |
| `network` +
(`spring-boot.build-image.network`)
| The https://docs.docker.com/network/#network-drivers[network driver] the builder container will be configured to use.
The value supplied will be passed unvalidated to Docker when creating the builder container.
|
| `cleanCache` + | `cleanCache` +
(`spring-boot.build-image.cleanCache`) (`spring-boot.build-image.cleanCache`)
| Whether to clean the cache before building. | Whether to clean the cache before building.
@ -177,13 +183,6 @@ Where `<options>` can contain:
| Whether to publish the generated image to a Docker registry. | Whether to publish the generated image to a Docker registry.
| `false` | `false`
| `network` +
(`spring-boot.build-image.network`)
| The network the build container will connect to. The value supplied for this option will be passed
unvalidated as `HostConfig.NetworkMode` to the configuration which creates the build container,
see https://docs.docker.com/engine/api/v1.41/#operation/ContainerCreate[Docker's engine API].
Using this option is similar to running `docker build --network ...`.
|
|=== |===
NOTE: The plugin detects the target Java compatibility of the project using the compiler's plugin configuration or the `maven.compiler.target` property. NOTE: The plugin detects the target Java compatibility of the project using the compiler's plugin configuration or the `maven.compiler.target` property.

@ -270,6 +270,17 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
}); });
} }
@TestTemplate
void whenBuildImageIsInvokedWithNetworkModeNone(MavenBuild mavenBuild) {
mavenBuild.project("build-image-network").goals("package")
.systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT").execute((project) -> {
assertThat(buildLog(project)).contains("Building image")
.contains("docker.io/library/build-image-network:0.0.1.BUILD-SNAPSHOT")
.contains("Network status: curl failed").contains("Successfully built image");
removeImage("build-image-network", "0.0.1.BUILD-SNAPSHOT");
});
}
@TestTemplate @TestTemplate
void whenBuildImageIsInvokedOnMultiModuleProjectWithPackageGoal(MavenBuild mavenBuild) { void whenBuildImageIsInvokedOnMultiModuleProjectWithPackageGoal(MavenBuild mavenBuild) {
mavenBuild.project("build-image-multi-module").goals("package") mavenBuild.project("build-image-multi-module").goals("package")

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot.maven.it</groupId>
<artifactId>build-image-network</artifactId>
<version>0.0.1.BUILD-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>@java.version@</maven.compiler.source>
<maven.compiler.target>@java.version@</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
<configuration>
<image>
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1</builder>
<network>none</network>
</image>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,28 @@
/*
* Copyright 2012-2020 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.test;
public class SampleApplication {
public static void main(String[] args) throws Exception {
System.out.println("Launched");
synchronized(args) {
args.wait(); // Prevent exit"
}
}
}

@ -32,4 +32,6 @@ if [[ -f META-INF/MANIFEST.MF ]]; then
cat META-INF/MANIFEST.MF cat META-INF/MANIFEST.MF
fi fi
echo "Network status: $(curl --silent --head https://spring.io | grep -E '^HTTP' || echo "curl failed")"
echo "---> Test Info buildpack done" echo "---> Test Info buildpack done"

Loading…
Cancel
Save