Add unpack interface to be used by client

Move client unpacker to pkg/unpack

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan
2022-03-25 18:08:34 -07:00
parent 030c1ac1ca
commit 8017daa12d
2 changed files with 245 additions and 142 deletions

70
pull.go
View File

@@ -23,12 +23,12 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/pkg/unpack"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/containerd/containerd/remotes/docker/schema1"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
)
@@ -63,19 +63,46 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
}
defer done(ctx)
var unpacks int32
var unpackEg *errgroup.Group
var unpackWrapper func(f images.Handler) images.Handler
var unpacker *unpack.Unpacker
if pullCtx.Unpack {
// unpacker only supports schema 2 image, for schema 1 this is noop.
u, err := c.newUnpacker(ctx, pullCtx)
snapshotterName, err := c.resolveSnapshotterName(ctx, pullCtx.Snapshotter)
if err != nil {
return nil, fmt.Errorf("create unpacker: %w", err)
return nil, fmt.Errorf("unable to resolve snapshotter: %w", err)
}
var uconfig UnpackConfig
for _, opt := range pullCtx.UnpackOpts {
if err := opt(ctx, &uconfig); err != nil {
return nil, err
}
}
var platformMatcher platforms.Matcher
if !uconfig.CheckPlatformSupported {
platformMatcher = platforms.All
}
// Check client Unpack config
platform := unpack.Platform{
Platform: platformMatcher,
SnapshotterKey: snapshotterName,
Snapshotter: c.SnapshotService(snapshotterName),
SnapshotOpts: append(pullCtx.SnapshotterOpts, uconfig.SnapshotOpts...),
Applier: c.DiffService(),
ApplyOpts: uconfig.ApplyOpts,
}
uopts := []unpack.UnpackerOpt{unpack.WithUnpackPlatform(platform)}
if pullCtx.MaxConcurrentUploadedLayers > 0 {
uopts = append(uopts, unpack.WithLimiter(semaphore.NewWeighted(int64(pullCtx.MaxConcurrentDownloads))))
}
if uconfig.DuplicationSuppressor != nil {
uopts = append(uopts, unpack.WithDuplicationSuppressor(uconfig.DuplicationSuppressor))
}
unpacker, err = unpack.NewUnpacker(ctx, c.ContentStore(), uopts...)
if err != nil {
return nil, fmt.Errorf("unable to initialize unpacker: %w", err)
}
unpackWrapper, unpackEg = u.handlerWrapper(ctx, pullCtx, &unpacks)
defer func() {
if err := unpackEg.Wait(); err != nil {
if _, err := unpacker.Wait(); err != nil {
if retErr == nil {
retErr = fmt.Errorf("unpack: %w", err)
}
@@ -84,9 +111,9 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
wrapper := pullCtx.HandlerWrapper
pullCtx.HandlerWrapper = func(h images.Handler) images.Handler {
if wrapper == nil {
return unpackWrapper(h)
return unpacker.Unpack(h)
}
return unpackWrapper(wrapper(h))
return unpacker.Unpack(wrapper(h))
}
}
@@ -98,11 +125,10 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
// NOTE(fuweid): unpacker defers blobs download. before create image
// record in ImageService, should wait for unpacking(including blobs
// download).
if pullCtx.Unpack {
if unpackEg != nil {
if err := unpackEg.Wait(); err != nil {
return nil, err
}
var ur unpack.Result
if unpacker != nil {
if ur, err = unpacker.Wait(); err != nil {
return nil, err
}
}
@@ -113,13 +139,11 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
if pullCtx.Unpack {
if unpacks == 0 {
// Try to unpack is none is done previously.
// This is at least required for schema 1 image.
if err := i.Unpack(ctx, pullCtx.Snapshotter, pullCtx.UnpackOpts...); err != nil {
return nil, fmt.Errorf("failed to unpack image on snapshotter %s: %w", pullCtx.Snapshotter, err)
}
if unpacker != nil && ur.Unpacks == 0 {
// Unpack was tried previously but nothing was unpacked
// This is at least required for schema 1 image.
if err := i.Unpack(ctx, pullCtx.Snapshotter, pullCtx.UnpackOpts...); err != nil {
return nil, fmt.Errorf("failed to unpack image on snapshotter %s: %w", pullCtx.Snapshotter, err)
}
}