forked from TrueCloudLab/distribution
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>
This commit is contained in:
parent
1d47ef7b80
commit
60d9c5dfad
5 changed files with 27 additions and 8 deletions
|
@ -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 a new issue