Pull: create image record after blobs download
When pull image with unpack option, the fetch action will defer blobs download until unpack. If create image record in ImageService before blobs download, the following requests to use image will fail because there is still missing blobs download. In order to fix concurrent issue, need to create image record after blobs download. Fix: #3937 Signed-off-by: Wei Fu <fuweid89@gmail.com>
This commit is contained in:
parent
592a617f3d
commit
75af17946d
@ -390,7 +390,11 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
return c.fetch(ctx, fetchCtx, ref, 0)
|
||||
img, err := c.fetch(ctx, fetchCtx, ref, 0)
|
||||
if err != nil {
|
||||
return images.Image{}, err
|
||||
}
|
||||
return c.createNewImage(ctx, img)
|
||||
}
|
||||
|
||||
// Push uploads the provided content to a remote resource
|
||||
|
30
pull.go
30
pull.go
@ -27,6 +27,7 @@ import (
|
||||
"github.com/containerd/containerd/remotes/docker/schema1"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
@ -62,15 +63,18 @@ 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
|
||||
|
||||
if pullCtx.Unpack {
|
||||
// unpacker only supports schema 2 image, for schema 1 this is noop.
|
||||
u, err := c.newUnpacker(ctx, pullCtx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create unpacker")
|
||||
}
|
||||
unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks)
|
||||
unpackWrapper, unpackEg = u.handlerWrapper(ctx, &unpacks)
|
||||
defer func() {
|
||||
if err := eg.Wait(); err != nil {
|
||||
if err := unpackEg.Wait(); err != nil {
|
||||
if retErr == nil {
|
||||
retErr = errors.Wrap(err, "unpack")
|
||||
}
|
||||
@ -90,6 +94,22 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img, err = c.createNewImage(ctx, img)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
|
||||
|
||||
if pullCtx.Unpack {
|
||||
@ -201,12 +221,14 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
|
||||
}
|
||||
}
|
||||
|
||||
img := images.Image{
|
||||
return images.Image{
|
||||
Name: name,
|
||||
Target: desc,
|
||||
Labels: rCtx.Labels,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) createNewImage(ctx context.Context, img images.Image) (images.Image, error) {
|
||||
is := c.ImageService()
|
||||
for {
|
||||
if created, err := is.Create(ctx, img); err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user