diff --git a/libimage/image.go b/libimage/image.go index f5b7fb918..cc77fc34e 100644 --- a/libimage/image.go +++ b/libimage/image.go @@ -587,6 +587,9 @@ func (i *Image) Tag(name string) error { return i.reload() } +// to have some symmetry with the errors from containers/storage. +var errTagUnknown = errors.New("tag not known") + // TODO (@vrothberg) - `docker rmi sha256:` will remove the digest from the // image. However, that's something containers storage does not support. var errUntagDigest = errors.New("untag by digest not supported") @@ -601,7 +604,7 @@ func (i *Image) Untag(name string) error { ref, err := NormalizeName(name) if err != nil { - return fmt.Errorf("normalizing name %q: %w", name, err) + return err } // FIXME: this is breaking Podman CI but must be re-enabled once @@ -616,6 +619,19 @@ func (i *Image) Untag(name string) error { name = ref.String() + foundName := false + for _, n := range i.Names() { + if n == name { + foundName = true + break + } + } + // Return an error if the name is not found, the c/storage + // RemoveNames() API does not create one if no match is found. + if !foundName { + return fmt.Errorf("%s: %w", name, errTagUnknown) + } + logrus.Debugf("Untagging %q from image %s", ref.String(), i.ID()) if i.runtime.eventChannel != nil { defer i.runtime.writeEvent(&Event{ID: i.ID(), Name: name, Time: time.Now(), Type: EventTypeImageUntag}) diff --git a/libimage/image_test.go b/libimage/image_test.go index 6edc59ecf..f12a546ad 100644 --- a/libimage/image_test.go +++ b/libimage/image_test.go @@ -361,15 +361,16 @@ func TestUntag(t *testing.T) { for _, test := range []struct { tag string untag string - expectError bool + expectError string }{ - {"foo", "foo", false}, - {"foo", "foo:latest", false}, - {"foo", "localhost/foo", false}, - {"foo", "localhost/foo:latest", false}, - {"quay.io/image/foo", "quay.io/image/foo", false}, - {"foo", "doNotExist", true}, - {"foo", digest, true}, + {"foo", "foo", ""}, + {"foo", "foo:latest", ""}, + {"foo", "localhost/foo", ""}, + {"foo", "localhost/foo:latest", ""}, + {"quay.io/image/foo", "quay.io/image/foo", ""}, + {"foo", "upperCase", "normalizing name \"upperCase\": repository name must be lowercase"}, + {"foo", "donotexist", "localhost/donotexist:latest: tag not known"}, + {"foo", digest, digest + ": untag by digest not supported"}, // {"foo", "foo@" + digest, false}, // {"foo", "localhost/foo@" + digest, false}, } { @@ -377,8 +378,8 @@ func TestUntag(t *testing.T) { require.NoError(t, err, "tag should have succeeded: %v", test) err = image.Untag(test.untag) - if test.expectError { - require.Error(t, err, "untag should have failed: %v", test) + if test.expectError != "" { + require.EqualError(t, err, test.expectError, "untag should have failed: %v", test) continue } require.NoError(t, err, "untag should have succeedded: %v", test) @@ -388,7 +389,7 @@ func TestUntag(t *testing.T) { // Check for specific error. err := image.Untag(digest) - require.True(t, errors.Is(err, errUntagDigest), "check for specific digest error") + require.ErrorIs(t, err, errUntagDigest, "check for specific digest error") } func getImageAndRuntime(t *testing.T) (*Runtime, *Image, func()) {