Skip to content

Commit

Permalink
Update embedded Docker reference, if any, in copy.Image
Browse files Browse the repository at this point in the history
Add EmbbeddedDockerReference to types.ManifestUpdateOptions, and use it
in copy.Image.  Pushing signed schema1 images to a different location
is impossible (skopeo users can use --remove-signatures), but signing an
unsigned schema1 image while pushing it does work.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
  • Loading branch information
mtrmac committed Nov 25, 2016
1 parent c71757b commit 1dc2a3b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 2 deletions.
31 changes: 31 additions & 0 deletions copy/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
canModifyManifest := len(sigs) == 0
manifestUpdates := types.ManifestUpdateOptions{}

if err := updateEmbeddedDockerReference(&manifestUpdates, dest, src, canModifyManifest); err != nil {
return err
}

if err := determineManifestConversion(&manifestUpdates, src, destSupportedManifestMIMETypes, canModifyManifest); err != nil {
return err
}
Expand Down Expand Up @@ -222,6 +226,33 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
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 {
manifestRef, err := src.EmbeddedDockerReference()
if err != nil {
return fmt.Errorf("Error parsing source image for embedded Docker reference: %v", err)
}
if manifestRef == nil {
return nil // No embedded manifest
}

destRef := dest.Reference().DockerReference()
if destRef == nil {
return nil // Destination does not care about Docker references
}

if destRef.String() == manifestRef.String() {
return nil // The reference matches
}

if !canModifyManifest {
return fmt.Errorf("Copying a schema1 image with embedded Docker reference %s to %s (Docker reference %s) would invalidate existing signatures. Explicitly enable signature removal to proceed anyway",
manifestRef.String(), transports.ImageName(dest.Reference()), destRef.String())
}
manifestUpdates.EmbeddedDockerReference = destRef
return nil
}

// copyLayers copies layers from src/rawSource to dest, using and updating manifestUpdates if necessary and canModifyManifest.
// If src.UpdatedImageNeedsLayerDiffIDs(manifestUpdates) will be true, it needs to be true by the time this function is called.
func copyLayers(manifestUpdates *types.ManifestUpdateOptions, dest types.ImageDestination, src types.Image, rawSource types.ImageSource,
Expand Down
8 changes: 8 additions & 0 deletions image/docker_schema1.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,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 = options.EmbeddedDockerReference.Name()
if tagged, isTagged := options.EmbeddedDockerReference.(reference.NamedTagged); isTagged {
copy.Tag = tagged.Tag()
} else {
copy.Tag = ""
}
}

switch options.ManifestMIMEType {
case "": // No conversion, OK
Expand Down
1 change: 1 addition & 0 deletions image/docker_schema2.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (typ
copy.LayersDescriptors[i].Size = info.Size
}
}
// 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
Expand Down
5 changes: 3 additions & 2 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,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) which should replace the originals, in order (the root layer first, and then successive layered layers)
ManifestMIMEType string
LayerInfos []BlobInfo // Complete BlobInfos (size+digest) 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
}
Expand Down

0 comments on commit 1dc2a3b

Please sign in to comment.