Abort newly created references on error
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
parent
69e7e7fa4f
commit
64a96aab8a
@ -90,6 +90,7 @@ type IngestManager interface {
|
|||||||
// Writer handles the write of content into a content store
|
// Writer handles the write of content into a content store
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
// Close is expected to be called after Commit() when commission is needed.
|
// Close is expected to be called after Commit() when commission is needed.
|
||||||
|
// Closing a writer without commit allows resuming or aborting.
|
||||||
io.WriteCloser
|
io.WriteCloser
|
||||||
|
|
||||||
// Digest may return empty digest or panics until committed.
|
// Digest may return empty digest or panics until committed.
|
||||||
|
@ -130,10 +130,10 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest,
|
|||||||
// tact.
|
// tact.
|
||||||
//
|
//
|
||||||
// If one needs to resume the transaction, a new writer can be obtained from
|
// If one needs to resume the transaction, a new writer can be obtained from
|
||||||
// `ContentStore.Resume` using the same key. The write can then be continued
|
// `Ingester.Writer` using the same key. The write can then be continued
|
||||||
// from it was left off.
|
// from it was left off.
|
||||||
//
|
//
|
||||||
// To abandon a transaction completely, first call close then `Store.Remove` to
|
// To abandon a transaction completely, first call close then `IngestManager.Abort` to
|
||||||
// clean up the associated resources.
|
// clean up the associated resources.
|
||||||
func (w *writer) Close() (err error) {
|
func (w *writer) Close() (err error) {
|
||||||
if w.fp != nil {
|
if w.fp != nil {
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/containerd/containerd/diff"
|
"github.com/containerd/containerd/diff"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/metadata"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
@ -127,7 +128,7 @@ func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts
|
|||||||
|
|
||||||
// DiffMounts creates a diff between the given mounts and uploads the result
|
// DiffMounts creates a diff between the given mounts and uploads the result
|
||||||
// to the content store.
|
// to the content store.
|
||||||
func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) {
|
func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) {
|
||||||
var config diff.Config
|
var config diff.Config
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
if err := opt(&config); err != nil {
|
if err := opt(&config); err != nil {
|
||||||
@ -169,7 +170,9 @@ func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount
|
|||||||
}
|
}
|
||||||
defer mount.Unmount(bDir, 0)
|
defer mount.Unmount(bDir, 0)
|
||||||
|
|
||||||
|
var newReference bool
|
||||||
if config.Reference == "" {
|
if config.Reference == "" {
|
||||||
|
newReference = true
|
||||||
config.Reference = uniqueRef()
|
config.Reference = uniqueRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,18 +180,31 @@ func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return emptyDesc, errors.Wrap(err, "failed to open writer")
|
return emptyDesc, errors.Wrap(err, "failed to open writer")
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
cw.Close()
|
||||||
|
if newReference {
|
||||||
|
if err := s.store.Abort(ctx, config.Reference); err != nil {
|
||||||
|
log.G(ctx).WithField("ref", config.Reference).Warnf("failed to delete diff upload")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if !newReference {
|
||||||
|
if err := cw.Truncate(0); err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if isCompressed {
|
if isCompressed {
|
||||||
dgstr := digest.SHA256.Digester()
|
dgstr := digest.SHA256.Digester()
|
||||||
compressed, err := compression.CompressStream(cw, compression.Gzip)
|
compressed, err := compression.CompressStream(cw, compression.Gzip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cw.Close()
|
|
||||||
return emptyDesc, errors.Wrap(err, "failed to get compressed stream")
|
return emptyDesc, errors.Wrap(err, "failed to get compressed stream")
|
||||||
}
|
}
|
||||||
err = archive.WriteDiff(ctx, io.MultiWriter(compressed, dgstr.Hash()), aDir, bDir)
|
err = archive.WriteDiff(ctx, io.MultiWriter(compressed, dgstr.Hash()), aDir, bDir)
|
||||||
compressed.Close()
|
compressed.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cw.Close()
|
|
||||||
return emptyDesc, errors.Wrap(err, "failed to write compressed diff")
|
return emptyDesc, errors.Wrap(err, "failed to write compressed diff")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +214,6 @@ func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount
|
|||||||
config.Labels["containerd.io/uncompressed"] = dgstr.Digest().String()
|
config.Labels["containerd.io/uncompressed"] = dgstr.Digest().String()
|
||||||
} else {
|
} else {
|
||||||
if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil {
|
if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil {
|
||||||
cw.Close()
|
|
||||||
return emptyDesc, errors.Wrap(err, "failed to write diff")
|
return emptyDesc, errors.Wrap(err, "failed to write diff")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user