From 9f72e8442d4d13d3aa5e8027d9ac4e42329bbd70 Mon Sep 17 00:00:00 2001 From: Richard Scothern Date: Tue, 26 Jan 2016 14:20:23 -0800 Subject: [PATCH] Add manifest put by digest to the registry client Signed-off-by: Richard Scothern --- manifests.go | 2 +- registry/client/repository.go | 21 +++++++++++++++++---- registry/client/repository_test.go | 21 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/manifests.go b/manifests.go index 1acb0500..40c5622f 100644 --- a/manifests.go +++ b/manifests.go @@ -81,7 +81,7 @@ type UnmarshalFunc func([]byte) (Manifest, Descriptor, error) var mappings = make(map[string]UnmarshalFunc, 0) -// UnmarshalManifest looks up manifest unmarshall functions based on +// UnmarshalManifest looks up manifest unmarshal functions based on // MediaType func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) { // Need to look up by the actual media type, not the raw contents of diff --git a/registry/client/repository.go b/registry/client/repository.go index 1f777add..5da2239f 100644 --- a/registry/client/repository.go +++ b/registry/client/repository.go @@ -427,9 +427,10 @@ func (o withTagOption) Apply(m distribution.ManifestService) error { } // Put puts a manifest. A tag can be specified using an options parameter which uses some shared state to hold the -// tag name in order to build the correct upload URL. This state is written and read under a lock. +// tag name in order to build the correct upload URL. func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) { ref := ms.name + var tagged bool for _, option := range options { if opt, ok := option.(withTagOption); ok { @@ -438,6 +439,7 @@ func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options . if err != nil { return "", err } + tagged = true } else { err := option.Apply(ms) if err != nil { @@ -445,13 +447,24 @@ func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options . } } } - - manifestURL, err := ms.ub.BuildManifestURL(ref) + mediaType, p, err := m.Payload() if err != nil { return "", err } - mediaType, p, err := m.Payload() + if !tagged { + // generate a canonical digest and Put by digest + _, d, err := distribution.UnmarshalManifest(mediaType, p) + if err != nil { + return "", err + } + ref, err = reference.WithDigest(ref, d.Digest) + if err != nil { + return "", err + } + } + + manifestURL, err := ms.ub.BuildManifestURL(ref) if err != nil { return "", err } diff --git a/registry/client/repository_test.go b/registry/client/repository_test.go index b7b782c7..df26b631 100644 --- a/registry/client/repository_test.go +++ b/registry/client/repository_test.go @@ -815,6 +815,7 @@ func TestManifestPut(t *testing.T) { if err != nil { t.Fatal(err) } + var m testutil.RequestResponseMap m = append(m, testutil.RequestResponseMapping{ Request: testutil.Request{ @@ -831,6 +832,22 @@ func TestManifestPut(t *testing.T) { }, }) + putDgst := digest.FromBytes(m1.Canonical) + m = append(m, testutil.RequestResponseMapping{ + Request: testutil.Request{ + Method: "PUT", + Route: "/v2/" + repo.Name() + "/manifests/" + putDgst.String(), + Body: payload, + }, + Response: testutil.Response{ + StatusCode: http.StatusAccepted, + Headers: http.Header(map[string][]string{ + "Content-Length": {"0"}, + "Docker-Content-Digest": {putDgst.String()}, + }), + }, + }) + e, c := testServer(m) defer c() @@ -848,6 +865,10 @@ func TestManifestPut(t *testing.T) { t.Fatal(err) } + if _, err := ms.Put(ctx, m1); err != nil { + t.Fatal(err) + } + // TODO(dmcgowan): Check for invalid input error }