Add manifest put by digest to the registry client

Signed-off-by: Richard Scothern <richard.scothern@gmail.com>
This commit is contained in:
Richard Scothern 2016-01-26 14:20:23 -08:00
parent 69db5b7440
commit 9f72e8442d
3 changed files with 39 additions and 5 deletions

View file

@ -81,7 +81,7 @@ type UnmarshalFunc func([]byte) (Manifest, Descriptor, error)
var mappings = make(map[string]UnmarshalFunc, 0) var mappings = make(map[string]UnmarshalFunc, 0)
// UnmarshalManifest looks up manifest unmarshall functions based on // UnmarshalManifest looks up manifest unmarshal functions based on
// MediaType // MediaType
func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) { func UnmarshalManifest(ctHeader string, p []byte) (Manifest, Descriptor, error) {
// Need to look up by the actual media type, not the raw contents of // Need to look up by the actual media type, not the raw contents of

View file

@ -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 // 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) { func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) {
ref := ms.name ref := ms.name
var tagged bool
for _, option := range options { for _, option := range options {
if opt, ok := option.(withTagOption); ok { if opt, ok := option.(withTagOption); ok {
@ -438,6 +439,7 @@ func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options .
if err != nil { if err != nil {
return "", err return "", err
} }
tagged = true
} else { } else {
err := option.Apply(ms) err := option.Apply(ms)
if err != nil { if err != nil {
@ -445,13 +447,24 @@ func (ms *manifests) Put(ctx context.Context, m distribution.Manifest, options .
} }
} }
} }
mediaType, p, err := m.Payload()
manifestURL, err := ms.ub.BuildManifestURL(ref)
if err != nil { if err != nil {
return "", err 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 { if err != nil {
return "", err return "", err
} }

View file

@ -815,6 +815,7 @@ func TestManifestPut(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
var m testutil.RequestResponseMap var m testutil.RequestResponseMap
m = append(m, testutil.RequestResponseMapping{ m = append(m, testutil.RequestResponseMapping{
Request: testutil.Request{ 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) e, c := testServer(m)
defer c() defer c()
@ -848,6 +865,10 @@ func TestManifestPut(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if _, err := ms.Put(ctx, m1); err != nil {
t.Fatal(err)
}
// TODO(dmcgowan): Check for invalid input error // TODO(dmcgowan): Check for invalid input error
} }