Merge pull request #3755 from wy65701436/fix-getstatus

pull/3764/head
Milos Gajdos 2022-10-28 08:20:15 +01:00 committed by GitHub
commit 7f9f86c411
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 16 deletions

View File

@ -687,6 +687,17 @@ func testBlobAPI(t *testing.T, env *testEnv, args blobArgs) *testEnv {
layerFile.Seek(0, 0) layerFile.Seek(0, 0)
uploadURLBase, _ = startPushLayer(t, env, imageName) uploadURLBase, _ = startPushLayer(t, env, imageName)
uploadURLBase, dgst := pushChunk(t, env.builder, imageName, uploadURLBase, layerFile, layerLength) uploadURLBase, dgst := pushChunk(t, env.builder, imageName, uploadURLBase, layerFile, layerLength)
// -----------------------------------------
// Check the chunk upload status
_, end, err := getUploadStatus(uploadURLBase)
if err != nil {
t.Fatalf("unexpected error doing chunk upload check: %v", err)
}
if end+1 != layerLength {
t.Fatalf("getting wrong chunk upload status: %d", end)
}
finishUpload(t, env.builder, imageName, uploadURLBase, dgst) finishUpload(t, env.builder, imageName, uploadURLBase, dgst)
// ----------------------------------------- // -----------------------------------------
@ -2487,6 +2498,27 @@ func pushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst diges
return resp.Header.Get("Location") return resp.Header.Get("Location")
} }
func getUploadStatus(location string) (string, int64, error) {
req, err := http.NewRequest(http.MethodGet, location, nil)
if err != nil {
return location, -1, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return location, -1, err
}
defer resp.Body.Close()
_, end, err := parseContentRange(resp.Header.Get("Range"))
if err != nil {
return location, -1, err
}
return resp.Header.Get("Location"), end, nil
}
func finishUpload(t *testing.T, ub *v2.URLBuilder, name reference.Named, uploadURLBase string, dgst digest.Digest) string { func finishUpload(t *testing.T, ub *v2.URLBuilder, name reference.Named, uploadURLBase string, dgst digest.Digest) string {
resp, err := doPushLayer(t, ub, name, dgst, uploadURLBase, nil) resp, err := doPushLayer(t, ub, name, dgst, uploadURLBase, nil)
if err != nil { if err != nil {

View File

@ -37,6 +37,9 @@ func blobUploadDispatcher(ctx *Context, r *http.Request) http.Handler {
} }
if buh.UUID != "" { if buh.UUID != "" {
if r.Method == http.MethodGet || r.Method == http.MethodHead {
return handler
}
if h := buh.ResumeBlobUpload(ctx, r); h != nil { if h := buh.ResumeBlobUpload(ctx, r); h != nil {
return h return h
} }
@ -92,7 +95,7 @@ func (buh *blobUploadHandler) StartBlobUpload(w http.ResponseWriter, r *http.Req
buh.Upload = upload buh.Upload = upload
if err := buh.blobUploadResponse(w, r, true); err != nil { if err := buh.blobUploadResponse(w, r); err != nil {
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
return return
} }
@ -104,19 +107,25 @@ func (buh *blobUploadHandler) StartBlobUpload(w http.ResponseWriter, r *http.Req
// GetUploadStatus returns the status of a given upload, identified by id. // GetUploadStatus returns the status of a given upload, identified by id.
func (buh *blobUploadHandler) GetUploadStatus(w http.ResponseWriter, r *http.Request) { func (buh *blobUploadHandler) GetUploadStatus(w http.ResponseWriter, r *http.Request) {
if buh.Upload == nil { if buh.Upload == nil {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown) blobs := buh.Repository.Blobs(buh)
return upload, err := blobs.Resume(buh, buh.UUID)
if err != nil {
if err == distribution.ErrBlobUploadUnknown {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown.WithDetail(err))
} else {
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
}
return
}
buh.Upload = upload
} }
// TODO(dmcgowan): Set last argument to false in blobUploadResponse when if err := buh.blobUploadResponse(w, r); err != nil {
// resumable upload is supported. This will enable returning a non-zero
// range for clients to begin uploading at an offset.
if err := buh.blobUploadResponse(w, r, true); err != nil {
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
return return
} }
w.Header().Set("Docker-Upload-UUID", buh.UUID)
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
@ -163,7 +172,7 @@ func (buh *blobUploadHandler) PatchBlobData(w http.ResponseWriter, r *http.Reque
return return
} }
if err := buh.blobUploadResponse(w, r, false); err != nil { if err := buh.blobUploadResponse(w, r); err != nil {
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
return return
} }
@ -181,6 +190,7 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown) buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown)
return return
} }
defer buh.Upload.Close()
dgstStr := r.FormValue("digest") // TODO(stevvooe): Support multiple digest parameters! dgstStr := r.FormValue("digest") // TODO(stevvooe): Support multiple digest parameters!
@ -251,6 +261,7 @@ func (buh *blobUploadHandler) CancelBlobUpload(w http.ResponseWriter, r *http.Re
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown) buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadUnknown)
return return
} }
defer buh.Upload.Close()
w.Header().Set("Docker-Upload-UUID", buh.UUID) w.Header().Set("Docker-Upload-UUID", buh.UUID)
if err := buh.Upload.Cancel(buh); err != nil { if err := buh.Upload.Cancel(buh); err != nil {
@ -302,11 +313,9 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
buh.Upload = upload buh.Upload = upload
if size := upload.Size(); size != buh.State.Offset { if size := upload.Size(); size != buh.State.Offset {
defer upload.Close()
dcontext.GetLogger(ctx).Errorf("upload resumed at wrong offset: %d != %d", size, buh.State.Offset) dcontext.GetLogger(ctx).Errorf("upload resumed at wrong offset: %d != %d", size, buh.State.Offset)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUploadInvalid.WithDetail(err)) buh.Errors = append(buh.Errors, v2.ErrorCodeRangeInvalid.WithDetail(err))
upload.Cancel(buh)
}) })
} }
return nil return nil
@ -314,10 +323,8 @@ func (buh *blobUploadHandler) ResumeBlobUpload(ctx *Context, r *http.Request) ht
// blobUploadResponse provides a standard request for uploading blobs and // blobUploadResponse provides a standard request for uploading blobs and
// chunk responses. This sets the correct headers but the response status is // chunk responses. This sets the correct headers but the response status is
// left to the caller. The fresh argument is used to ensure that new blob // left to the caller.
// uploads always start at a 0 offset. This allows disabling resumable push by func (buh *blobUploadHandler) blobUploadResponse(w http.ResponseWriter, r *http.Request) error {
// always returning a 0 offset on check status.
func (buh *blobUploadHandler) blobUploadResponse(w http.ResponseWriter, r *http.Request, fresh bool) error {
// TODO(stevvooe): Need a better way to manage the upload state automatically. // TODO(stevvooe): Need a better way to manage the upload state automatically.
buh.State.Name = buh.Repository.Named().Name() buh.State.Name = buh.Repository.Named().Name()
buh.State.UUID = buh.Upload.ID() buh.State.UUID = buh.Upload.ID()