diff --git a/integration/copy_test.go b/integration/copy_test.go index 1b28759b..43a4d4aa 100644 --- a/integration/copy_test.go +++ b/integration/copy_test.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "fmt" "io/ioutil" "net/http" @@ -103,9 +104,9 @@ func (s *CopySuite) TestCopySimpleAtomicRegistry(c *check.C) { assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1) // "push": dir: → atomic: assertSkopeoSucceeds(c, "", "--tls-verify=false", "--debug", "copy", "dir:"+dir1, "atomic:localhost:5000/myns/unsigned:unsigned") - // The result of pushing and pulling is an unmodified image. + // The result of pushing and pulling is an equivalent image, except for schema1 embedded names. assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:unsigned", "dir:"+dir2) - destructiveCheckDirImagesAreEqual(c, dir1, dir2) + assertSchema1DirImagesAreEqualExceptNames(c, dir1, "estesp/busybox:amd64", dir2, "myns/unsigned:unsigned") } // The most basic (skopeo copy) use: @@ -139,11 +140,10 @@ func (s *CopySuite) TestCopySimple(c *check.C) { c.Assert(err, check.IsNil) } -// Check whether dir: images in dir1 and dir2 are equal. -// WARNING: This modifies the contents of dir1 and dir2! -func destructiveCheckDirImagesAreEqual(c *check.C, dir1, dir2 string) { +// Check whether dir: images in dir1 and dir2 are equal, ignoring schema1 signatures. +func assertDirImagesAreEqual(c *check.C, dir1, dir2 string) { // The manifests may have different JWS signatures; so, compare the manifests by digests, which - // strips the signatures, and remove them, comparing the rest file by file. + // strips the signatures. digests := []digest.Digest{} for _, dir := range []string{dir1, dir2} { manifestPath := filepath.Join(dir, "manifest.json") @@ -152,12 +152,37 @@ func destructiveCheckDirImagesAreEqual(c *check.C, dir1, dir2 string) { digest, err := manifest.Digest(m) c.Assert(err, check.IsNil) digests = append(digests, digest) - err = os.Remove(manifestPath) - c.Assert(err, check.IsNil) - c.Logf("Manifest file %s (digest %s) removed", manifestPath, digest) } c.Assert(digests[0], check.Equals, digests[1]) - out := combinedOutputOfCommand(c, "diff", "-urN", dir1, dir2) + // Then compare the rest file by file. + out := combinedOutputOfCommand(c, "diff", "-urN", "-x", "manifest.json", dir1, dir2) + c.Assert(out, check.Equals, "") +} + +// Check whether schema1 dir: images in dir1 and dir2 are equal, ignoring schema1 signatures and the embedded path/tag values, which should have the expected values. +func assertSchema1DirImagesAreEqualExceptNames(c *check.C, dir1, ref1, dir2, ref2 string) { + // The manifests may have different JWS signatures and names; so, unmarshal and delete these elements. + manifests := []map[string]interface{}{} + for dir, ref := range map[string]string{dir1: ref1, dir2: ref2} { + manifestPath := filepath.Join(dir, "manifest.json") + m, err := ioutil.ReadFile(manifestPath) + c.Assert(err, check.IsNil) + data := map[string]interface{}{} + err = json.Unmarshal(m, &data) + c.Assert(err, check.IsNil) + c.Assert(data["schemaVersion"], check.Equals, float64(1)) + colon := strings.LastIndex(ref, ":") + c.Assert(colon, check.Not(check.Equals), -1) + c.Assert(data["name"], check.Equals, ref[:colon]) + c.Assert(data["tag"], check.Equals, ref[colon+1:]) + for _, key := range []string{"signatures", "name", "tag"} { + delete(data, key) + } + manifests = append(manifests, data) + } + c.Assert(manifests[0], check.DeepEquals, manifests[1]) + // Then compare the rest file by file. + out := combinedOutputOfCommand(c, "diff", "-urN", "-x", "manifest.json", dir1, dir2) c.Assert(out, check.Equals, "") } @@ -176,7 +201,7 @@ func (s *CopySuite) TestCopyStreaming(c *check.C) { // Compare (copies of) the original and the copy: assertSkopeoSucceeds(c, "", "copy", "docker://estesp/busybox:amd64", "dir:"+dir1) assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/unsigned:streaming", "dir:"+dir2) - destructiveCheckDirImagesAreEqual(c, dir1, dir2) + assertSchema1DirImagesAreEqualExceptNames(c, dir1, "estesp/busybox:amd64", dir2, "myns/unsigned:streaming") // FIXME: Also check pushing to docker:// } @@ -253,34 +278,34 @@ func (s *CopySuite) TestCopySignatures(c *check.C) { // type: signedBy // Sign the images - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "personal@example.com", "docker://busybox:1.23", "atomic:localhost:5000/myns/personal:personal") - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "official@example.com", "docker://busybox:1.23.2", "atomic:localhost:5000/myns/official:official") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "personal@example.com", "docker://busybox:1.26", "atomic:localhost:5006/myns/personal:personal") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "official@example.com", "docker://busybox:1.26.1", "atomic:localhost:5006/myns/official:official") // Verify that we can pull them - assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/personal:personal", dirDest) - assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/official:official", dirDest) + assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/personal:personal", dirDest) + assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/official:official", dirDest) // Verify that mis-signed images are rejected - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/personal:personal", "atomic:localhost:5000/myns/official:attack") - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/personal:attack") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5006/myns/personal:personal", "atomic:localhost:5006/myns/official:attack") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5006/myns/official:official", "atomic:localhost:5006/myns/personal:attack") assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*", - "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/personal:attack", dirDest) + "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/personal:attack", dirDest) assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*", - "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/official:attack", dirDest) + "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/official:attack", dirDest) // Verify that signed identity is verified. - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/naming:test1") - assertSkopeoFails(c, ".*Source image rejected: Signature for identity localhost:5000/myns/official:official is not accepted.*", - "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/naming:test1", dirDest) + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5006/myns/official:official", "atomic:localhost:5006/myns/naming:test1") + assertSkopeoFails(c, ".*Source image rejected: Signature for identity localhost:5006/myns/official:official is not accepted.*", + "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/naming:test1", dirDest) // signedIdentity works - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/naming:naming") - assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/naming:naming", dirDest) + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5006/myns/official:official", "atomic:localhost:5006/myns/naming:naming") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/naming:naming", dirDest) // Verify that cosigning requirements are enforced - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/cosigned:cosigned") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "atomic:localhost:5006/myns/official:official", "atomic:localhost:5006/myns/cosigned:cosigned") assertSkopeoFails(c, ".*Source image rejected: Invalid GPG signature.*", - "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/cosigned:cosigned", dirDest) + "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/cosigned:cosigned", dirDest) - assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "personal@example.com", "atomic:localhost:5000/myns/official:official", "atomic:localhost:5000/myns/cosigned:cosigned") - assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5000/myns/cosigned:cosigned", dirDest) + assertSkopeoSucceeds(c, "", "--tls-verify=false", "copy", "--sign-by", "personal@example.com", "atomic:localhost:5006/myns/official:official", "atomic:localhost:5006/myns/cosigned:cosigned") + assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "copy", "atomic:localhost:5006/myns/cosigned:cosigned", dirDest) } // --policy copy for dir: sources @@ -342,10 +367,10 @@ func (s *CopySuite) TestCopyCompression(c *check.C) { defer os.RemoveAll(topDir) for i, t := range []struct{ fixture, remote string }{ - //{"uncompressed-image-s1", "docker://" + v2DockerRegistryURL + "/compression/compression:s1"}, // FIXME: depends on push to tag working - //{"uncompressed-image-s2", "docker://" + v2DockerRegistryURL + "/compression/compression:s2"}, // FIXME: depends on push to tag working + {"uncompressed-image-s1", "docker://" + v2DockerRegistryURL + "/compression/compression:s1"}, + {"uncompressed-image-s2", "docker://" + v2DockerRegistryURL + "/compression/compression:s2"}, {"uncompressed-image-s1", "atomic:localhost:5000/myns/compression:s1"}, - //{"uncompressed-image-s2", "atomic:localhost:5000/myns/compression:s2"}, // FIXME: The unresolved "MANIFEST_UNKNOWN"/"unexpected end of JSON input" failure + {"uncompressed-image-s2", "atomic:localhost:5000/myns/compression:s2"}, } { dir := filepath.Join(topDir, fmt.Sprintf("case%d", i)) err := os.MkdirAll(dir, 0755) @@ -501,7 +526,7 @@ func (s *CopySuite) TestCopyAtomicExtension(c *check.C) { assertSkopeoSucceeds(c, "", "--tls-verify=false", "--policy", policy, "--registries.d", registriesDir, "copy", "docker://localhost:5000/myns/extension:atomic", dirDest+"/dirAD") // Both access methods result in the same data. - destructiveCheckDirImagesAreEqual(c, filepath.Join(topDir, "dirAA"), filepath.Join(topDir, "dirAD")) + assertDirImagesAreEqual(c, filepath.Join(topDir, "dirAA"), filepath.Join(topDir, "dirAD")) // Get another image (different so that they don't share signatures, and sign it using docker://) assertSkopeoSucceeds(c, "", "--tls-verify=false", "--registries.d", registriesDir, @@ -514,7 +539,7 @@ func (s *CopySuite) TestCopyAtomicExtension(c *check.C) { assertSkopeoSucceeds(c, "", "--debug", "--tls-verify=false", "--policy", policy, "--registries.d", registriesDir, "copy", "docker://localhost:5000/myns/extension:extension", dirDest+"/dirDD") // Both access methods result in the same data. - destructiveCheckDirImagesAreEqual(c, filepath.Join(topDir, "dirDA"), filepath.Join(topDir, "dirDD")) + assertDirImagesAreEqual(c, filepath.Join(topDir, "dirDA"), filepath.Join(topDir, "dirDD")) } func (s *SkopeoSuite) TestCopySrcWithAuth(c *check.C) { @@ -547,13 +572,7 @@ func (s *CopySuite) TestCopySchemaConversion(c *check.C) { // Test conversion / schema autodetection both for the OpenShift embedded registry… s.testCopySchemaConversionRegistries(c, "docker://localhost:5005/myns/schema1", "docker://localhost:5006/myns/schema2") // … and for various docker/distribution registry versions. - if false { - // FIXME: This does not currently work, because the schema1-only docker/distribution registry we have (unlike newer versions) - // enforces that a schema1 manifest contains a matching tag field. Our _s2→s1 conversion_ code does set the tag correctly, - // but a mere copy of schema1→schema1 changing the tag does not update the manifest. - // So, enabling this test results in a successful schema2→schema1 conversion, followed by a schema1→schema1 copy failure. - s.testCopySchemaConversionRegistries(c, "docker://"+v2s1DockerRegistryURL+"/schema1", "docker://"+v2DockerRegistryURL+"/schema2") - } + s.testCopySchemaConversionRegistries(c, "docker://"+v2s1DockerRegistryURL+"/schema1", "docker://"+v2DockerRegistryURL+"/schema2") } func (s *CopySuite) testCopySchemaConversionRegistries(c *check.C, schema1Registry, schema2Registry string) { diff --git a/integration/fixtures/policy.json b/integration/fixtures/policy.json index eb68d7f2..2ba1c2a2 100644 --- a/integration/fixtures/policy.json +++ b/integration/fixtures/policy.json @@ -45,46 +45,46 @@ ] }, "atomic": { - "localhost:5000/myns/personal": [ + "localhost:5006/myns/personal": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "@keydir@/personal-pubkey.gpg" } ], - "localhost:5000/myns/official": [ + "localhost:5006/myns/official": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "@keydir@/official-pubkey.gpg" } ], - "localhost:5000/myns/naming:test1": [ + "localhost:5006/myns/naming:test1": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "@keydir@/official-pubkey.gpg" } ], - "localhost:5000/myns/naming:naming": [ + "localhost:5006/myns/naming:naming": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "@keydir@/official-pubkey.gpg", "signedIdentity": { "type": "exactRepository", - "dockerRepository": "localhost:5000/myns/official" + "dockerRepository": "localhost:5006/myns/official" } } ], - "localhost:5000/myns/cosigned:cosigned": [ + "localhost:5006/myns/cosigned:cosigned": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "@keydir@/official-pubkey.gpg", "signedIdentity": { "type": "exactRepository", - "dockerRepository": "localhost:5000/myns/official" + "dockerRepository": "localhost:5006/myns/official" } }, { diff --git a/integration/registry.go b/integration/registry.go index 0136e336..fa749bd7 100644 --- a/integration/registry.go +++ b/integration/registry.go @@ -109,6 +109,7 @@ http: } cmd := exec.Command(binary, confPath) + consumeAndLogOutputs(c, fmt.Sprintf("registry-%s", url), cmd) if err := cmd.Start(); err != nil { os.RemoveAll(tmp) if os.IsNotExist(err) { diff --git a/vendor/github.com/containers/image/copy/copy.go b/vendor/github.com/containers/image/copy/copy.go index 1fb753ed..fd131765 100644 --- a/vendor/github.com/containers/image/copy/copy.go +++ b/vendor/github.com/containers/image/copy/copy.go @@ -183,6 +183,10 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe manifestUpdates := types.ManifestUpdateOptions{} manifestUpdates.InformationOnly.Destination = dest + if err := updateEmbeddedDockerReference(&manifestUpdates, dest, src, canModifyManifest); err != nil { + return err + } + // We compute preferredManifestMIMEType only to show it in error messages. // Without having to add this context in an error message, we would be happy enough to know only that no conversion is needed. preferredManifestMIMEType, otherManifestMIMETypeCandidates, err := determineManifestConversion(&manifestUpdates, src, destSupportedManifestMIMETypes, canModifyManifest) @@ -273,6 +277,24 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe return nil } +// updateEmbeddedDockerReference handles the Docker reference embedded in Docker schema1 manifests. +func updateEmbeddedDockerReference(manifestUpdates *types.ManifestUpdateOptions, dest types.ImageDestination, src types.Image, canModifyManifest bool) error { + destRef := dest.Reference().DockerReference() + if destRef == nil { + return nil // Destination does not care about Docker references + } + if !src.EmbeddedDockerReferenceConflicts(destRef) { + return nil // No reference embedded in the manifest, or it matches destRef already. + } + + if !canModifyManifest { + return errors.Errorf("Copying a schema1 image with an embedded Docker reference to %s (Docker reference %s) would invalidate existing signatures. Explicitly enable signature removal to proceed anyway", + transports.ImageName(dest.Reference()), destRef.String()) + } + manifestUpdates.EmbeddedDockerReference = destRef + return nil +} + // copyLayers copies layers from src/rawSource to dest, using and updating ic.manifestUpdates if necessary and ic.canModifyManifest. func (ic *imageCopier) copyLayers() error { srcInfos := ic.src.LayerInfos() diff --git a/vendor/github.com/containers/image/image/docker_schema1.go b/vendor/github.com/containers/image/image/docker_schema1.go index 6d09a868..4152b3cd 100644 --- a/vendor/github.com/containers/image/image/docker_schema1.go +++ b/vendor/github.com/containers/image/image/docker_schema1.go @@ -135,6 +135,27 @@ func (m *manifestSchema1) LayerInfos() []types.BlobInfo { return layers } +// EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. +// It returns false if the manifest does not embed a Docker reference. +// (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) +func (m *manifestSchema1) EmbeddedDockerReferenceConflicts(ref reference.Named) bool { + // This is a bit convoluted: We can’t just have a "get embedded docker reference" method + // and have the “does it conflict” logic in the generic copy code, because the manifest does not actually + // embed a full docker/distribution reference, but only the repo name and tag (without the host name). + // So we would have to provide a “return repo without host name, and tag” getter for the generic code, + // which would be very awkward. Instead, we do the matching here in schema1-specific code, and all the + // generic copy code needs to know about is reference.Named and that a manifest may need updating + // for some destinations. + name := reference.Path(ref) + var tag string + if tagged, isTagged := ref.(reference.NamedTagged); isTagged { + tag = tagged.Tag() + } else { + tag = "" + } + return m.Name != name || m.Tag != tag +} + func (m *manifestSchema1) imageInspectInfo() (*types.ImageInspectInfo, error) { v1 := &v1Image{} if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), v1); err != nil { @@ -173,6 +194,14 @@ func (m *manifestSchema1) UpdatedImage(options types.ManifestUpdateOptions) (typ copy.FSLayers[(len(options.LayerInfos)-1)-i].BlobSum = info.Digest } } + if options.EmbeddedDockerReference != nil { + copy.Name = reference.Path(options.EmbeddedDockerReference) + if tagged, isTagged := options.EmbeddedDockerReference.(reference.NamedTagged); isTagged { + copy.Tag = tagged.Tag() + } else { + copy.Tag = "" + } + } switch options.ManifestMIMEType { case "": // No conversion, OK diff --git a/vendor/github.com/containers/image/image/docker_schema2.go b/vendor/github.com/containers/image/image/docker_schema2.go index ea529e24..a2a36ea2 100644 --- a/vendor/github.com/containers/image/image/docker_schema2.go +++ b/vendor/github.com/containers/image/image/docker_schema2.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/Sirupsen/logrus" + "github.com/containers/image/docker/reference" "github.com/containers/image/manifest" "github.com/containers/image/types" "github.com/opencontainers/go-digest" @@ -140,6 +141,13 @@ func (m *manifestSchema2) LayerInfos() []types.BlobInfo { return blobs } +// EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. +// It returns false if the manifest does not embed a Docker reference. +// (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) +func (m *manifestSchema2) EmbeddedDockerReferenceConflicts(ref reference.Named) bool { + return false +} + func (m *manifestSchema2) imageInspectInfo() (*types.ImageInspectInfo, error) { config, err := m.ConfigBlob() if err != nil { @@ -180,6 +188,7 @@ func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (typ copy.LayersDescriptors[i].URLs = info.URLs } } + // Ignore options.EmbeddedDockerReference: it may be set when converting from schema1 to schema2, but we really don't care. switch options.ManifestMIMEType { case "": // No conversion, OK diff --git a/vendor/github.com/containers/image/image/manifest.go b/vendor/github.com/containers/image/image/manifest.go index 4715a3bc..75c9e711 100644 --- a/vendor/github.com/containers/image/image/manifest.go +++ b/vendor/github.com/containers/image/image/manifest.go @@ -3,6 +3,7 @@ package image import ( "time" + "github.com/containers/image/docker/reference" "github.com/containers/image/manifest" "github.com/containers/image/pkg/strslice" "github.com/containers/image/types" @@ -72,6 +73,10 @@ type genericManifest interface { // The Digest field is guaranteed to be provided; Size may be -1. // WARNING: The list may contain duplicates, and they are semantically relevant. LayerInfos() []types.BlobInfo + // EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. + // It returns false if the manifest does not embed a Docker reference. + // (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) + EmbeddedDockerReferenceConflicts(ref reference.Named) bool imageInspectInfo() (*types.ImageInspectInfo, error) // To be called by inspectManifest // UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. // This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute diff --git a/vendor/github.com/containers/image/image/oci.go b/vendor/github.com/containers/image/image/oci.go index 74084204..2575d1e0 100644 --- a/vendor/github.com/containers/image/image/oci.go +++ b/vendor/github.com/containers/image/image/oci.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io/ioutil" + "github.com/containers/image/docker/reference" "github.com/containers/image/manifest" "github.com/containers/image/types" "github.com/opencontainers/go-digest" @@ -107,6 +108,13 @@ func (m *manifestOCI1) LayerInfos() []types.BlobInfo { return blobs } +// EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. +// It returns false if the manifest does not embed a Docker reference. +// (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) +func (m *manifestOCI1) EmbeddedDockerReferenceConflicts(ref reference.Named) bool { + return false +} + func (m *manifestOCI1) imageInspectInfo() (*types.ImageInspectInfo, error) { config, err := m.ConfigBlob() if err != nil { @@ -146,6 +154,7 @@ func (m *manifestOCI1) UpdatedImage(options types.ManifestUpdateOptions) (types. copy.LayersDescriptors[i].Size = info.Size } } + // Ignore options.EmbeddedDockerReference: it may be set when converting from schema1, but we really don't care. switch options.ManifestMIMEType { case "": // No conversion, OK diff --git a/vendor/github.com/containers/image/types/types.go b/vendor/github.com/containers/image/types/types.go index 62f5732b..63337c81 100644 --- a/vendor/github.com/containers/image/types/types.go +++ b/vendor/github.com/containers/image/types/types.go @@ -226,6 +226,10 @@ type Image interface { // The Digest field is guaranteed to be provided; Size may be -1. // WARNING: The list may contain duplicates, and they are semantically relevant. LayerInfos() []BlobInfo + // EmbeddedDockerReferenceConflicts whether a Docker reference embedded in the manifest, if any, conflicts with destination ref. + // It returns false if the manifest does not embed a Docker reference. + // (This embedding unfortunately happens for Docker schema1, please do not add support for this in any new formats.) + EmbeddedDockerReferenceConflicts(ref reference.Named) bool // Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration. Inspect() (*ImageInspectInfo, error) // UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs. @@ -245,8 +249,9 @@ type Image interface { // ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest type ManifestUpdateOptions struct { - LayerInfos []BlobInfo // Complete BlobInfos (size+digest+urls) which should replace the originals, in order (the root layer first, and then successive layered layers) - ManifestMIMEType string + LayerInfos []BlobInfo // Complete BlobInfos (size+digest+urls) which should replace the originals, in order (the root layer first, and then successive layered layers) + EmbeddedDockerReference reference.Named + ManifestMIMEType string // The values below are NOT requests to modify the image; they provide optional context which may or may not be used. InformationOnly ManifestUpdateInformation }