summaryrefslogtreecommitdiff
path: root/test/e2e/rmi_test.go
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2021-02-08 13:51:31 +0100
committerValentin Rothberg <rothberg@redhat.com>2021-02-08 14:58:17 +0100
commitfeecdf919f37d34033b58977e6af5c34bf26b6c4 (patch)
treec74b72d9e2700a4fa9f2227e571720a9d745e38c /test/e2e/rmi_test.go
parent69ddbde9835159b19fab33f1dd22353e4b1ca484 (diff)
downloadpodman-feecdf919f37d34033b58977e6af5c34bf26b6c4.tar.gz
podman-feecdf919f37d34033b58977e6af5c34bf26b6c4.tar.bz2
podman-feecdf919f37d34033b58977e6af5c34bf26b6c4.zip
make `podman rmi` more robust
The c/storage library is subject to TOCTOUs as the central container and image storage may be shared by many instances of many tools. As shown in #6510, it's fairly easy to have multiple instances of Podman running in parallel and yield image-lookup errors when removing them. The underlying issue is the TOCTOU of removal being split into multiple stages of first reading the local images and then removing them. Some images may already have been removed in between the two stages. To make image removal more robust, handle errors at stage two when a given image is not present (anymore) in the storage. Fixes: #6510 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'test/e2e/rmi_test.go')
-rw-r--r--test/e2e/rmi_test.go30
1 files changed, 30 insertions, 0 deletions
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index 4833a282e..257570ea7 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -1,7 +1,9 @@
package integration
import (
+ "fmt"
"os"
+ "sync"
. "github.com/containers/podman/v2/test/utils"
. "github.com/onsi/ginkgo"
@@ -275,4 +277,32 @@ RUN find $LOCAL
match, _ := session.ErrorGrepString("image name or ID must be specified")
Expect(match).To(BeTrue())
})
+
+ It("podman image rm - concurrent with shared layers", func() {
+ // #6510 has shown a fairly simple reproducer to force storage
+ // errors during parallel image removal. Since it's subject to
+ // a race, we may not hit the condition a 100 percent of times
+ // but ocal reproducers hit it all the time.
+
+ var wg sync.WaitGroup
+
+ buildAndRemove := func(i int) {
+ defer GinkgoRecover()
+ defer wg.Done()
+ imageName := fmt.Sprintf("rmtest:%d", i)
+ containerfile := `FROM quay.io/libpod/cirros:latest
+RUN ` + fmt.Sprintf("touch %s", imageName)
+
+ podmanTest.BuildImage(containerfile, imageName, "false")
+ session := podmanTest.Podman([]string{"rmi", "-f", imageName})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ }
+
+ wg.Add(10)
+ for i := 0; i < 10; i++ {
+ go buildAndRemove(i)
+ }
+ wg.Wait()
+ })
})