Browse Source

Merge pull request #46009 from vvoland/c8d-resolve-fix-digested-and-named

c8d/resolveImage: Fix Digested and Named reference
Sebastiaan van Stijn 1 year ago
parent
commit
f061f39145
2 changed files with 53 additions and 0 deletions
  1. 18 0
      daemon/containerd/image.go
  2. 35 0
      integration/image/remove_test.go

+ 18 - 0
daemon/containerd/image.go

@@ -261,6 +261,24 @@ func (i *ImageService) resolveImage(ctx context.Context, refOrID string) (contai
 			return containerdimages.Image{}, images.ErrImageDoesNotExist{Ref: parsed}
 			return containerdimages.Image{}, images.ErrImageDoesNotExist{Ref: parsed}
 		}
 		}
 
 
+		// If reference is both Named and Digested, make sure we don't match
+		// images with a different repository even if digest matches.
+		// For example, busybox@sha256:abcdef..., shouldn't match asdf@sha256:abcdef...
+		if parsedNamed, ok := parsed.(reference.Named); ok {
+			for _, img := range imgs {
+				imgNamed, err := reference.ParseNormalizedNamed(img.Name)
+				if err != nil {
+					log.G(ctx).WithError(err).WithField("image", img.Name).Warn("image with invalid name encountered")
+					continue
+				}
+
+				if parsedNamed.Name() == imgNamed.Name() {
+					return img, nil
+				}
+			}
+			return containerdimages.Image{}, images.ErrImageDoesNotExist{Ref: parsed}
+		}
+
 		return imgs[0], nil
 		return imgs[0], nil
 	}
 	}
 
 

+ 35 - 0
integration/image/remove_test.go

@@ -6,9 +6,11 @@ import (
 	"testing"
 	"testing"
 
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/integration/internal/container"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 	is "gotest.tools/v3/assert/cmp"
+	"gotest.tools/v3/skip"
 )
 )
 
 
 func TestRemoveImageOrphaning(t *testing.T) {
 func TestRemoveImageOrphaning(t *testing.T) {
@@ -57,3 +59,36 @@ func TestRemoveImageOrphaning(t *testing.T) {
 	_, _, err = client.ImageInspectWithRaw(ctx, commitResp2.ID)
 	_, _, err = client.ImageInspectWithRaw(ctx, commitResp2.ID)
 	assert.Check(t, is.ErrorContains(err, "No such image:"))
 	assert.Check(t, is.ErrorContains(err, "No such image:"))
 }
 }
+
+func TestRemoveByDigest(t *testing.T) {
+	skip.If(t, !testEnv.UsingSnapshotter(), "RepoDigests doesn't include tags when using graphdrivers")
+
+	defer setupTest(t)()
+	ctx := context.Background()
+	client := testEnv.APIClient()
+
+	err := client.ImageTag(ctx, "busybox", "test-remove-by-digest:latest")
+	assert.NilError(t, err)
+
+	inspect, _, err := client.ImageInspectWithRaw(ctx, "test-remove-by-digest")
+	assert.NilError(t, err)
+
+	id := ""
+	for _, ref := range inspect.RepoDigests {
+		if strings.Contains(ref, "test-remove-by-digest") {
+			id = ref
+			break
+		}
+	}
+	assert.Assert(t, id != "")
+
+	t.Logf("removing %s", id)
+	_, err = client.ImageRemove(ctx, id, types.ImageRemoveOptions{})
+	assert.NilError(t, err)
+
+	inspect, _, err = client.ImageInspectWithRaw(ctx, "busybox")
+	assert.Check(t, err, "busybox image got deleted")
+
+	inspect, _, err = client.ImageInspectWithRaw(ctx, "test-remove-by-digest")
+	assert.Check(t, is.ErrorType(err, errdefs.IsNotFound))
+}