Warn when image building workspace directories cannot be deleted
When the `buildWorkspace` location in the `spring-boot:build-image` Maven goal or `bootBuildImage` Gradle task is configured to use a local bind source, the location is passed to the CNB lifecycle without further processing by Spring Boot. The lifecycle is in control of creating any files in the specified location. Spring Boot tries to remove the directories at the specified location after an image is successfully created, but should not fail the image build if the lifecycle has created files or directories with permissions that keep them from being deleted successfully. Fixes gh-40760
This commit is contained in:
parent
524424bc98
commit
cd441130bd
|
|
@ -102,6 +102,17 @@ public abstract class AbstractBuildLog implements BuildLog {
|
|||
log();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failedCleaningWorkDir(Cache cache, Exception exception) {
|
||||
StringBuilder message = new StringBuilder("Warning: Working location " + cache + " could not be cleaned");
|
||||
if (exception != null) {
|
||||
message.append(": ").append(exception.getMessage());
|
||||
}
|
||||
log();
|
||||
log(message.toString());
|
||||
log();
|
||||
}
|
||||
|
||||
private String getDigest(Image image) {
|
||||
List<String> digests = image.getDigests();
|
||||
return (digests.isEmpty() ? "" : digests.get(0));
|
||||
|
|
|
|||
|
|
@ -114,6 +114,13 @@ public interface BuildLog {
|
|||
*/
|
||||
void taggedImage(ImageReference tag);
|
||||
|
||||
/**
|
||||
* Log that a cache cleanup step was not completed successfully.
|
||||
* @param cache the cache
|
||||
* @param exception any exception that caused the failure
|
||||
*/
|
||||
void failedCleaningWorkDir(Cache cache, Exception exception);
|
||||
|
||||
/**
|
||||
* Factory method that returns a {@link BuildLog} the outputs to {@link System#out}.
|
||||
* @return a build log instance that logs to system out
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ class Lifecycle implements Closeable {
|
|||
deleteVolume(cache.getVolume().getVolumeName());
|
||||
}
|
||||
if (cache.getBind() != null) {
|
||||
deleteBind(cache.getBind().getSource());
|
||||
deleteBind(cache.getBind());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -319,12 +319,12 @@ class Lifecycle implements Closeable {
|
|||
this.docker.volume().delete(name, true);
|
||||
}
|
||||
|
||||
private void deleteBind(String source) {
|
||||
private void deleteBind(Cache.Bind bind) {
|
||||
try {
|
||||
FileSystemUtils.deleteRecursively(Path.of(source));
|
||||
FileSystemUtils.deleteRecursively(Path.of(bind.getSource()));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Error cleaning bind mount directory '" + source + "'", ex);
|
||||
this.log.failedCleaningWorkDir(bind, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
|
|||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.gradle.testkit.runner.BuildResult;
|
||||
import org.gradle.testkit.runner.TaskOutcome;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.TestTemplate;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
|
|
@ -301,10 +300,8 @@ class BootBuildImageIntegrationTests {
|
|||
}
|
||||
|
||||
@TestTemplate
|
||||
@EnabledOnOs(value = OS.LINUX,
|
||||
disabledReason = "Works with Docker Engine on Linux but is not reliable with "
|
||||
+ "Docker Desktop on other OSs")
|
||||
@Disabled("gh-40760")
|
||||
@EnabledOnOs(value = OS.LINUX, disabledReason = "Works with Docker Engine on Linux but is not reliable with "
|
||||
+ "Docker Desktop on other OSs")
|
||||
void buildsImageWithBindCaches() throws IOException {
|
||||
writeMainClass();
|
||||
writeLongNameResource();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import java.time.OffsetDateTime;
|
|||
import java.util.Random;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.TestTemplate;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
|
|
@ -402,10 +401,8 @@ class BuildImageTests extends AbstractArchiveIntegrationTests {
|
|||
}
|
||||
|
||||
@TestTemplate
|
||||
@EnabledOnOs(value = OS.LINUX,
|
||||
disabledReason = "Works with Docker Engine on Linux but is not reliable with "
|
||||
+ "Docker Desktop on other OSs")
|
||||
@Disabled("gh-40760")
|
||||
@EnabledOnOs(value = OS.LINUX, disabledReason = "Works with Docker Engine on Linux but is not reliable with "
|
||||
+ "Docker Desktop on other OSs")
|
||||
void whenBuildImageIsInvokedWithBindCaches(MavenBuild mavenBuild) {
|
||||
String testBuildId = randomString();
|
||||
mavenBuild.project("build-image-bind-caches")
|
||||
|
|
|
|||
Loading…
Reference in New Issue