From 5d793afcb5860b4a0c0377ac1e9d57701fa99bf6 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Fri, 30 Jul 2021 12:24:28 -0500 Subject: [PATCH] Prevent hanging when deleting Docker builder container after exception An exception being thrown while the Maven plugin is uploading the app archive bits to an ephemeral builder container would leave the interaction with the Docker daemon in a state that caused further interaction with the daemon (such as deleting the ephemeral builder) to hang indefinitely. This commit cleans up the connection on an exception to prevent this condition. Fixes gh-27515 --- .../boot/maven/BuildImageTests.java | 18 ++++++++ .../build-image-multi-module/app/pom.xml | 42 +++++++++++++++++++ .../main/java/org/test/SampleApplication.java | 30 +++++++++++++ .../build-image-multi-module/library/pom.xml | 12 ++++++ .../src/main/java/org/test/SampleLibrary.java | 23 ++++++++++ .../projects/build-image-multi-module/pom.xml | 30 +++++++++++++ .../boot/maven/BuildImageMojo.java | 8 +++- 7 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/pom.xml create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/src/main/java/org/test/SampleApplication.java create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/pom.xml create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/src/main/java/org/test/SampleLibrary.java create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/pom.xml 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 95dae4bee2fe..90275280dbe4 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 @@ -228,6 +228,24 @@ void whenBuildImageIsInvokedWithZipPackaging(MavenBuild mavenBuild) { }); } + @TestTemplate + void whenBuildImageIsInvokedOnMultiModuleProjectWithPackageGoal(MavenBuild mavenBuild) { + mavenBuild.project("build-image-multi-module").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-multi-module-app:0.0.1.BUILD-SNAPSHOT") + .contains("Successfully built image"); + removeImage("build-image-multi-module-app", "0.0.1.BUILD-SNAPSHOT"); + }); + } + + @TestTemplate + void failsWhenBuildImageIsInvokedOnMultiModuleProjectWithBuildImageGoal(MavenBuild mavenBuild) { + mavenBuild.project("build-image-multi-module").goals("spring-boot:build-image") + .systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT").executeAndFail( + (project) -> assertThat(buildLog(project)).contains("Error packaging archive for image")); + } + @TestTemplate void failsWhenPublishWithoutPublishRegistryConfigured(MavenBuild mavenBuild) { mavenBuild.project("build-image").goals("package").systemProperty("spring-boot.build-image.publish", "true") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/pom.xml new file mode 100644 index 000000000000..b62508b86cc7 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + org.springframework.boot.maven.it + build-image-multi-module + 0.0.1.BUILD-SNAPSHOT + + build-image-multi-module-app + app + + + + org.springframework.boot.maven.it + build-image-multi-module-library + 0.0.1.BUILD-SNAPSHOT + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + build-image + + + + projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.1 + + + + + + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/src/main/java/org/test/SampleApplication.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/src/main/java/org/test/SampleApplication.java new file mode 100644 index 000000000000..a2ad26ea7165 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/app/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,30 @@ +/* + * 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; + +import org.test.SampleLibrary; + +public class SampleApplication { + + public static void main(String[] args) throws Exception { + System.out.println(SampleLibrary.getMessage()); + synchronized (args) { + args.wait(); // Prevent exit" + } + } + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/pom.xml new file mode 100644 index 000000000000..85907f446000 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + org.springframework.boot.maven.it + build-image-multi-module + 0.0.1.BUILD-SNAPSHOT + + build-image-multi-module-library + library + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/src/main/java/org/test/SampleLibrary.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/src/main/java/org/test/SampleLibrary.java new file mode 100644 index 000000000000..e70a97eca11f --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/library/src/main/java/org/test/SampleLibrary.java @@ -0,0 +1,23 @@ +/* + * Copyright 2012-2021 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 SampleLibrary { + public static String getMessage() { + return "Launched"; + } +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/pom.xml new file mode 100644 index 000000000000..43f482f9629e --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/intTest/projects/build-image-multi-module/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + org.springframework.boot.maven.it + build-image-multi-module + 0.0.1.BUILD-SNAPSHOT + pom + + UTF-8 + @java.version@ + @java.version@ + + + + library + app + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java index 340e98ff785f..34520d6f9acc 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java @@ -390,7 +390,13 @@ static class PackagedTarArchive implements TarArchive { public void writeTo(OutputStream outputStream) throws IOException { TarArchiveOutputStream tar = new TarArchiveOutputStream(outputStream); tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); - this.packager.packageImage(this.libraries, (entry, entryWriter) -> write(entry, entryWriter, tar)); + try { + this.packager.packageImage(this.libraries, (entry, entryWriter) -> write(entry, entryWriter, tar)); + } + catch (RuntimeException ex) { + outputStream.close(); + throw new RuntimeException("Error packaging archive for image", ex); + } } private void write(ZipEntry jarEntry, EntryWriter entryWriter, TarArchiveOutputStream tar) {