address get manifest issue with oci. namespace; and comment descriptions
Signed-off-by: Mike Brown <brownwm@us.ibm.com>master
							parent
							
								
									fcaffa38bc
								
							
						
					
					
						commit
						426afb3a4c
					
				|  | @ -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 New Issue