Handle OCI manifests and image indexes without a media type
In the OCI image specification, the MediaType field is reserved and otherwise undefined; assume that manifests without a media in storage are OCI images or image indexes, and determine which by looking at what fields are in the JSON. We do keep a check that when unmarshalling an OCI image or image index, if it has a MediaType field, it must match that media type of the upload. Signed-off-by: Owen W. Taylor <otaylor@fishsoup.net>master
							parent
							
								
									1d47ef7b80
								
							
						
					
					
						commit
						60d9c5dfad
					
				|  | @ -60,8 +60,8 @@ func init() { | |||
| 			return nil, distribution.Descriptor{}, err | ||||
| 		} | ||||
| 
 | ||||
| 		if m.MediaType != v1.MediaTypeImageIndex { | ||||
| 			err = fmt.Errorf("mediaType in image index should be '%s' not '%s'", | ||||
| 		if m.MediaType != "" && m.MediaType != v1.MediaTypeImageIndex { | ||||
| 			err = fmt.Errorf("if present, mediaType in image index should be '%s' not '%s'", | ||||
| 				v1.MediaTypeImageIndex, m.MediaType) | ||||
| 
 | ||||
| 			return nil, distribution.Descriptor{}, err | ||||
|  | @ -205,5 +205,12 @@ func (m *DeserializedManifestList) MarshalJSON() ([]byte, error) { | |||
| // Payload returns the raw content of the manifest list. The contents can be
 | ||||
| // used to calculate the content identifier.
 | ||||
| func (m DeserializedManifestList) Payload() (string, []byte, error) { | ||||
| 	return m.MediaType, m.canonical, nil | ||||
| 	var mediaType string | ||||
| 	if m.MediaType == "" { | ||||
| 		mediaType = v1.MediaTypeImageIndex | ||||
| 	} else { | ||||
| 		mediaType = m.MediaType | ||||
| 	} | ||||
| 
 | ||||
| 	return mediaType, m.canonical, nil | ||||
| } | ||||
|  |  | |||
|  | @ -299,7 +299,7 @@ func TestMediaTypes(t *testing.T) { | |||
| 	mediaTypeTest(t, MediaTypeManifestList, "", true) | ||||
| 	mediaTypeTest(t, MediaTypeManifestList, MediaTypeManifestList, false) | ||||
| 	mediaTypeTest(t, MediaTypeManifestList, MediaTypeManifestList+"XXX", true) | ||||
| 	mediaTypeTest(t, v1.MediaTypeImageIndex, "", true) | ||||
| 	mediaTypeTest(t, v1.MediaTypeImageIndex, "", false) | ||||
| 	mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex, false) | ||||
| 	mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex+"XXX", true) | ||||
| } | ||||
|  |  | |||
|  | @ -97,8 +97,8 @@ func (m *DeserializedManifest) UnmarshalJSON(b []byte) error { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if manifest.MediaType != v1.MediaTypeImageManifest { | ||||
| 		return fmt.Errorf("mediaType in manifest should be '%s' not '%s'", | ||||
| 	if manifest.MediaType != "" && manifest.MediaType != v1.MediaTypeImageManifest { | ||||
| 		return fmt.Errorf("if present, mediaType in manifest should be '%s' not '%s'", | ||||
| 			v1.MediaTypeImageManifest, manifest.MediaType) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -120,5 +120,5 @@ func (m *DeserializedManifest) MarshalJSON() ([]byte, error) { | |||
| // Payload returns the raw content of the manifest. The contents can be used to
 | ||||
| // calculate the content identifier.
 | ||||
| func (m DeserializedManifest) Payload() (string, []byte, error) { | ||||
| 	return m.MediaType, m.canonical, nil | ||||
| 	return v1.MediaTypeImageManifest, m.canonical, nil | ||||
| } | ||||
|  |  | |||
|  | @ -178,7 +178,7 @@ func mediaTypeTest(t *testing.T, mediaType string, shouldError bool) { | |||
| } | ||||
| 
 | ||||
| func TestMediaTypes(t *testing.T) { | ||||
| 	mediaTypeTest(t, "", true) | ||||
| 	mediaTypeTest(t, "", false) | ||||
| 	mediaTypeTest(t, v1.MediaTypeImageManifest, false) | ||||
| 	mediaTypeTest(t, v1.MediaTypeImageManifest+"XXX", true) | ||||
| } | ||||
|  |  | |||
|  | @ -106,6 +106,18 @@ func (ms *manifestStore) Get(ctx context.Context, dgst digest.Digest, options .. | |||
| 			return ms.ocischemaHandler.Unmarshal(ctx, dgst, content) | ||||
| 		case manifestlist.MediaTypeManifestList, v1.MediaTypeImageIndex: | ||||
| 			return ms.manifestListHandler.Unmarshal(ctx, dgst, content) | ||||
| 		case "": | ||||
| 			// OCI image or image index - no media type in the content
 | ||||
| 
 | ||||
| 			// First see if it looks like an image index
 | ||||
| 			res, err := ms.manifestListHandler.Unmarshal(ctx, dgst, content) | ||||
| 			resIndex := res.(*manifestlist.DeserializedManifestList) | ||||
| 			if err == nil && resIndex.Manifests != nil { | ||||
| 				return resIndex, nil | ||||
| 			} | ||||
| 
 | ||||
| 			// Otherwise, assume it must be an image manifest
 | ||||
| 			return ms.ocischemaHandler.Unmarshal(ctx, dgst, content) | ||||
| 		default: | ||||
| 			return nil, distribution.ErrManifestVerification{fmt.Errorf("unrecognized manifest content type %s", versioned.MediaType)} | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue