Skip to content

Commit

Permalink
copy: add support for ForceCompressionFormat
Browse files Browse the repository at this point in the history
ForceCompressionFormat allows end users to force selected compression format
(set in DestinationCtx.CompressionFormat) which ensures that while copying
blobs of other compression algorithms are not reused.

Following flag is a frontend wrapper for: containers#2023
Will help in:
* containers/buildah#4613
* containers/podman#18660

Signed-off-by: Aditya R <arajan@redhat.com>
  • Loading branch information
flouthoc committed Aug 2, 2023
1 parent aca0600 commit a7556dd
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
14 changes: 12 additions & 2 deletions copy/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ type Options struct {
// Invalid when copying a non-multi-architecture image. That will probably
// change in the future.
EnsureCompressionVariantsExist []OptionCompressionVariant
// ForceCompressionFormat ensures that the compression algorithm set in
// DestinationCtx.CompressionFormat is used exclusively, and blobs of other
// compression algorithms are not reused.
ForceCompressionFormat bool
}

// OptionCompressionVariant allows to supply information about
Expand Down Expand Up @@ -269,8 +273,11 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
if len(options.EnsureCompressionVariantsExist) > 0 {
return nil, fmt.Errorf("EnsureCompressionVariantsExist is not implemented when not creating a multi-architecture image")
}
if (options.DestinationCtx == nil || options.DestinationCtx.CompressionFormat == nil) && options.ForceCompressionFormat {
return nil, fmt.Errorf("cannot use ForceCompressionFormat with undefined default compression format")
}
// The simple case: just copy a single image.
single, err := c.copySingleImage(ctx, c.unparsedToplevel, nil, copySingleImageOptions{requireCompressionFormatMatch: false})
single, err := c.copySingleImage(ctx, c.unparsedToplevel, nil, copySingleImageOptions{requireCompressionFormatMatch: c.options.ForceCompressionFormat})
if err != nil {
return nil, err
}
Expand All @@ -279,6 +286,9 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
if len(options.EnsureCompressionVariantsExist) > 0 {
return nil, fmt.Errorf("EnsureCompressionVariantsExist is not implemented when not creating a multi-architecture image")
}
if (options.DestinationCtx == nil || options.DestinationCtx.CompressionFormat == nil) && options.ForceCompressionFormat {
return nil, fmt.Errorf("cannot use ForceCompressionFormat with undefined default compression format")
}
// This is a manifest list, and we weren't asked to copy multiple images. Choose a single image that
// matches the current system to copy, and copy it.
mfest, manifestType, err := c.unparsedToplevel.Manifest(ctx)
Expand All @@ -295,7 +305,7 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef,
}
logrus.Debugf("Source is a manifest list; copying (only) instance %s for current system", instanceDigest)
unparsedInstance := image.UnparsedInstance(rawSource, &instanceDigest)
single, err := c.copySingleImage(ctx, unparsedInstance, nil, copySingleImageOptions{requireCompressionFormatMatch: false})
single, err := c.copySingleImage(ctx, unparsedInstance, nil, copySingleImageOptions{requireCompressionFormatMatch: c.options.ForceCompressionFormat})
if err != nil {
return nil, fmt.Errorf("copying system image from manifest list: %w", err)
}
Expand Down
15 changes: 10 additions & 5 deletions copy/multiple.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ const (
)

type instanceCopy struct {
op instanceCopyKind
sourceDigest digest.Digest
op instanceCopyKind
sourceDigest digest.Digest
forceCompressionFormat bool

// Fields which can be used by callers when operation
// is `instanceCopyClone`
Expand Down Expand Up @@ -122,9 +123,13 @@ func prepareInstanceCopies(list internalManifest.List, instanceDigests []digest.
if err != nil {
return res, fmt.Errorf("getting details for instance %s: %w", instanceDigest, err)
}
if (options.DestinationCtx == nil || options.DestinationCtx.CompressionFormat == nil) && options.ForceCompressionFormat {
return res, fmt.Errorf("cannot use ForceCompressionFormat with undefined default compression")
}
res = append(res, instanceCopy{
op: instanceCopyCopy,
sourceDigest: instanceDigest,
op: instanceCopyCopy,
sourceDigest: instanceDigest,
forceCompressionFormat: options.ForceCompressionFormat,
})
platform := platformV1ToPlatformComparable(instanceDetails.ReadOnly.Platform)
compressionList := compressionsByPlatform[platform]
Expand Down Expand Up @@ -230,7 +235,7 @@ func (c *copier) copyMultipleImages(ctx context.Context) (copiedManifest []byte,
logrus.Debugf("Copying instance %s (%d/%d)", instance.sourceDigest, i+1, len(instanceCopyList))
c.Printf("Copying image %s (%d/%d)\n", instance.sourceDigest, i+1, len(instanceCopyList))
unparsedInstance := image.UnparsedInstance(c.rawSource, &instanceCopyList[i].sourceDigest)
updated, err := c.copySingleImage(ctx, unparsedInstance, &instanceCopyList[i].sourceDigest, copySingleImageOptions{requireCompressionFormatMatch: false})
updated, err := c.copySingleImage(ctx, unparsedInstance, &instanceCopyList[i].sourceDigest, copySingleImageOptions{requireCompressionFormatMatch: instance.forceCompressionFormat})
if err != nil {
return nil, fmt.Errorf("copying image %d/%d from manifest list: %w", i+1, len(instanceCopyList), err)
}
Expand Down
5 changes: 4 additions & 1 deletion copy/multiple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestPrepareCopyInstancesforInstanceCopyCopy(t *testing.T) {

for _, instance := range sourceInstances {
compare = append(compare, instanceCopy{op: instanceCopyCopy,
sourceDigest: instance})
sourceDigest: instance, forceCompressionFormat: false})
}
assert.Equal(t, instancesToCopy, compare)

Expand All @@ -42,6 +42,9 @@ func TestPrepareCopyInstancesforInstanceCopyCopy(t *testing.T) {
compare = []instanceCopy{{op: instanceCopyCopy,
sourceDigest: sourceInstances[1]}}
assert.Equal(t, instancesToCopy, compare)

_, err = prepareInstanceCopies(list, sourceInstances, &Options{Instances: []digest.Digest{sourceInstances[1]}, ImageListSelection: CopySpecificImages, ForceCompressionFormat: true})
require.EqualError(t, err, "cannot use ForceCompressionFormat with undefined default compression")
}

// Test `instanceCopyClone` cases.
Expand Down

0 comments on commit a7556dd

Please sign in to comment.