Skip to content
Merged
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
22 changes: 16 additions & 6 deletions docker/docker_image_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ import (
"github.com/pkg/errors"
)

var manifestMIMETypes = []string{
// TODO(runcom): we'll add OCI as part of another PR here
manifest.DockerV2Schema2MediaType,
manifest.DockerV2Schema1SignedMediaType,
manifest.DockerV2Schema1MediaType,
}

func supportedManifestMIMETypesMap() map[string]bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think a map[string]struct{} is more idiomatic, but I really don’t care enough.

Copy link
Member Author

Choose a reason for hiding this comment

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

arg, that's how it was, then changed my mind, I'll put it back with struct{}

Copy link
Member Author

Choose a reason for hiding this comment

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

on a second though, I like comparing with just ! - we change this any time though...

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sure, whatever works.

m := make(map[string]bool, len(manifestMIMETypes))
for _, mt := range manifestMIMETypes {
m[mt] = true
}
return m
}

type dockerImageDestination struct {
ref dockerReference
c *dockerClient
Expand Down Expand Up @@ -47,12 +62,7 @@ func (d *dockerImageDestination) Close() {
}

func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
return []string{
// TODO(runcom): we'll add OCI as part of another PR here
manifest.DockerV2Schema2MediaType,
manifest.DockerV2Schema1SignedMediaType,
manifest.DockerV2Schema1MediaType,
}
return manifestMIMETypes
}

// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
Expand Down
11 changes: 11 additions & 0 deletions docker/docker_image_src.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ func newImageSource(ctx *types.SystemContext, ref dockerReference, requestedMani
if requestedManifestMIMETypes == nil {
requestedManifestMIMETypes = manifest.DefaultRequestedManifestMIMETypes
}
supportedMIMEs := supportedManifestMIMETypesMap()
acceptableRequestedMIMEs := false
for _, mtrequested := range requestedManifestMIMETypes {
if supportedMIMEs[mtrequested] {
acceptableRequestedMIMEs = true
break
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would ignore the input value if any value is unrecognized; I think it should ignore input only if all values are unrecognized (so that a caller can say “i prefer v2s1, then OCI, then v2s2 as a last resort”.)

}
}
if !acceptableRequestedMIMEs {
requestedManifestMIMETypes = manifest.DefaultRequestedManifestMIMETypes
}
return &dockerImageSource{
ref: ref,
requestedManifestMIMETypes: requestedManifestMIMETypes,
Expand Down
28 changes: 28 additions & 0 deletions image/docker_schema2.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/containers/image/manifest"
"github.com/containers/image/types"
"github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -166,13 +167,40 @@ func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (typ
case "": // No conversion, OK
case manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema1MediaType:
return copy.convertToManifestSchema1(options.InformationOnly.Destination)
case imgspecv1.MediaTypeImageManifest:
return copy.convertToManifestOCI1()
default:
return nil, errors.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema2MediaType, options.ManifestMIMEType)
}

return memoryImageFromManifest(&copy), nil
}

func (m *manifestSchema2) convertToManifestOCI1() (types.Image, error) {
// Create a copy of the descriptor.
config := m.ConfigDescriptor

// The only difference between OCI and DockerSchema2 is the mediatypes. The
// media type of the manifest is handled by manifestSchema2FromComponents.
config.MediaType = imgspecv1.MediaTypeImageConfig

layers := make([]descriptor, len(m.LayersDescriptors))
for idx := range layers {
layers[idx] = m.LayersDescriptors[idx]
if m.LayersDescriptors[idx].MediaType == manifest.DockerV2Schema2ForeignLayerMediaType {
layers[idx].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable
} else {
layers[idx].MediaType = imgspecv1.MediaTypeImageLayerGzip
Copy link
Collaborator

Choose a reason for hiding this comment

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

This works for now (i.e. at it was perfectly valid a week ago), longer-term we should actually know whether the input is gzipped. Filed #229.

}
}

// Rather than copying the ConfigBlob now, we just pass m.src to the
// translated manifest, since the only difference is the mediatype of
// descriptors there is no change to any blob stored in m.src.
m1 := manifestOCI1FromComponents(config, m.src, nil, layers)
return memoryImageFromManifest(m1), nil
}

// Based on docker/distribution/manifest/schema1/config_builder.go
func (m *manifestSchema2) convertToManifestSchema1(dest types.ImageDestination) (types.Image, error) {
configBytes, err := m.ConfigBlob()
Expand Down
23 changes: 23 additions & 0 deletions image/docker_schema2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/containers/image/manifest"
"github.com/containers/image/types"
"github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -440,6 +441,28 @@ func TestManifestSchema2UpdatedImage(t *testing.T) {
assert.Equal(t, *typedM2, *typedOriginal)
}

func TestConvertToManifestOCI(t *testing.T) {
originalSrc := newSchema2ImageSource(t, "httpd-copy:latest")
original := manifestSchema2FromFixture(t, originalSrc, "schema2.json")
res, err := original.UpdatedImage(types.ManifestUpdateOptions{
ManifestMIMEType: imgspecv1.MediaTypeImageManifest,
})
require.NoError(t, err)

convertedJSON, mt, err := res.Manifest()
require.NoError(t, err)
assert.Equal(t, imgspecv1.MediaTypeImageManifest, mt)

byHandJSON, err := ioutil.ReadFile("fixtures/schema2-to-oci1.json")
require.NoError(t, err)
var converted, byHand map[string]interface{}
err = json.Unmarshal(byHandJSON, &byHand)
require.NoError(t, err)
err = json.Unmarshal(convertedJSON, &converted)
require.NoError(t, err)
assert.Equal(t, byHand, converted)
}

func TestConvertToManifestSchema1(t *testing.T) {
originalSrc := newSchema2ImageSource(t, "httpd-copy:latest")
original := manifestSchema2FromFixture(t, originalSrc, "schema2.json")
Expand Down
1 change: 0 additions & 1 deletion image/fixtures/oci1.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 5940,
Expand Down
29 changes: 29 additions & 0 deletions image/fixtures/schema2-to-oci1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 5940,
"digest": "sha256:9ca4bda0a6b3727a6ffcc43e981cad0f24e2ec79d338f6ba325b4dfd0756fb8f"
},
"layers": [{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 51354364,
"digest": "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb"
}, {
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 150,
"digest": "sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c"
}, {
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 11739507,
"digest": "sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9"
}, {
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 8841833,
"digest": "sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909"
}, {
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 291,
"digest": "sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa"
}]
}
8 changes: 3 additions & 5 deletions image/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ type manifestOCI1 struct {
src types.ImageSource // May be nil if configBlob is not nil
configBlob []byte // If set, corresponds to contents of ConfigDescriptor.
SchemaVersion int `json:"schemaVersion"`
MediaType string `json:"mediaType"`
ConfigDescriptor descriptor `json:"config"`
LayersDescriptors []descriptor `json:"layers"`
}
Expand All @@ -29,12 +28,11 @@ func manifestOCI1FromManifest(src types.ImageSource, manifest []byte) (genericMa
}

// manifestOCI1FromComponents builds a new manifestOCI1 from the supplied data:
func manifestOCI1FromComponents(config descriptor, configBlob []byte, layers []descriptor) genericManifest {
func manifestOCI1FromComponents(config descriptor, src types.ImageSource, configBlob []byte, layers []descriptor) genericManifest {
return &manifestOCI1{
src: nil,
src: src,
configBlob: configBlob,
SchemaVersion: 2,
MediaType: imgspecv1.MediaTypeImageManifest,
ConfigDescriptor: config,
LayersDescriptors: layers,
}
Expand All @@ -45,7 +43,7 @@ func (m *manifestOCI1) serialize() ([]byte, error) {
}

func (m *manifestOCI1) manifestMIMEType() string {
return m.MediaType
return imgspecv1.MediaTypeImageManifest
}

// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object.
Expand Down
12 changes: 6 additions & 6 deletions image/oci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,29 @@ func manifestOCI1FromComponentsLikeFixture(configBlob []byte) genericManifest {
MediaType: imgspecv1.MediaTypeImageConfig,
Size: 5940,
Digest: "sha256:9ca4bda0a6b3727a6ffcc43e981cad0f24e2ec79d338f6ba325b4dfd0756fb8f",
}, configBlob, []descriptor{
}, nil, configBlob, []descriptor{
{
MediaType: imgspecv1.MediaTypeImageLayer,
MediaType: imgspecv1.MediaTypeImageLayerGzip,
Digest: "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
Size: 51354364,
},
{
MediaType: imgspecv1.MediaTypeImageLayer,
MediaType: imgspecv1.MediaTypeImageLayerGzip,
Digest: "sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c",
Size: 150,
},
{
MediaType: imgspecv1.MediaTypeImageLayer,
MediaType: imgspecv1.MediaTypeImageLayerGzip,
Digest: "sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9",
Size: 11739507,
},
{
MediaType: imgspecv1.MediaTypeImageLayer,
MediaType: imgspecv1.MediaTypeImageLayerGzip,
Digest: "sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909",
Size: 8841833,
},
{
MediaType: imgspecv1.MediaTypeImageLayer,
MediaType: imgspecv1.MediaTypeImageLayerGzip,
Digest: "sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa",
Size: 291,
},
Expand Down
58 changes: 8 additions & 50 deletions oci/layout/oci_dest.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ func (d *ociImageDestination) Close() {
func (d *ociImageDestination) SupportedManifestMIMETypes() []string {
return []string{
imgspecv1.MediaTypeImageManifest,
manifest.DockerV2Schema2MediaType,
}
}

Expand Down Expand Up @@ -134,60 +133,16 @@ func (d *ociImageDestination) ReapplyBlob(info types.BlobInfo) (types.BlobInfo,
return info, nil
}

func createManifest(m []byte) ([]byte, string, error) {
om := imgspecv1.Manifest{}
mt := manifest.GuessMIMEType(m)
switch mt {
case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType:
// There a simple reason about not yet implementing this.
// OCI image-spec assure about backward compatibility with docker v2s2 but not v2s1
// generating a v2s2 is a migration docker does when upgrading to 1.10.3
// and I don't think we should bother about this now (I don't want to have migration code here in skopeo)
return nil, "", errors.New("can't create an OCI manifest from Docker V2 schema 1 manifest")
case manifest.DockerV2Schema2MediaType:
if err := json.Unmarshal(m, &om); err != nil {
return nil, "", err
}
om.MediaType = imgspecv1.MediaTypeImageManifest
for i, l := range om.Layers {
if l.MediaType == manifest.DockerV2Schema2ForeignLayerMediaType {
om.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable
} else {
om.Layers[i].MediaType = imgspecv1.MediaTypeImageLayer
}
}
om.Config.MediaType = imgspecv1.MediaTypeImageConfig
b, err := json.Marshal(om)
if err != nil {
return nil, "", err
}
return b, om.MediaType, nil
case manifest.DockerV2ListMediaType:
return nil, "", errors.New("can't create an OCI manifest from Docker V2 schema 2 manifest list")
case imgspecv1.MediaTypeImageManifestList:
return nil, "", errors.New("can't create an OCI manifest from OCI manifest list")
case imgspecv1.MediaTypeImageManifest:
return m, mt, nil
}
return nil, "", errors.Errorf("unrecognized manifest media type %q", mt)
}

func (d *ociImageDestination) PutManifest(m []byte) error {
// TODO(mitr, runcom): this breaks signatures entirely since at this point we're creating a new manifest
// and signatures don't apply anymore. Will fix.
ociMan, mt, err := createManifest(m)
if err != nil {
return err
}
digest, err := manifest.Digest(ociMan)
digest, err := manifest.Digest(m)
if err != nil {
return err
}
desc := imgspecv1.Descriptor{}
desc.Digest = digest.String()
desc.Digest = digest
// TODO(runcom): beaware and add support for OCI manifest list
desc.MediaType = mt
desc.Size = int64(len(ociMan))
desc.MediaType = imgspecv1.MediaTypeImageManifest
desc.Size = int64(len(m))
data, err := json.Marshal(desc)
if err != nil {
return err
Expand All @@ -197,7 +152,10 @@ func (d *ociImageDestination) PutManifest(m []byte) error {
if err != nil {
return err
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This …NonDistributable conversion is not present in the new conversion code, is that intentional?

Copy link
Member Author

Choose a reason for hiding this comment

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

I missed it somehow

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

if err := ioutil.WriteFile(blobPath, ociMan, 0644); err != nil {
if err := ensureParentDirectoryExists(blobPath); err != nil {
return err
}
if err := ioutil.WriteFile(blobPath, m, 0644); err != nil {
return err
}
// TODO(runcom): ugly here?
Expand Down
33 changes: 0 additions & 33 deletions oci/layout/oci_dest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,36 +59,3 @@ func TestPutBlobDigestFailure(t *testing.T) {
require.Error(t, err)
require.True(t, os.IsNotExist(err))
}

func TestPutManifestUnrecognizedMediaType(t *testing.T) {
ref, tmpDir := refToTempOCI(t)
defer os.RemoveAll(tmpDir)
dirRef, ok := ref.(ociReference)
require.True(t, ok)

ociDest, err := dirRef.NewImageDestination(nil)
require.NoError(t, err)

m := `{"name":"puerapuliae/busybox","tag":"latest","architecture":"amd64","fsLayers":[{"blobSum":"sha256:04f18047a28f8dea4a3b3872a2ad345cbb6f0eae28d99a60d3df844d6eaae571"},{"blobSum":"sha256:04f18047a28f8dea4a3b3872a2ad345cbb6f0eae28d99a60d3df844d6eaae571"}],"history":[{"v1Compatibility":"{\"id\":\"b46e47334e74d687019107dbec32559dd598db58fe90d2a0c5473bda8b59829d\",\"comment\":\"Imported from -\",\"created\":\"2015-07-03T07:56:02.57018886Z\",\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":9356886}\n"},{"v1Compatibility":"{\"id\":\"b46e47334e74d687019107dbec32559dd598db58fe90d2a0c5473bda8b59829d\",\"comment\":\"Imported from -\",\"created\":\"2015-07-03T07:56:02.57018886Z\",\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":9356886}\n"}],"signatures":[{"header":{"jwk":{"crv":"P-256","kid":"SVJ4:Q6G3:SXTN:H6LT:7PXH:DHUZ:SGTB:5TMV:YPIV:UPHY:MRHO:PN6V","kty":"EC","x":"qrSsA2UAKEFlDhLk12zoWpnHgYcTNfEOWGZU46pzhfk","y":"RtD_vGFtagPlheiunLvZL02LOssnu7DqShuBwc6Ml44"},"alg":"ES256"},"signature":"YzfU_rKQLWqG74uilltTiV3O92lfEjaG5wJkVt_dCtjH_C5AeghfQttnbtceJOyiaU7xP2yEnjdultutsxkQKQ","protected":"eyJmb3JtYXRMZW5ndGgiOjI4NDgsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNi0wOS0xMFQwODoyMDowOFoifQ"}]}`

err = ociDest.PutManifest([]byte(m))
require.Error(t, err)
assert.Equal(t, `unrecognized manifest media type ""`, err.Error())
}

// regression test for projectatomic/skopeo#198
func TestPutManifestDockerV2Schema1Signed(t *testing.T) {
ref, tmpDir := refToTempOCI(t)
defer os.RemoveAll(tmpDir)
dirRef, ok := ref.(ociReference)
require.True(t, ok)

ociDest, err := dirRef.NewImageDestination(nil)
require.NoError(t, err)

m := `{"name":"puerapuliae/busybox","tag":"latest","architecture":"amd64","fsLayers":[{"blobSum":"sha256:04f18047a28f8dea4a3b3872a2ad345cbb6f0eae28d99a60d3df844d6eaae571"},{"blobSum":"sha256:04f18047a28f8dea4a3b3872a2ad345cbb6f0eae28d99a60d3df844d6eaae571"}],"history":[{"v1Compatibility":"{\"id\":\"b46e47334e74d687019107dbec32559dd598db58fe90d2a0c5473bda8b59829d\",\"comment\":\"Imported from -\",\"created\":\"2015-07-03T07:56:02.57018886Z\",\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":9356886}\n"},{"v1Compatibility":"{\"id\":\"b46e47334e74d687019107dbec32559dd598db58fe90d2a0c5473bda8b59829d\",\"comment\":\"Imported from -\",\"created\":\"2015-07-03T07:56:02.57018886Z\",\"container_config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":9356886}\n"}],"schemaVersion":1,"signatures":[{"header":{"jwk":{"crv":"P-256","kid":"SVJ4:Q6G3:SXTN:H6LT:7PXH:DHUZ:SGTB:5TMV:YPIV:UPHY:MRHO:PN6V","kty":"EC","x":"qrSsA2UAKEFlDhLk12zoWpnHgYcTNfEOWGZU46pzhfk","y":"RtD_vGFtagPlheiunLvZL02LOssnu7DqShuBwc6Ml44"},"alg":"ES256"},"signature":"YzfU_rKQLWqG74uilltTiV3O92lfEjaG5wJkVt_dCtjH_C5AeghfQttnbtceJOyiaU7xP2yEnjdultutsxkQKQ","protected":"eyJmb3JtYXRMZW5ndGgiOjI4NDgsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNi0wOS0xMFQwODoyMDowOFoifQ"}]}`

err = ociDest.PutManifest([]byte(m))
require.Error(t, err)
assert.Equal(t, `can't create an OCI manifest from Docker V2 schema 1 manifest`, err.Error())
}
Loading