From aaaa48dbb15d7a99f8e7a7cb29f1a1eaf760effa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Fri, 8 Jul 2022 15:12:35 +0200 Subject: [PATCH] containerd: Implement push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Gronowski --- daemon/containerd/service.go | 55 +++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/daemon/containerd/service.go b/daemon/containerd/service.go index 31f8c6f2c5efa..b0657b6eaac5c 100644 --- a/daemon/containerd/service.go +++ b/daemon/containerd/service.go @@ -12,6 +12,7 @@ import ( cerrdefs "github.com/containerd/containerd/errdefs" containerdimages "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/archive" + "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" @@ -373,7 +374,59 @@ func (cs *containerdStore) LookupImage(ctx context.Context, name string) (*types } func (cs *containerdStore) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error { - panic("not implemented") + // TODO: Pass this from user? + platformMatcher := platforms.DefaultStrict() + + ref, err := reference.ParseNormalizedNamed(image) + if err != nil { + return err + } + if tag != "" { + // Push by digest is not supported, so only tags are supported. + ref, err = reference.WithTag(ref, tag) + if err != nil { + return err + } + } + + is := cs.client.ImageService() + + img, err := is.Get(ctx, ref.String()) + if err != nil { + return errors.Wrap(err, "Failed to get image") + } + + target := img.Target + + // Create a temporary image which is stripped from content that references other platforms. + // We or the remote may not have them and referencing them will end with an error. + if platformMatcher != platforms.All { + tmpRef := ref.String() + "-tmp-platformspecific" + platformImg, err := converter.Convert(ctx, cs.client, tmpRef, ref.String(), converter.WithPlatform(platformMatcher)) + if err != nil { + return errors.Wrap(err, "Failed to convert image to platform specific") + } + + target = platformImg.Target + defer cs.client.ImageService().Delete(ctx, platformImg.Name, containerdimages.SynchronousDelete()) + } + + imageHandler := containerdimages.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) { + logrus.WithField("desc", desc).Debug("Pushing") + return nil, nil + }) + imageHandler = remotes.SkipNonDistributableBlobs(imageHandler) + + resolver := newResolverFromAuthConfig(authConfig) + + logrus.WithField("desc", target).WithField("ref", ref.String()).Info("Pushing desc to remote ref") + err = cs.client.Push(ctx, ref.String(), target, + containerd.WithResolver(resolver), + containerd.WithPlatformMatcher(platformMatcher), + containerd.WithImageHandler(imageHandler), + ) + + return err } func (cs *containerdStore) SearchRegistryForImages(ctx context.Context, searchFilters filters.Args, term string, limit int, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registrytypes.SearchResults, error) {