From 4c1fa571940d82366bb7efd181c4683e6cb936ad Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Fri, 26 Mar 2021 18:04:31 -0700 Subject: [PATCH] remotes/docker: Only return "already exists" on push when the upload was successful The `(dockerPusher).Push` method uses a `StatusTracker` to check if an upload already happened, before repeating the upload. However, there is no provision for failure handling. If a PUT request returns an error, the `StatusTracker` will still see the upload as if it happened successfully. Add a status boolean so that only successful uploads short-circuit `Push`. Signed-off-by: Aaron Lehmann --- remotes/docker/pusher.go | 8 +++++--- remotes/docker/status.go | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/remotes/docker/pusher.go b/remotes/docker/pusher.go index 0da62f4f7..334e8bbaa 100644 --- a/remotes/docker/pusher.go +++ b/remotes/docker/pusher.go @@ -52,7 +52,7 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten ref := remotes.MakeRefKey(ctx, desc) status, err := p.tracker.GetStatus(ref) if err == nil { - if status.Offset == status.Total { + if status.Committed && status.Offset == status.Total { return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "ref %v", ref) } // TODO: Handle incomplete status @@ -341,8 +341,6 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di if err := pw.pipe.Close(); err != nil { return err } - // TODO: Update status to determine committing - // TODO: timeout waiting for response resp := <-pw.responseC if resp.err != nil { @@ -379,6 +377,10 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di return errors.Errorf("got digest %s, expected %s", actual, expected) } + status.Committed = true + status.UpdatedAt = time.Now() + pw.tracker.SetStatus(pw.ref, status) + return nil } diff --git a/remotes/docker/status.go b/remotes/docker/status.go index 8069d6767..cee9199f2 100644 --- a/remotes/docker/status.go +++ b/remotes/docker/status.go @@ -28,6 +28,8 @@ import ( type Status struct { content.Status + Committed bool + // UploadUUID is used by the Docker registry to reference blob uploads UploadUUID string }