diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java index 8b2e822cfb..b7feaa5277 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java @@ -265,6 +265,12 @@ public class BuildRequest { 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) { 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, @@ -371,6 +377,11 @@ public class BuildRequest { return this.bindings; } + /** + * Return the network the build container will connect to. + * @return the network + * @since 2.6.0 + */ public String getNetwork() { return this.network; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java index f67470445b..ae372bc71e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Lifecycle.java @@ -148,7 +148,9 @@ class Lifecycle implements Closeable { this.request.getBindings().forEach(phase::withBinding); } phase.withEnv(PLATFORM_API_VERSION_KEY, this.platformVersion.toString()); - phase.withNetworkMode(this.request.getNetwork()); + if (this.request.getNetwork() != null) { + phase.withNetworkMode(this.request.getNetwork()); + } return phase; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java index fab5bb4845..8c0264f836 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Phase.java @@ -104,6 +104,10 @@ class Phase { 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) { this.networkMode = networkMode; } @@ -134,7 +138,9 @@ class Phase { update.withLabel("author", "spring-boot"); this.bindings.forEach(update::withBinding); this.env.forEach(update::withEnv); - update.withNetworkMode(this.networkMode); + if (this.networkMode != null) { + update.withNetworkMode(this.networkMode); + } } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java index 1df69c312e..a411b49f28 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ContainerConfig.java @@ -188,6 +188,11 @@ public class ContainerConfig { 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) { this.networkMode = networkMode; } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java index e2cc1bc47b..6bed915d45 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/PhaseTests.java @@ -57,7 +57,6 @@ class PhaseTests { phase.apply(update); verify(update).withCommand("/cnb/lifecycle/test", NO_ARGS); verify(update).withLabel("author", "spring-boot"); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } @@ -71,7 +70,6 @@ class PhaseTests { verify(update).withBinding(Binding.from("/var/run/docker.sock", "/var/run/docker.sock")); verify(update).withCommand("/cnb/lifecycle/test", NO_ARGS); verify(update).withLabel("author", "spring-boot"); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } @@ -83,7 +81,6 @@ class PhaseTests { phase.apply(update); verify(update).withCommand("/cnb/lifecycle/test", "-log-level", "debug"); verify(update).withLabel("author", "spring-boot"); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } @@ -95,7 +92,6 @@ class PhaseTests { phase.apply(update); verify(update).withCommand("/cnb/lifecycle/test"); verify(update).withLabel("author", "spring-boot"); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } @@ -107,7 +103,6 @@ class PhaseTests { phase.apply(update); verify(update).withCommand("/cnb/lifecycle/test", "a", "b", "c"); verify(update).withLabel("author", "spring-boot"); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } @@ -121,7 +116,6 @@ class PhaseTests { verify(update).withCommand("/cnb/lifecycle/test"); verify(update).withLabel("author", "spring-boot"); verify(update).withBinding(Binding.from(volumeName, "/test")); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } @@ -136,7 +130,6 @@ class PhaseTests { verify(update).withLabel("author", "spring-boot"); verify(update).withEnv("name1", "value1"); verify(update).withEnv("name2", "value2"); - verify(update).withNetworkMode(null); verifyNoMoreInteractions(update); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 888d1524c9..0d1677aac2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -155,6 +155,12 @@ Where `` can contain: * `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` | Whether to clean the cache before building. @@ -170,13 +176,6 @@ Where `` can contain: | Whether to publish the generated image to a Docker registry. | `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. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java index a8517e11ef..8f5d4691af 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests.java @@ -71,6 +71,7 @@ class BootBuildImageIntegrationTests { assertThat(result.getOutput()).contains("docker.io/library/" + projectName); assertThat(result.getOutput()).contains("---> Test Info buildpack building"); 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"); removeImage(projectName); } @@ -247,6 +248,20 @@ class BootBuildImageIntegrationTests { 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 void failsWithBuilderError() throws IOException { writeMainClass(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithNetworkModeNone.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithNetworkModeNone.gradle new file mode 100644 index 0000000000..d5b5b0113e --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootBuildImageIntegrationTests-buildsImageWithNetworkModeNone.gradle @@ -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" +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 2a58ca004d..df8aa32b50 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -163,6 +163,12 @@ Where `` can contain: * `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` + (`spring-boot.build-image.cleanCache`) | Whether to clean the cache before building. @@ -177,13 +183,6 @@ Where `` can contain: | Whether to publish the generated image to a Docker registry. | `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. diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java index 6bc3d56770..0d75a99e44 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/java/org/springframework/boot/maven/BuildImageTests.java @@ -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 void whenBuildImageIsInvokedOnMultiModuleProjectWithPackageGoal(MavenBuild mavenBuild) { mavenBuild.project("build-image-multi-module").goals("package") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-network/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-network/pom.xml new file mode 100644 index 0000000000..1f0ca34f92 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-network/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + org.springframework.boot.maven.it + build-image-network + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + @java.version@ + @java.version@ + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + build-image + + + + projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1 + none + + + + + + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-network/src/main/java/org/test/SampleApplication.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-network/src/main/java/org/test/SampleApplication.java new file mode 100644 index 0000000000..27259ff01a --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-network/src/main/java/org/test/SampleApplication.java @@ -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" + } + } + +} diff --git a/src/spring-boot-builder/buildpacks/test-info/bin/build b/src/spring-boot-builder/buildpacks/test-info/bin/build index a9317aa0c6..8c1dce7774 100755 --- a/src/spring-boot-builder/buildpacks/test-info/bin/build +++ b/src/spring-boot-builder/buildpacks/test-info/bin/build @@ -32,4 +32,6 @@ if [[ -f META-INF/MANIFEST.MF ]]; then cat META-INF/MANIFEST.MF fi +echo "Network status: $(curl --silent --head https://spring.io | grep -E '^HTTP' || echo "curl failed")" + echo "---> Test Info buildpack done"