c8d: Make sure the content isn't removed while we export
This change add leases for all the content that will be exported, once the image(s) are exported the lease is removed, thus letting containerd's GC to do its job if needed. This fixes the case where someone would remove an image that is still being exported. This fixes the TestAPIImagesSaveAndLoad cli integration test. Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
This commit is contained in:
parent
ee79423124
commit
f3a6b0fd08
1 changed files with 38 additions and 2 deletions
|
@ -6,9 +6,11 @@ import (
|
|||
"io"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/content"
|
||||
cerrdefs "github.com/containerd/containerd/errdefs"
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/mount"
|
||||
cplatforms "github.com/containerd/containerd/platforms"
|
||||
|
@ -58,11 +60,17 @@ func (i *ImageService) ExportImage(ctx context.Context, names []string, outStrea
|
|||
archive.WithPlatform(platform),
|
||||
}
|
||||
|
||||
ctx, release, err := i.client.WithLease(ctx)
|
||||
contentStore := i.client.ContentStore()
|
||||
leasesManager := i.client.LeasesService()
|
||||
lease, err := leasesManager.Create(ctx, leases.WithRandomID())
|
||||
if err != nil {
|
||||
return errdefs.System(err)
|
||||
}
|
||||
defer release(ctx)
|
||||
defer func() {
|
||||
if err := leasesManager.Delete(ctx, lease); err != nil {
|
||||
log.G(ctx).WithError(err).Warn("cleaning up lease")
|
||||
}
|
||||
}()
|
||||
|
||||
for _, name := range names {
|
||||
target, err := i.resolveDescriptor(ctx, name)
|
||||
|
@ -70,6 +78,10 @@ func (i *ImageService) ExportImage(ctx context.Context, names []string, outStrea
|
|||
return err
|
||||
}
|
||||
|
||||
if err = leaseContent(ctx, contentStore, leasesManager, lease, target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We may not have locally all the platforms that are specified in the index.
|
||||
// Export only those manifests that we have.
|
||||
// TODO(vvoland): Reconsider this when `--platform` is added.
|
||||
|
@ -101,6 +113,30 @@ func (i *ImageService) ExportImage(ctx context.Context, names []string, outStrea
|
|||
return i.client.Export(ctx, outStream, opts...)
|
||||
}
|
||||
|
||||
// leaseContent will add a resource to the lease for each child of the descriptor making sure that it and
|
||||
// its children won't be deleted while the lease exists
|
||||
func leaseContent(ctx context.Context, store content.Store, leasesManager leases.Manager, lease leases.Lease, desc ocispec.Descriptor) error {
|
||||
return containerdimages.Walk(ctx, containerdimages.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
_, err := store.Info(ctx, desc.Digest)
|
||||
if err != nil {
|
||||
if errors.Is(err, cerrdefs.ErrNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errdefs.System(err)
|
||||
}
|
||||
|
||||
r := leases.Resource{
|
||||
ID: desc.Digest.String(),
|
||||
Type: "content",
|
||||
}
|
||||
if err := leasesManager.AddResource(ctx, lease, r); err != nil {
|
||||
return nil, errdefs.System(err)
|
||||
}
|
||||
|
||||
return containerdimages.Children(ctx, store, desc)
|
||||
}), desc)
|
||||
}
|
||||
|
||||
// LoadImage uploads a set of images into the repository. This is the
|
||||
// complement of ExportImage. The input stream is an uncompressed tar
|
||||
// ball containing images and metadata.
|
||||
|
|
Loading…
Reference in a new issue