From 82daf624980482f61596214c50adaeddd9a13568 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 18 Sep 2024 12:11:16 -0700 Subject: [PATCH] Ensure all layers are here when tagging Signed-off-by: apostasie --- pkg/cmd/image/tag.go | 7 +++++++ pkg/imgutil/imgutil.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 48929d3694e..6a0b24700f7 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) @@ -64,6 +65,12 @@ func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagO return err } image.Name = target.String() + + err = imgutil.EnsureAllContent(ctx, client, srcName, "", options.GOptions) + if err != nil { + return err + } + if _, err = imageService.Create(ctx, image); err != nil { if errdefs.IsAlreadyExists(err) { if err = imageService.Delete(ctx, image.Name); err != nil { diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 3b042c9fb63..3cab4475cd5 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -44,6 +44,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" + "github.com/containerd/nerdctl/v2/pkg/platformutil" ) // EnsuredImage contains the image existed in containerd and its metadata. @@ -102,6 +103,44 @@ func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotte return res, nil } +func EnsureAllContent(ctx context.Context, client *containerd.Client, rawRef string, platform string, options types.GlobalCommandOptions) error { + named, err := distributionref.ParseDockerRef(rawRef) + if err != nil { + return err + } + refDomain := distributionref.Domain(named) + + // Get a resolver + var dOpts []dockerconfigresolver.Opt + if options.InsecureRegistry { + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) + dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) + } + dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.HostsDir)) + resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) + if err != nil { + return err + } + + var platformComparer platforms.MatchComparer + if platform != "" { + parsed, err := platforms.Parse(platform) + if err != nil { + return err + } + platformComparer = platformutil.NewMatchComparerFromOCISpecPlatformSlice([]ocispec.Platform{parsed}) + } else { + platforms.Default() + } + + opts := []containerd.RemoteOpt{ + containerd.WithResolver(resolver), + containerd.WithPlatformMatcher(platformComparer), + } + _, err = client.Fetch(ctx, rawRef, opts...) + return err +} + // EnsureImage ensures the image. // // # When insecure is set, skips verifying certs, and also falls back to HTTP when the registry does not speak HTTPS