Clean up after unexpectedly terminated build

The `podman system prune` command is able to remove build containers that were created during the build, but were not removed because the build terminated unexpectedly.

By default, build containers are not removed to prevent interference with builds in progress. Use the **--build** flag when running the command to remove build containers as well.

Fixes: https://issues.redhat.com/browse/RHEL-62009

Signed-off-by: Jan Rodák <hony.com@seznam.cz>
This commit is contained in:
Jan Rodák
2025-01-20 21:39:54 +01:00
parent 3b6c7665b9
commit 81eb84fdaa
10 changed files with 158 additions and 11 deletions

View File

@@ -6,6 +6,8 @@ import (
"fmt"
"os"
"path/filepath"
"syscall"
"time"
. "github.com/containers/podman/v5/test/utils"
. "github.com/onsi/ginkgo/v2"
@@ -23,6 +25,11 @@ FROM scratch
ENV test1=test1
ENV test2=test2`
var longBuildImage = fmt.Sprintf(`
FROM %s
RUN echo "Hello, World!"
RUN RUN echo "Please use signal 9 this will never ends" && sleep 10000s`, ALPINE)
var _ = Describe("Podman prune", func() {
It("podman container prune containers", func() {
@@ -580,4 +587,63 @@ var _ = Describe("Podman prune", func() {
Expect(err).ToNot(HaveOccurred())
Expect(dirents).To(HaveLen(3))
})
It("podman system prune --build clean up after terminated build", func() {
useCustomNetworkDir(podmanTest, tempdir)
podmanTest.BuildImage(pruneImage, "alpine_notleaker:latest", "false")
create := podmanTest.Podman([]string{"create", "--name", "test", BB, "sleep", "10000"})
create.WaitWithDefaultTimeout()
Expect(create).Should(ExitCleanly())
containerFilePath := filepath.Join(podmanTest.TempDir, "ContainerFile-podman-leaker")
err := os.WriteFile(containerFilePath, []byte(longBuildImage), 0755)
Expect(err).ToNot(HaveOccurred())
build := podmanTest.Podman([]string{"build", "-f", containerFilePath, "-t", "podmanleaker"})
// Build will never finish so let's wait for build to ask for SIGKILL to simulate a failed build that leaves stage containers.
matchedOutput := false
for range 900 {
if build.LineInOutputContains("Please use signal 9") {
matchedOutput = true
build.Signal(syscall.SIGKILL)
break
}
time.Sleep(100 * time.Millisecond)
}
if !matchedOutput {
Fail("Did not match special string in podman build")
}
// Check Intermediate image of stage container
none := podmanTest.Podman([]string{"images", "-a"})
none.WaitWithDefaultTimeout()
Expect(none).Should(ExitCleanly())
Expect(none.OutputToString()).Should(ContainSubstring("none"))
// Check if Container and Stage Container exist
count := podmanTest.Podman([]string{"ps", "-aq", "--external"})
count.WaitWithDefaultTimeout()
Expect(count).Should(ExitCleanly())
Expect(count.OutputToStringArray()).To(HaveLen(3))
prune := podmanTest.Podman([]string{"system", "prune", "--build", "-f"})
prune.WaitWithDefaultTimeout()
Expect(prune).Should(ExitCleanly())
// Container should still exist, but no stage containers
count = podmanTest.Podman([]string{"ps", "-aq", "--external"})
count.WaitWithDefaultTimeout()
Expect(count).Should(ExitCleanly())
Expect(count.OutputToString()).To(BeEmpty())
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
after := podmanTest.Podman([]string{"images", "-a"})
after.WaitWithDefaultTimeout()
Expect(after).Should(ExitCleanly())
Expect(after.OutputToString()).ShouldNot(ContainSubstring("none"))
Expect(after.OutputToString()).Should(ContainSubstring("notleaker"))
})
})