Merge pull request #1775 from dmcgowan/get-content-digest
Add option to get content digest from manifest get
This commit is contained in:
commit
4e08e7d1d6
2 changed files with 45 additions and 7 deletions
|
@ -394,11 +394,26 @@ func (o etagOption) Apply(ms distribution.ManifestService) error {
|
|||
return fmt.Errorf("etag options is a client-only option")
|
||||
}
|
||||
|
||||
// ReturnContentDigest allows a client to set a the content digest on
|
||||
// a successful request from the 'Docker-Content-Digest' header. This
|
||||
// returned digest is represents the digest which the registry uses
|
||||
// to refer to the content and can be used to delete the content.
|
||||
func ReturnContentDigest(dgst *digest.Digest) distribution.ManifestServiceOption {
|
||||
return contentDigestOption{dgst}
|
||||
}
|
||||
|
||||
type contentDigestOption struct{ digest *digest.Digest }
|
||||
|
||||
func (o contentDigestOption) Apply(ms distribution.ManifestService) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) {
|
||||
var (
|
||||
digestOrTag string
|
||||
ref reference.Named
|
||||
err error
|
||||
contentDgst *digest.Digest
|
||||
)
|
||||
|
||||
for _, option := range options {
|
||||
|
@ -408,6 +423,8 @@ func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...dis
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if opt, ok := option.(contentDigestOption); ok {
|
||||
contentDgst = opt.digest
|
||||
} else {
|
||||
err := option.Apply(ms)
|
||||
if err != nil {
|
||||
|
@ -450,6 +467,12 @@ func (ms *manifests) Get(ctx context.Context, dgst digest.Digest, options ...dis
|
|||
if resp.StatusCode == http.StatusNotModified {
|
||||
return nil, distribution.ErrManifestNotModified
|
||||
} else if SuccessStatus(resp.StatusCode) {
|
||||
if contentDgst != nil {
|
||||
dgst, err := digest.ParseDigest(resp.Header.Get("Docker-Content-Digest"))
|
||||
if err == nil {
|
||||
*contentDgst = dgst
|
||||
}
|
||||
}
|
||||
mt := resp.Header.Get("Content-Type")
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
|
|
|
@ -605,6 +605,14 @@ func addTestManifestWithEtag(repo reference.Named, reference string, content []b
|
|||
*m = append(*m, testutil.RequestResponseMapping{Request: getReqWithEtag, Response: getRespWithEtag})
|
||||
}
|
||||
|
||||
func contentDigestString(mediatype string, content []byte) string {
|
||||
if mediatype == schema1.MediaTypeSignedManifest {
|
||||
m, _, _ := distribution.UnmarshalManifest(mediatype, content)
|
||||
content = m.(*schema1.SignedManifest).Canonical
|
||||
}
|
||||
return digest.Canonical.FromBytes(content).String()
|
||||
}
|
||||
|
||||
func addTestManifest(repo reference.Named, reference string, mediatype string, content []byte, m *testutil.RequestResponseMap) {
|
||||
*m = append(*m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
|
@ -615,9 +623,10 @@ func addTestManifest(repo reference.Named, reference string, mediatype string, c
|
|||
StatusCode: http.StatusOK,
|
||||
Body: content,
|
||||
Headers: http.Header(map[string][]string{
|
||||
"Content-Length": {fmt.Sprint(len(content))},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {mediatype},
|
||||
"Content-Length": {fmt.Sprint(len(content))},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {mediatype},
|
||||
"Docker-Content-Digest": {contentDigestString(mediatype, content)},
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
@ -629,9 +638,10 @@ func addTestManifest(repo reference.Named, reference string, mediatype string, c
|
|||
Response: testutil.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Headers: http.Header(map[string][]string{
|
||||
"Content-Length": {fmt.Sprint(len(content))},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {mediatype},
|
||||
"Content-Length": {fmt.Sprint(len(content))},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {mediatype},
|
||||
"Docker-Content-Digest": {digest.Canonical.FromBytes(content).String()},
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
@ -710,7 +720,8 @@ func TestV1ManifestFetch(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
manifest, err = ms.Get(ctx, dgst, distribution.WithTag("latest"))
|
||||
var contentDigest digest.Digest
|
||||
manifest, err = ms.Get(ctx, dgst, distribution.WithTag("latest"), ReturnContentDigest(&contentDigest))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -723,6 +734,10 @@ func TestV1ManifestFetch(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if contentDigest != dgst {
|
||||
t.Fatalf("Unexpected returned content digest %v, expected %v", contentDigest, dgst)
|
||||
}
|
||||
|
||||
manifest, err = ms.Get(ctx, dgst, distribution.WithTag("badcontenttype"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
Loading…
Reference in a new issue