diff --git a/internal/cri/server/images/image_pull.go b/internal/cri/server/images/image_pull.go index 488136b43..3dd100d99 100644 --- a/internal/cri/server/images/image_pull.go +++ b/internal/cri/server/images/image_pull.go @@ -37,7 +37,6 @@ import ( "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/log" distribution "github.com/distribution/reference" - imagedigest "github.com/opencontainers/go-digest" imagespec "github.com/opencontainers/image-spec/specs-go/v1" runtime "k8s.io/cri-api/pkg/apis/runtime/v1" @@ -49,6 +48,7 @@ import ( "github.com/containerd/containerd/v2/internal/cri/annotations" criconfig "github.com/containerd/containerd/v2/internal/cri/config" crilabels "github.com/containerd/containerd/v2/internal/cri/labels" + "github.com/containerd/containerd/v2/internal/cri/util" snpkg "github.com/containerd/containerd/v2/pkg/snapshotters" "github.com/containerd/containerd/v2/pkg/tracing" ) @@ -220,7 +220,7 @@ func (c *CRIImageService) PullImage(ctx context.Context, name string, credential } imageID := configDesc.Digest.String() - repoDigest, repoTag := getRepoDigestAndTag(namedRef, image.Target().Digest, isSchema1) + repoDigest, repoTag := util.GetRepoDigestAndTag(namedRef, image.Target().Digest, isSchema1) for _, r := range []string{imageID, repoTag, repoDigest} { if r == "" { continue @@ -252,21 +252,6 @@ func (c *CRIImageService) PullImage(ctx context.Context, name string, credential return imageID, nil } -// getRepoDigestAngTag returns image repoDigest and repoTag of the named image reference. -func getRepoDigestAndTag(namedRef distribution.Named, digest imagedigest.Digest, schema1 bool) (string, string) { - var repoTag, repoDigest string - if _, ok := namedRef.(distribution.NamedTagged); ok { - repoTag = namedRef.String() - } - if _, ok := namedRef.(distribution.Canonical); ok { - repoDigest = namedRef.String() - } else if !schema1 { - // digest is not actual repo digest for schema1 image. - repoDigest = namedRef.Name() + "@" + digest.String() - } - return repoDigest, repoTag -} - // ParseAuth parses AuthConfig and returns username and password/secret required by containerd. func ParseAuth(auth *runtime.AuthConfig, host string) (string, string, error) { if auth == nil { diff --git a/internal/cri/server/images/image_pull_test.go b/internal/cri/server/images/image_pull_test.go index e981c7e30..bc79e35f0 100644 --- a/internal/cri/server/images/image_pull_test.go +++ b/internal/cri/server/images/image_pull_test.go @@ -21,8 +21,6 @@ import ( "encoding/base64" "testing" - docker "github.com/distribution/reference" - "github.com/opencontainers/go-digest" "github.com/stretchr/testify/assert" runtime "k8s.io/cri-api/pkg/apis/runtime/v1" @@ -440,52 +438,6 @@ func TestSnapshotterFromPodSandboxConfig(t *testing.T) { } } -func TestGetRepoDigestAndTag(t *testing.T) { - digest := digest.Digest("sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582") - for _, test := range []struct { - desc string - ref string - schema1 bool - expectedRepoDigest string - expectedRepoTag string - }{ - { - desc: "repo tag should be empty if original ref has no tag", - ref: "gcr.io/library/busybox@" + digest.String(), - expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(), - }, - { - desc: "repo tag should not be empty if original ref has tag", - ref: "gcr.io/library/busybox:latest", - expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(), - expectedRepoTag: "gcr.io/library/busybox:latest", - }, - { - desc: "repo digest should be empty if original ref is schema1 and has no digest", - ref: "gcr.io/library/busybox:latest", - schema1: true, - expectedRepoDigest: "", - expectedRepoTag: "gcr.io/library/busybox:latest", - }, - { - desc: "repo digest should not be empty if original ref is schema1 but has digest", - ref: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", - schema1: true, - expectedRepoDigest: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", - expectedRepoTag: "", - }, - } { - test := test - t.Run(test.desc, func(t *testing.T) { - named, err := docker.ParseDockerRef(test.ref) - assert.NoError(t, err) - repoDigest, repoTag := getRepoDigestAndTag(named, digest, test.schema1) - assert.Equal(t, test.expectedRepoDigest, repoDigest) - assert.Equal(t, test.expectedRepoTag, repoTag) - }) - } -} - func TestImageGetLabels(t *testing.T) { criService, _ := newTestCRIService() diff --git a/internal/cri/server/podsandbox/helpers.go b/internal/cri/server/podsandbox/helpers.go index 29c6accce..071be4782 100644 --- a/internal/cri/server/podsandbox/helpers.go +++ b/internal/cri/server/podsandbox/helpers.go @@ -24,8 +24,6 @@ import ( "github.com/containerd/log" "github.com/containerd/typeurl/v2" - docker "github.com/distribution/reference" - imagedigest "github.com/opencontainers/go-digest" runtimespec "github.com/opencontainers/runtime-spec/specs-go" containerd "github.com/containerd/containerd/v2/client" @@ -65,21 +63,6 @@ func (c *Controller) getVolatileSandboxRootDir(id string) string { return filepath.Join(c.config.StateDir, sandboxesDir, id) } -// getRepoDigestAngTag returns image repoDigest and repoTag of the named image reference. -func getRepoDigestAndTag(namedRef docker.Named, digest imagedigest.Digest, schema1 bool) (string, string) { - var repoTag, repoDigest string - if _, ok := namedRef.(docker.NamedTagged); ok { - repoTag = namedRef.String() - } - if _, ok := namedRef.(docker.Canonical); ok { - repoDigest = namedRef.String() - } else if !schema1 { - // digest is not actual repo digest for schema1 image. - repoDigest = namedRef.Name() + "@" + digest.String() - } - return repoDigest, repoTag -} - // toContainerdImage converts an image object in image store to containerd image handler. func (c *Controller) toContainerdImage(ctx context.Context, image imagestore.Image) (containerd.Image, error) { // image should always have at least one reference. diff --git a/internal/cri/server/podsandbox/helpers_test.go b/internal/cri/server/podsandbox/helpers_test.go index f78754503..f2cab5962 100644 --- a/internal/cri/server/podsandbox/helpers_test.go +++ b/internal/cri/server/podsandbox/helpers_test.go @@ -24,58 +24,10 @@ import ( crilabels "github.com/containerd/containerd/v2/internal/cri/labels" "github.com/containerd/containerd/v2/pkg/oci" - docker "github.com/distribution/reference" - imagedigest "github.com/opencontainers/go-digest" runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" ) -func TestGetRepoDigestAndTag(t *testing.T) { - digest := imagedigest.Digest("sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582") - for _, test := range []struct { - desc string - ref string - schema1 bool - expectedRepoDigest string - expectedRepoTag string - }{ - { - desc: "repo tag should be empty if original ref has no tag", - ref: "gcr.io/library/busybox@" + digest.String(), - expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(), - }, - { - desc: "repo tag should not be empty if original ref has tag", - ref: "gcr.io/library/busybox:latest", - expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(), - expectedRepoTag: "gcr.io/library/busybox:latest", - }, - { - desc: "repo digest should be empty if original ref is schema1 and has no digest", - ref: "gcr.io/library/busybox:latest", - schema1: true, - expectedRepoDigest: "", - expectedRepoTag: "gcr.io/library/busybox:latest", - }, - { - desc: "repo digest should not be empty if original ref is schema1 but has digest", - ref: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", - schema1: true, - expectedRepoDigest: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", - expectedRepoTag: "", - }, - } { - test := test - t.Run(test.desc, func(t *testing.T) { - named, err := docker.ParseDockerRef(test.ref) - assert.NoError(t, err) - repoDigest, repoTag := getRepoDigestAndTag(named, digest, test.schema1) - assert.Equal(t, test.expectedRepoDigest, repoDigest) - assert.Equal(t, test.expectedRepoTag, repoTag) - }) - } -} - func TestBuildLabels(t *testing.T) { imageConfigLabels := map[string]string{ "a": "z", diff --git a/internal/cri/util/references.go b/internal/cri/util/references.go index 4813f89e1..6c9791bfa 100644 --- a/internal/cri/util/references.go +++ b/internal/cri/util/references.go @@ -16,7 +16,10 @@ package util -import reference "github.com/distribution/reference" +import ( + reference "github.com/distribution/reference" + imagedigest "github.com/opencontainers/go-digest" +) // ParseImageReferences parses a list of arbitrary image references and returns // the repotags and repodigests @@ -35,3 +38,18 @@ func ParseImageReferences(refs []string) ([]string, []string) { } return tags, digests } + +// GetRepoDigestAndTag returns image repoDigest and repoTag of the named image reference. +func GetRepoDigestAndTag(namedRef reference.Named, digest imagedigest.Digest, schema1 bool) (string, string) { + var repoTag, repoDigest string + if _, ok := namedRef.(reference.NamedTagged); ok { + repoTag = namedRef.String() + } + if _, ok := namedRef.(reference.Canonical); ok { + repoDigest = namedRef.String() + } else if !schema1 { + // digest is not actual repo digest for schema1 image. + repoDigest = namedRef.Name() + "@" + digest.String() + } + return repoDigest, repoTag +} diff --git a/internal/cri/util/references_test.go b/internal/cri/util/references_test.go index 0f12bee13..eaea819a2 100644 --- a/internal/cri/util/references_test.go +++ b/internal/cri/util/references_test.go @@ -20,6 +20,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/distribution/reference" + "github.com/opencontainers/go-digest" ) func TestParseImageReferences(t *testing.T) { @@ -37,3 +40,49 @@ func TestParseImageReferences(t *testing.T) { assert.Equal(t, expectedTags, tags) assert.Equal(t, expectedDigests, digests) } + +func TestGetRepoDigestAndTag(t *testing.T) { + digest := digest.Digest("sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582") + for _, test := range []struct { + desc string + ref string + schema1 bool + expectedRepoDigest string + expectedRepoTag string + }{ + { + desc: "repo tag should be empty if original ref has no tag", + ref: "gcr.io/library/busybox@" + digest.String(), + expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(), + }, + { + desc: "repo tag should not be empty if original ref has tag", + ref: "gcr.io/library/busybox:latest", + expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(), + expectedRepoTag: "gcr.io/library/busybox:latest", + }, + { + desc: "repo digest should be empty if original ref is schema1 and has no digest", + ref: "gcr.io/library/busybox:latest", + schema1: true, + expectedRepoDigest: "", + expectedRepoTag: "gcr.io/library/busybox:latest", + }, + { + desc: "repo digest should not be empty if original ref is schema1 but has digest", + ref: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", + schema1: true, + expectedRepoDigest: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594", + expectedRepoTag: "", + }, + } { + test := test + t.Run(test.desc, func(t *testing.T) { + named, err := reference.ParseDockerRef(test.ref) + assert.NoError(t, err) + repoDigest, repoTag := GetRepoDigestAndTag(named, digest, test.schema1) + assert.Equal(t, test.expectedRepoDigest, repoDigest) + assert.Equal(t, test.expectedRepoTag, repoTag) + }) + } +}