forked from TrueCloudLab/distribution
Adds cross-repository blob mounting behavior
Extends blob upload POST endpoint to support mount and from query parameters as described in #634 Signed-off-by: Brian Bland <brian.bland@docker.com>
This commit is contained in:
parent
c426367881
commit
41e30f626b
10 changed files with 416 additions and 10 deletions
|
@ -116,8 +116,16 @@ type blobUploadHandler struct {
|
|||
}
|
||||
|
||||
// StartBlobUpload begins the blob upload process and allocates a server-side
|
||||
// blob writer session.
|
||||
// blob writer session, optionally mounting the blob from a separate repository.
|
||||
func (buh *blobUploadHandler) StartBlobUpload(w http.ResponseWriter, r *http.Request) {
|
||||
fromRepo := r.FormValue("from")
|
||||
mountDigest := r.FormValue("mount")
|
||||
|
||||
if mountDigest != "" && fromRepo != "" {
|
||||
buh.mountBlob(w, fromRepo, mountDigest)
|
||||
return
|
||||
}
|
||||
|
||||
blobs := buh.Repository.Blobs(buh)
|
||||
upload, err := blobs.Create(buh)
|
||||
|
||||
|
@ -254,18 +262,10 @@ func (buh *blobUploadHandler) PutBlobUploadComplete(w http.ResponseWriter, r *ht
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// Build our canonical blob url
|
||||
blobURL, err := buh.urlBuilder.BuildBlobURL(buh.Repository.Name(), desc.Digest)
|
||||
if err != nil {
|
||||
if err := buh.writeBlobCreatedHeaders(w, desc); err != nil {
|
||||
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Location", blobURL)
|
||||
w.Header().Set("Content-Length", "0")
|
||||
w.Header().Set("Docker-Content-Digest", desc.Digest.String())
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
// CancelBlobUpload cancels an in-progress upload of a blob.
|
||||
|
@ -335,3 +335,45 @@ func (buh *blobUploadHandler) blobUploadResponse(w http.ResponseWriter, r *http.
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// mountBlob attempts to mount a blob from another repository by its digest. If
|
||||
// successful, the blob is linked into the blob store and 201 Created is
|
||||
// returned with the canonical url of the blob.
|
||||
func (buh *blobUploadHandler) mountBlob(w http.ResponseWriter, fromRepo, mountDigest string) {
|
||||
dgst, err := digest.ParseDigest(mountDigest)
|
||||
if err != nil {
|
||||
buh.Errors = append(buh.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err))
|
||||
return
|
||||
}
|
||||
|
||||
blobs := buh.Repository.Blobs(buh)
|
||||
desc, err := blobs.Mount(buh, fromRepo, dgst)
|
||||
if err != nil {
|
||||
if err == distribution.ErrBlobUnknown {
|
||||
buh.Errors = append(buh.Errors, v2.ErrorCodeBlobUnknown.WithDetail(dgst))
|
||||
} else {
|
||||
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := buh.writeBlobCreatedHeaders(w, desc); err != nil {
|
||||
buh.Errors = append(buh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// writeBlobCreatedHeaders writes the standard headers describing a newly
|
||||
// created blob. A 201 Created is written as well as the canonical URL and
|
||||
// blob digest.
|
||||
func (buh *blobUploadHandler) writeBlobCreatedHeaders(w http.ResponseWriter, desc distribution.Descriptor) error {
|
||||
blobURL, err := buh.urlBuilder.BuildBlobURL(buh.Repository.Name(), desc.Digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Header().Set("Location", blobURL)
|
||||
w.Header().Set("Content-Length", "0")
|
||||
w.Header().Set("Docker-Content-Digest", desc.Digest.String())
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue