implement Repository Blobs upload resuming
Signed-off-by: Damien Mathieu <dmathieu@salesforce.com>master
							parent
							
								
									90dfea7952
								
							
						
					
					
						commit
						dd3bdee21c
					
				| 
						 | 
					@ -799,7 +799,18 @@ func (bs *blobs) Create(ctx context.Context, options ...distribution.BlobCreateO
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (bs *blobs) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) {
 | 
					func (bs *blobs) Resume(ctx context.Context, id string) (distribution.BlobWriter, error) {
 | 
				
			||||||
	panic("not implemented")
 | 
						location, err := bs.ub.BuildBlobUploadChunkURL(bs.name, id)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &httpBlobUpload{
 | 
				
			||||||
 | 
							statter:   bs.statter,
 | 
				
			||||||
 | 
							client:    bs.client,
 | 
				
			||||||
 | 
							uuid:      id,
 | 
				
			||||||
 | 
							startedAt: time.Now(),
 | 
				
			||||||
 | 
							location:  location,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (bs *blobs) Delete(ctx context.Context, dgst digest.Digest) error {
 | 
					func (bs *blobs) Delete(ctx context.Context, dgst digest.Digest) error {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ import (
 | 
				
			||||||
	"github.com/docker/distribution/manifest/schema1"
 | 
						"github.com/docker/distribution/manifest/schema1"
 | 
				
			||||||
	"github.com/docker/distribution/reference"
 | 
						"github.com/docker/distribution/reference"
 | 
				
			||||||
	"github.com/docker/distribution/registry/api/errcode"
 | 
						"github.com/docker/distribution/registry/api/errcode"
 | 
				
			||||||
	"github.com/docker/distribution/registry/api/v2"
 | 
						v2 "github.com/docker/distribution/registry/api/v2"
 | 
				
			||||||
	"github.com/docker/distribution/testutil"
 | 
						"github.com/docker/distribution/testutil"
 | 
				
			||||||
	"github.com/docker/distribution/uuid"
 | 
						"github.com/docker/distribution/uuid"
 | 
				
			||||||
	"github.com/docker/libtrust"
 | 
						"github.com/docker/libtrust"
 | 
				
			||||||
| 
						 | 
					@ -200,6 +200,95 @@ func TestBlobServeBlobHEAD(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestBlobResume(t *testing.T) {
 | 
				
			||||||
 | 
						dgst, b1 := newRandomBlob(1024)
 | 
				
			||||||
 | 
						id := uuid.Generate().String()
 | 
				
			||||||
 | 
						var m testutil.RequestResponseMap
 | 
				
			||||||
 | 
						repo, _ := reference.WithName("test.example.com/repo1")
 | 
				
			||||||
 | 
						m = append(m, testutil.RequestResponseMapping{
 | 
				
			||||||
 | 
							Request: testutil.Request{
 | 
				
			||||||
 | 
								Method: "PATCH",
 | 
				
			||||||
 | 
								Route:  "/v2/" + repo.Name() + "/blobs/uploads/" + id,
 | 
				
			||||||
 | 
								Body:   b1,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Response: testutil.Response{
 | 
				
			||||||
 | 
								StatusCode: http.StatusAccepted,
 | 
				
			||||||
 | 
								Headers: http.Header(map[string][]string{
 | 
				
			||||||
 | 
									"Docker-Content-Digest": {dgst.String()},
 | 
				
			||||||
 | 
									"Range":                 {fmt.Sprintf("0-%d", len(b1)-1)},
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						m = append(m, testutil.RequestResponseMapping{
 | 
				
			||||||
 | 
							Request: testutil.Request{
 | 
				
			||||||
 | 
								Method: "PUT",
 | 
				
			||||||
 | 
								Route:  "/v2/" + repo.Name() + "/blobs/uploads/" + id,
 | 
				
			||||||
 | 
								QueryParams: map[string][]string{
 | 
				
			||||||
 | 
									"digest": {dgst.String()},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Response: testutil.Response{
 | 
				
			||||||
 | 
								StatusCode: http.StatusCreated,
 | 
				
			||||||
 | 
								Headers: http.Header(map[string][]string{
 | 
				
			||||||
 | 
									"Docker-Content-Digest": {dgst.String()},
 | 
				
			||||||
 | 
									"Content-Range":         {fmt.Sprintf("0-%d", len(b1)-1)},
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						m = append(m, testutil.RequestResponseMapping{
 | 
				
			||||||
 | 
							Request: testutil.Request{
 | 
				
			||||||
 | 
								Method: "HEAD",
 | 
				
			||||||
 | 
								Route:  "/v2/" + repo.Name() + "/blobs/" + dgst.String(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Response: testutil.Response{
 | 
				
			||||||
 | 
								StatusCode: http.StatusOK,
 | 
				
			||||||
 | 
								Headers: http.Header(map[string][]string{
 | 
				
			||||||
 | 
									"Content-Length": {fmt.Sprint(len(b1))},
 | 
				
			||||||
 | 
									"Last-Modified":  {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e, c := testServer(m)
 | 
				
			||||||
 | 
						defer c()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx := context.Background()
 | 
				
			||||||
 | 
						r, err := NewRepository(repo, e, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l := r.Blobs(ctx)
 | 
				
			||||||
 | 
						upload, err := l.Resume(ctx, id)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Error resuming blob: %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if upload.ID() != id {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected UUID %s; expected %s", upload.ID(), id)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						n, err := upload.ReadFrom(bytes.NewReader(b1))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if n != int64(len(b1)) {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected ReadFrom length: %d; expected: %d", n, len(b1))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						blob, err := upload.Commit(ctx, distribution.Descriptor{
 | 
				
			||||||
 | 
							Digest: dgst,
 | 
				
			||||||
 | 
							Size:   int64(len(b1)),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if blob.Size != int64(len(b1)) {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected blob size: %d; expected: %d", blob.Size, len(b1))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestBlobDelete(t *testing.T) {
 | 
					func TestBlobDelete(t *testing.T) {
 | 
				
			||||||
	dgst, _ := newRandomBlob(1024)
 | 
						dgst, _ := newRandomBlob(1024)
 | 
				
			||||||
	var m testutil.RequestResponseMap
 | 
						var m testutil.RequestResponseMap
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue