Skip to content

Commit

Permalink
libimage: force remove: only untag on multi tag image
Browse files Browse the repository at this point in the history
When removing an image by name, do not remove the image and all its
tags, even if force is set.  Instead, just untag the specified name.

Note: adjust the load test to preserve the order in the untagged field.

Also vendor in the latest HEAD in containers/image to fix a bug revealed
in Podman CI.

Context: containers/podman/issues/10685
Signed-off-by: Valentin Rothberg <[email protected]>
  • Loading branch information
vrothberg committed Jun 17, 2021
1 parent a1e5456 commit c6578d7
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 38 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.15

require (
github.com/BurntSushi/toml v0.3.1
github.com/containers/image/v5 v5.13.1
github.com/containers/image/v5 v5.13.2-0.20210617132750-db0df5e0cf5e
github.com/containers/ocicrypt v1.1.1
github.com/containers/storage v1.32.2
github.com/disiqueira/gotree/v3 v3.0.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
github.com/containers/image/v5 v5.13.1 h1:eUb9YHEEo+akiQQEfCqZbAa9edg9Y6Mm30BG3NU4MbY=
github.com/containers/image/v5 v5.13.1/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag=
github.com/containers/image/v5 v5.13.2-0.20210617132750-db0df5e0cf5e h1:5Q9jlvOsaPAavVxGbb2gBHcYi/SKKXERzPUCpeTP5E4=
github.com/containers/image/v5 v5.13.2-0.20210617132750-db0df5e0cf5e/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
Expand Down
16 changes: 9 additions & 7 deletions libimage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,17 +329,19 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport,
// an `rmi foo` will not untag "foo" but instead attempt to remove the
// entire image. If there's a container using "foo", we should get an
// error.
if options.Force || referencedBy == "" || numNames == 1 {
if referencedBy == "" || numNames == 1 {
// DO NOTHING, the image will be removed
} else {
byID := strings.HasPrefix(i.ID(), referencedBy)
byDigest := strings.HasPrefix(referencedBy, "sha256:")
if byID && numNames > 1 {
return errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names())
} else if byDigest && numNames > 1 {
// FIXME - Docker will remove the digest but containers storage
// does not support that yet, so our hands are tied.
return errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names())
if !options.Force {
if byID && numNames > 1 {
return errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names())
} else if byDigest && numNames > 1 {
// FIXME - Docker will remove the digest but containers storage
// does not support that yet, so our hands are tied.
return errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names())
}
}

// Only try to untag if we know it's not an ID or digest.
Expand Down
2 changes: 1 addition & 1 deletion libimage/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestLoad(t *testing.T) {
}

// Now remove the image.
rmReports, rmErrors := runtime.RemoveImages(ctx, loadedImages, &RemoveImagesOptions{Force: true})
rmReports, rmErrors := runtime.RemoveImages(ctx, ids, &RemoveImagesOptions{Force: true})
require.Len(t, rmErrors, 0)
require.Len(t, rmReports, test.numImages)

Expand Down
44 changes: 44 additions & 0 deletions libimage/remove_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package libimage

import (
"context"
"os"
"testing"

"github.com/containers/common/pkg/config"
"github.com/stretchr/testify/require"
)

func TestRemoveImages(t *testing.T) {
// Note: this will resolve pull from the GCR registry (see
// testdata/registries.conf).
busyboxLatest := "docker.io/library/busybox:latest"

runtime, cleanup := testNewRuntime(t)
defer cleanup()
ctx := context.Background()

pullOptions := &PullOptions{}
pullOptions.Writer = os.Stdout
pulledImages, err := runtime.Pull(ctx, busyboxLatest, config.PullPolicyAlways, pullOptions)
require.NoError(t, err)
require.Len(t, pulledImages, 1)

err = pulledImages[0].Tag("foobar")
require.NoError(t, err)

// containers/podman/issues/10685 - force removal on image with
// multiple tags will only untag but not remove all tags including the
// image.
rmReports, rmErrors := runtime.RemoveImages(ctx, []string{"foobar"}, &RemoveImagesOptions{Force: true})
require.Nil(t, rmErrors)
require.Len(t, rmReports, 1)
require.Equal(t, pulledImages[0].ID(), rmReports[0].ID)
require.False(t, rmReports[0].Removed)
require.Equal(t, []string{"localhost/foobar:latest"}, rmReports[0].Untagged)

// The busybox image is still present even if foobar was force removed.
exists, err := runtime.Exists(busyboxLatest)
require.NoError(t, err)
require.True(t, exists)
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ github.com/containerd/cgroups/stats/v1
github.com/containerd/containerd/errdefs
github.com/containerd/containerd/log
github.com/containerd/containerd/platforms
# github.com/containers/image/v5 v5.13.1
# github.com/containers/image/v5 v5.13.2-0.20210617132750-db0df5e0cf5e
## explicit
github.com/containers/image/v5/copy
github.com/containers/image/v5/directory
Expand Down

0 comments on commit c6578d7

Please sign in to comment.