Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions image/internal/image/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) {
// layers in the resulting configuration isn't guaranteed to be returned to due how
// old image manifests work (docker v2s1 especially).
func (m *manifestOCI1) OCIConfig(ctx context.Context) (*imgspecv1.Image, error) {
if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig {
if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig && m.m.Config.MediaType != internalManifest.WasmConfigMediaType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICS the two objects are not interchangeable and it makes no sense to parse the WASM one as an OCI one.

return nil, internalManifest.NewNonImageArtifactError(&m.m.Manifest)
}

Expand Down Expand Up @@ -244,7 +244,7 @@ func (m *manifestOCI1) layerEditsOfOCIOnlyFeatures(options *types.ManifestUpdate
// value.
// This does not change the state of the original manifestOCI1 object.
func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, options *types.ManifestUpdateOptions) (*manifestSchema2, error) {
if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig {
if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig && m.m.Config.MediaType != internalManifest.WasmConfigMediaType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would that work??!

return nil, internalManifest.NewNonImageArtifactError(&m.m.Manifest)
}

Expand Down Expand Up @@ -290,6 +290,9 @@ func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, options *type
case ociencspec.MediaTypeLayerEnc, ociencspec.MediaTypeLayerGzipEnc, ociencspec.MediaTypeLayerZstdEnc,
ociencspec.MediaTypeLayerNonDistributableEnc, ociencspec.MediaTypeLayerNonDistributableGzipEnc, ociencspec.MediaTypeLayerNonDistributableZstdEnc:
return nil, fmt.Errorf("during manifest conversion: encrypted layers (%q) are not supported in docker images", layers[idx].MediaType)
case internalManifest.WasmContentLayerMediaType, internalManifest.WasmContentLayerMediaType + "+gzip", internalManifest.WasmContentLayerMediaType + "+zstd",
internalManifest.WasmContentLayerMediaType + "+encrypted", internalManifest.WasmContentLayerMediaType + "+gzip+encrypted", internalManifest.WasmContentLayerMediaType + "+zstd+encrypted":
return nil, fmt.Errorf("during manifest conversion: WASM layers (%q) are not supported in docker images", layers[idx].MediaType)
default:
return nil, fmt.Errorf("Unknown media type during manifest conversion: %q", layers[idx].MediaType)
}
Expand All @@ -306,7 +309,7 @@ func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, options *type
// value.
// This does not change the state of the original manifestOCI1 object.
func (m *manifestOCI1) convertToManifestSchema1(ctx context.Context, options *types.ManifestUpdateOptions) (genericManifest, error) {
if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig {
if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig && m.m.Config.MediaType != internalManifest.WasmConfigMediaType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

return nil, internalManifest.NewNonImageArtifactError(&m.m.Manifest)
}

Expand Down
4 changes: 4 additions & 0 deletions image/internal/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ const (
DockerV2Schema2ForeignLayerMediaType = "application/vnd.docker.image.rootfs.foreign.diff.tar"
// DockerV2Schema2ForeignLayerMediaType is the MIME type used for gzipped schema 2 foreign layers.
DockerV2Schema2ForeignLayerMediaTypeGzip = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip"
// WasmContentLayerMediaType is the MIME type used for WASM content layers.
WasmContentLayerMediaType = "application/vnd.wasm.content.layer.v1"
// WasmConfigMediaType is the MIME type used for WASM config blobs.
WasmConfigMediaType = "application/vnd.wasm.config.v1+json"
)

// GuessMIMEType guesses MIME type of a manifest and returns it _if it is recognized_, or "" if unknown or unrecognized.
Expand Down
25 changes: 17 additions & 8 deletions image/manifest/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ func SupportedOCI1MediaType(m string) error {
imgspecv1.MediaTypeImageLayerNonDistributable, imgspecv1.MediaTypeImageLayerNonDistributableGzip, imgspecv1.MediaTypeImageLayerNonDistributableZstd, //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
imgspecv1.MediaTypeImageManifest,
imgspecv1.MediaTypeLayoutHeader,
ociencspec.MediaTypeLayerEnc, ociencspec.MediaTypeLayerGzipEnc:
ociencspec.MediaTypeLayerEnc, ociencspec.MediaTypeLayerGzipEnc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is deprecated and has no known users, so I don’t see much point in extending it.

manifest.WasmContentLayerMediaType, manifest.WasmContentLayerMediaType + "+gzip", manifest.WasmContentLayerMediaType + "+zstd",
manifest.WasmContentLayerMediaType + "+encrypted", manifest.WasmContentLayerMediaType + "+gzip+encrypted", manifest.WasmContentLayerMediaType + "+zstd+encrypted",
manifest.WasmConfigMediaType:
return nil
default:
return fmt.Errorf("unsupported OCIv1 media type: %q", m)
Expand Down Expand Up @@ -116,6 +119,11 @@ var oci1CompressionMIMETypeSets = []compressionMIMETypeSet{
compressiontypes.GzipAlgorithmName: imgspecv1.MediaTypeImageLayerGzip,
compressiontypes.ZstdAlgorithmName: imgspecv1.MediaTypeImageLayerZstd,
},
{
mtsUncompressed: manifest.WasmContentLayerMediaType,
compressiontypes.GzipAlgorithmName: manifest.WasmContentLayerMediaType + "+gzip",
compressiontypes.ZstdAlgorithmName: manifest.WasmContentLayerMediaType + "+zstd",
},
}

// UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls+mediatype), in order (the root layer first, and then successive layered layers)
Expand Down Expand Up @@ -173,7 +181,8 @@ func getEncryptedMediaType(mediatype string) (string, error) {
unsuffixedMediatype := parts[0]
switch unsuffixedMediatype {
case DockerV2Schema2LayerMediaType, imgspecv1.MediaTypeImageLayer,
imgspecv1.MediaTypeImageLayerNonDistributable: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
imgspecv1.MediaTypeImageLayerNonDistributable, //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images.
manifest.WasmContentLayerMediaType:
return mediatype + "+encrypted", nil
}

Expand All @@ -199,11 +208,11 @@ func (m *OCI1) Serialize() ([]byte, error) {

// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration.
func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*types.ImageInspectInfo, error) {
if m.Config.MediaType != imgspecv1.MediaTypeImageConfig {
// We could return at least the layers, but thats already available in a better format via types.Image.LayerInfos.
if m.Config.MediaType != imgspecv1.MediaTypeImageConfig && m.Config.MediaType != manifest.WasmConfigMediaType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And again

// We could return at least the layers, but that's already available in a better format via types.Image.LayerInfos.
// Most software calling this without human intervention is going to expect the values to be realistic and relevant,
// and is probably better served by failing; we can always re-visit that later if we fail now, but
// if we started returning some data for OCI artifacts now, we couldnt start failing in this function later.
// if we started returning some data for OCI artifacts now, we couldn't start failing in this function later.
return nil, manifest.NewNonImageArtifactError(&m.Manifest)
}

Expand Down Expand Up @@ -253,8 +262,8 @@ func (m *OCI1) ImageID(diffIDs []digest.Digest) (string, error) {
// gives us the option to not fail, and return some value, in the future,
// without committing to that approach now.
// (The only known caller of ImageID is storage/storageImageDestination.computeID,
// which cant work with non-image artifacts.)
if m.Config.MediaType != imgspecv1.MediaTypeImageConfig {
// which can't work with non-image artifacts.)
if m.Config.MediaType != imgspecv1.MediaTypeImageConfig && m.Config.MediaType != manifest.WasmConfigMediaType {
return "", manifest.NewNonImageArtifactError(&m.Manifest)
}

Expand All @@ -269,7 +278,7 @@ func (m *OCI1) ImageID(diffIDs []digest.Digest) (string, error) {
// NOTE: Even if this returns true, the relevant format might not accept all compression algorithms; the set of accepted
// algorithms depends not on the current format, but possibly on the target of a conversion.
func (m *OCI1) CanChangeLayerCompression(mimeType string) bool {
if m.Config.MediaType != imgspecv1.MediaTypeImageConfig {
if m.Config.MediaType != imgspecv1.MediaTypeImageConfig && m.Config.MediaType != manifest.WasmConfigMediaType {
return false
}
return compressionVariantsRecognizeMIMEType(oci1CompressionMIMETypeSets, mimeType)
Expand Down
7 changes: 7 additions & 0 deletions image/manifest/oci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ func TestSupportedOCI1MediaType(t *testing.T) {
{imgspecv1.MediaTypeImageLayerZstd, false},
{imgspecv1.MediaTypeImageManifest, false},
{imgspecv1.MediaTypeLayoutHeader, false},
{"application/vnd.wasm.content.layer.v1", false},
{"application/vnd.wasm.content.layer.v1+gzip", false},
{"application/vnd.wasm.content.layer.v1+zstd", false},
{"application/vnd.wasm.content.layer.v1+encrypted", false},
{"application/vnd.wasm.content.layer.v1+gzip+encrypted", false},
{"application/vnd.wasm.content.layer.v1+zstd+encrypted", false},
{"application/vnd.wasm.config.v1+json", false},
{"application/vnd.oci.image.layer.nondistributable.v1.tar+unknown", true},
}
for _, d := range data {
Expand Down
Loading