diff --git a/cmd/buildah/rmi.go b/cmd/buildah/rmi.go index c66015670d5..796d6766661 100644 --- a/cmd/buildah/rmi.go +++ b/cmd/buildah/rmi.go @@ -3,6 +3,11 @@ package main import ( "fmt" + "github.com/Sirupsen/logrus" + "github.com/containers/image/storage" + "github.com/containers/image/transports" + "github.com/containers/image/transports/alltransports" + "github.com/containers/image/types" "github.com/urfave/cli" ) @@ -20,7 +25,7 @@ var ( func rmiCmd(c *cli.Context) error { args := c.Args() if len(args) == 0 { - return fmt.Errorf("image ID must be specified") + return fmt.Errorf("image name or ID must be specified") } store, err := getStore(c) @@ -29,7 +34,64 @@ func rmiCmd(c *cli.Context) error { } for _, id := range args { - _, err := store.DeleteImage(id, true) + // If it's an exact name or ID match with the underlying + // storage library's information about the image, then it's + // enough. + _, err = store.DeleteImage(id, true) + if err != nil { + var ref types.ImageReference + // If it's looks like a proper image reference, parse + // it and check if it corresponds to an image that + // actually exists. + if ref2, err2 := alltransports.ParseImageName(id); err2 == nil { + if img, err2 := ref2.NewImage(nil); err2 == nil { + img.Close() + ref = ref2 + } else { + logrus.Debugf("error confirming presence of image %q: %v", transports.ImageName(ref2), err2) + } + } else { + logrus.Debugf("error parsing %q as an image reference: %v", id, err2) + } + if ref == nil { + // If it's looks like an image reference that's + // relative to our storage, parse it and check + // if it corresponds to an image that actually + // exists. + if ref2, err2 := storage.Transport.ParseStoreReference(store, id); err2 == nil { + if img, err2 := ref2.NewImage(nil); err2 == nil { + img.Close() + ref = ref2 + } else { + logrus.Debugf("error confirming presence of image %q: %v", transports.ImageName(ref2), err2) + } + } else { + logrus.Debugf("error parsing %q as a store reference: %v", id, err2) + } + } + if ref == nil { + // If it might be an ID that's relative to our + // storage, parse it and check if it + // corresponds to an image that actually + // exists. This _should_ be redundant, since + // we already tried deleting the image using + // the ID directly above, but it can't hurt, + // either. + if ref2, err2 := storage.Transport.ParseStoreReference(store, "@"+id); err2 == nil { + if img, err2 := ref2.NewImage(nil); err2 == nil { + img.Close() + ref = ref2 + } else { + logrus.Debugf("error confirming presence of image %q: %v", transports.ImageName(ref2), err2) + } + } else { + logrus.Debugf("error parsing %q as an image reference: %v", "@"+id, err2) + } + } + if ref != nil { + err = ref.DeleteImage(nil) + } + } if err != nil { return fmt.Errorf("error removing image %q: %v", id, err) } diff --git a/tests/basic.bats b/tests/basic.bats index a32d2a629b3..7b0534fc2ce 100644 --- a/tests/basic.bats +++ b/tests/basic.bats @@ -67,6 +67,7 @@ load helpers [ "$status" -eq 1 ] buildah commit --signature-policy ${TESTSDIR}/policy.json $newcid containers-storage:another-new-image buildah commit --signature-policy ${TESTSDIR}/policy.json $newcid yet-another-new-image + buildah commit --signature-policy ${TESTSDIR}/policy.json $newcid containers-storage:gratuitous-new-image buildah unmount $newcid buildah rm $newcid @@ -92,5 +93,16 @@ load helpers cmp ${TESTDIR}/randomfile $yetanothernewroot/randomfile test -s $yetanothernewroot/other-randomfile cmp ${TESTDIR}/other-randomfile $yetanothernewroot/other-randomfile - buildah rm $yetanothernewcid + buildah delete $yetanothernewcid + + buildah rmi containers-storage:other-new-image + buildah rmi another-new-image + run buildah --debug=false images -q + [ "$status" -eq 0 ] + [ "$output" != "" ] + for id in $output ; do + buildah rmi $id + done + run buildah --debug=false images -q + [ "$output" == "" ] }