imagetools: copy manifests between repositories

Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
Justin Chadwell 2022-05-18 11:52:28 +01:00
parent d3412f1039
commit 37ca8631f9
2 changed files with 33 additions and 4 deletions

View File

@ -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
}

View File

@ -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 {