From 37ca8631f94b29f78e3ad04d40dae3a333a77e85 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Wed, 18 May 2022 11:52:28 +0100 Subject: [PATCH] imagetools: copy manifests between repositories Signed-off-by: Justin Chadwell --- commands/imagetools/create.go | 9 +++++---- util/imagetools/create.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/commands/imagetools/create.go b/commands/imagetools/create.go index 7e9db288..7426cd04 100644 --- a/commands/imagetools/create.go +++ b/commands/imagetools/create.go @@ -78,9 +78,6 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error { if len(repos) == 0 { return errors.Errorf("no repositories specified, please set a reference in tag or source") } - if len(repos) > 1 { - return errors.Errorf("multiple repositories currently not supported, found %v", repos) - } var defaultRepo *string if len(repos) == 1 { @@ -92,7 +89,7 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error { for i, s := range srcs { if s.Ref == nil && s.Desc.MediaType == "" && s.Desc.Digest != "" { if defaultRepo == nil { - return errors.Errorf("multiple repositories specified, cannot determine default from %v", repos) + return errors.Errorf("multiple repositories specified, cannot infer repository for %q", args[i]) } n, err := reference.ParseNormalizedNamed(*defaultRepo) @@ -181,6 +178,10 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error { r = imagetools.New(imageopt) for _, t := range tags { + if err := r.Copy(ctx, srcs, t); err != nil { + return err + } + if err := r.Push(ctx, t, desc, dt); err != nil { return err } diff --git a/util/imagetools/create.go b/util/imagetools/create.go index 4b21e75c..2275636d 100644 --- a/util/imagetools/create.go +++ b/util/imagetools/create.go @@ -10,6 +10,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" "github.com/docker/distribution/reference" + "github.com/moby/buildkit/util/contentutil" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -169,6 +170,33 @@ func (r *Resolver) Push(ctx context.Context, ref reference.Named, desc ocispec.D return err } +func (r *Resolver) Copy(ctx context.Context, srcs []*Source, dest reference.Named) error { + dest = reference.TagNameOnly(dest) + p, err := r.resolver().Pusher(ctx, dest.String()) + if err != nil { + return err + } + + for _, src := range srcs { + if reference.Domain(src.Ref) == reference.Domain(dest) && reference.Path(src.Ref) == reference.Path(dest) { + continue + } + + srcRef := reference.TagNameOnly(src.Ref) + f, err := r.resolver().Fetcher(ctx, srcRef.String()) + if err != nil { + return err + } + + err = contentutil.CopyChain(ctx, contentutil.FromPusher(p), contentutil.FromFetcher(f), src.Desc) + if err != nil { + return err + } + } + + return nil +} + func (r *Resolver) loadPlatform(ctx context.Context, p2 *ocispec.Platform, in string, dt []byte) error { var manifest ocispec.Manifest if err := json.Unmarshal(dt, &manifest); err != nil {