forked from TrueCloudLab/distribution
address get manifest issue with oci. namespace; and comment descriptions
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
This commit is contained in:
parent
fcaffa38bc
commit
426afb3a4c
3 changed files with 9 additions and 183 deletions
|
@ -61,7 +61,7 @@ func (m Manifest) References() []distribution.Descriptor {
|
|||
return references
|
||||
}
|
||||
|
||||
// Target returns the target of this signed manifest.
|
||||
// Target returns the target of this manifest.
|
||||
func (m Manifest) Target() distribution.Descriptor {
|
||||
return m.Config
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ func (m Manifest) References() []distribution.Descriptor {
|
|||
return references
|
||||
}
|
||||
|
||||
// Target returns the target of this signed manifest.
|
||||
// Target returns the target of this manifest.
|
||||
func (m Manifest) Target() distribution.Descriptor {
|
||||
return m.Config
|
||||
}
|
||||
|
|
|
@ -111,13 +111,11 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
supportsOCI := supportsOCISchema || supportsOCIImageIndex
|
||||
|
||||
var manifest distribution.Manifest
|
||||
if imh.Tag != "" {
|
||||
tags := imh.Repository.Tags(imh)
|
||||
var desc distribution.Descriptor
|
||||
if !supportsOCI {
|
||||
desc, err = tags.Get(imh, imh.Tag)
|
||||
} else {
|
||||
desc, err = tags.Get(imh, imh.annotatedTag(supportsOCI))
|
||||
if err != nil && supportsOCI { // in the supportsOCI case fall back to the non OCI image
|
||||
desc, err = tags.Get(imh, imh.annotatedTag(false))
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -140,7 +138,12 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
|
|||
if imh.Tag != "" {
|
||||
options = append(options, distribution.WithTag(imh.annotatedTag(supportsOCI)))
|
||||
}
|
||||
var manifest distribution.Manifest
|
||||
manifest, err = manifests.Get(imh, imh.Digest, options...)
|
||||
if err != nil && supportsOCI && imh.Tag != "" { // in the supportsOCI case fall back to the non OCI image
|
||||
options = append(options[:0], distribution.WithTag(imh.annotatedTag(false)))
|
||||
manifest, err = manifests.Get(imh, imh.Digest, options...)
|
||||
}
|
||||
if err != nil {
|
||||
if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
|
||||
|
@ -238,183 +241,6 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
|
|||
w.Write(p)
|
||||
}
|
||||
|
||||
// GetImageManifest fetches the image manifest from the storage backend, if it exists.
|
||||
func (imh *manifestHandler) GetImageManifest(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Printf("\n\nGetting a manifest!\n\n\n")
|
||||
supportsSchema2 := false
|
||||
supportsManifestList := false
|
||||
supportsOCISchema := false
|
||||
supportsOCIImageIndex := false
|
||||
|
||||
// this parsing of Accept headers is not quite as full-featured as godoc.org's parser, but we don't care about "q=" values
|
||||
// https://github.com/golang/gddo/blob/e91d4165076d7474d20abda83f92d15c7ebc3e81/httputil/header/header.go#L165-L202
|
||||
for _, acceptHeader := range r.Header["Accept"] {
|
||||
// r.Header[...] is a slice in case the request contains the same header more than once
|
||||
// if the header isn't set, we'll get the zero value, which "range" will handle gracefully
|
||||
|
||||
// we need to split each header value on "," to get the full list of "Accept" values (per RFC 2616)
|
||||
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
||||
for _, mediaType := range strings.Split(acceptHeader, ",") {
|
||||
// remove "; q=..." if present
|
||||
if i := strings.Index(mediaType, ";"); i >= 0 {
|
||||
mediaType = mediaType[:i]
|
||||
}
|
||||
|
||||
// it's common (but not required) for Accept values to be space separated ("a/b, c/d, e/f")
|
||||
mediaType = strings.TrimSpace(mediaType)
|
||||
|
||||
if mediaType == schema2.MediaTypeManifest {
|
||||
supportsSchema2 = true
|
||||
}
|
||||
if mediaType == manifestlist.MediaTypeManifestList {
|
||||
supportsManifestList = true
|
||||
}
|
||||
if mediaType == v1.MediaTypeImageManifest {
|
||||
supportsOCISchema = true
|
||||
}
|
||||
if mediaType == v1.MediaTypeImageIndex {
|
||||
supportsOCIImageIndex = true
|
||||
}
|
||||
}
|
||||
}
|
||||
supportsOCI := supportsOCISchema || supportsOCIImageIndex
|
||||
|
||||
ctxu.GetLogger(imh).Debug("GetImageManifest")
|
||||
manifests, err := imh.Repository.Manifests(imh)
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, err)
|
||||
return
|
||||
}
|
||||
|
||||
var manifest distribution.Manifest
|
||||
if imh.Tag != "" {
|
||||
tags := imh.Repository.Tags(imh)
|
||||
var desc distribution.Descriptor
|
||||
if !supportsOCI {
|
||||
desc, err = tags.Get(imh, imh.Tag)
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
desc, err = tags.Get(imh, imh.annotatedTag(supportsOCI))
|
||||
if err != nil {
|
||||
desc, err = tags.Get(imh, imh.annotatedTag(false))
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
imh.Digest = desc.Digest
|
||||
}
|
||||
|
||||
if etagMatch(r, imh.Digest.String()) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
var options []distribution.ManifestServiceOption
|
||||
if imh.Tag != "" {
|
||||
options = append(options, distribution.WithTag(imh.annotatedTag(supportsOCI)))
|
||||
}
|
||||
manifest, err = manifests.Get(imh, imh.Digest, options...)
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
|
||||
return
|
||||
}
|
||||
|
||||
schema2Manifest, isSchema2 := manifest.(*schema2.DeserializedManifest)
|
||||
manifestList, isManifestList := manifest.(*manifestlist.DeserializedManifestList)
|
||||
isAnOCIManifest := isSchema2 && (schema2Manifest.MediaType == v1.MediaTypeImageManifest)
|
||||
isAnOCIImageIndex := isManifestList && (manifestList.MediaType == v1.MediaTypeImageIndex)
|
||||
|
||||
badCombinations := [][]bool{
|
||||
{isSchema2 && !isAnOCIManifest, supportsOCISchema && !supportsSchema2},
|
||||
{isManifestList && !isAnOCIImageIndex, supportsOCIImageIndex && !supportsManifestList},
|
||||
{isAnOCIManifest, !supportsOCISchema && supportsSchema2},
|
||||
{isAnOCIImageIndex, !supportsOCIImageIndex && supportsManifestList},
|
||||
}
|
||||
for i, combo := range badCombinations {
|
||||
if combo[0] && combo[1] {
|
||||
fmt.Printf("\n\nbad combo! %d\n\n\n", i)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
if isAnOCIManifest {
|
||||
fmt.Print("\n\nreturning OCI manifest\n\n")
|
||||
} else if isSchema2 {
|
||||
fmt.Print("\n\nreturning schema 2 manifest\n\n")
|
||||
} else {
|
||||
fmt.Print("\n\nreturning schema 1 manifest\n\n")
|
||||
}
|
||||
|
||||
// Only rewrite schema2 manifests when they are being fetched by tag.
|
||||
// If they are being fetched by digest, we can't return something not
|
||||
// matching the digest.
|
||||
if imh.Tag != "" && isSchema2 && !(supportsSchema2 || supportsOCISchema) {
|
||||
// Rewrite manifest in schema1 format
|
||||
dcontext.GetLogger(imh).Infof("rewriting manifest %s in schema1 format to support old client", imh.Digest.String())
|
||||
|
||||
manifest, err = imh.convertSchema2Manifest(schema2Manifest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else if imh.Tag != "" && isManifestList && !(supportsManifestList || supportsOCIImageIndex) {
|
||||
// Rewrite manifest in schema1 format
|
||||
dcontext.GetLogger(imh).Infof("rewriting manifest list %s in schema1 format to support old client", imh.Digest.String())
|
||||
|
||||
// Find the image manifest corresponding to the default
|
||||
// platform
|
||||
var manifestDigest digest.Digest
|
||||
for _, manifestDescriptor := range manifestList.Manifests {
|
||||
if manifestDescriptor.Platform.Architecture == defaultArch && manifestDescriptor.Platform.OS == defaultOS {
|
||||
manifestDigest = manifestDescriptor.Digest
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if manifestDigest == "" {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown)
|
||||
return
|
||||
}
|
||||
|
||||
manifest, err = manifests.Get(imh, manifestDigest)
|
||||
if err != nil {
|
||||
if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
|
||||
} else {
|
||||
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If necessary, convert the image manifest
|
||||
if schema2Manifest, isSchema2 := manifest.(*schema2.DeserializedManifest); isSchema2 && !supportsSchema2 {
|
||||
manifest, err = imh.convertSchema2Manifest(schema2Manifest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
imh.Digest = manifestDigest
|
||||
}
|
||||
}
|
||||
|
||||
ct, p, err := manifest.Payload()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", ct)
|
||||
w.Header().Set("Content-Length", fmt.Sprint(len(p)))
|
||||
w.Header().Set("Docker-Content-Digest", imh.Digest.String())
|
||||
w.Header().Set("Etag", fmt.Sprintf(`"%s"`, imh.Digest))
|
||||
w.Write(p)
|
||||
|
||||
fmt.Printf("\n\nSucceeded in getting the manifest!\n\n\n")
|
||||
}
|
||||
|
||||
func (imh *manifestHandler) convertSchema2Manifest(schema2Manifest *schema2.DeserializedManifest) (distribution.Manifest, error) {
|
||||
targetDescriptor := schema2Manifest.Target()
|
||||
blobs := imh.Repository.Blobs(imh)
|
||||
|
|
Loading…
Reference in a new issue