Skip to content

Commit

Permalink
copy/multiple: split how images are selected for copy
Browse files Browse the repository at this point in the history
We want copyMultipleImages to supports various methods about how a image
must be copied into a manifest list wheather its to be ignored, copied
as is, copied and modified or copied and replicated.

In order to support this is better to split it as a seperate function so
this can be unit tested.

Signed-off-by: Aditya R <[email protected]>
  • Loading branch information
flouthoc committed Mar 18, 2023
1 parent c1cc1ea commit 941cd13
Showing 1 changed file with 61 additions and 24 deletions.
85 changes: 61 additions & 24 deletions copy/multiple.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,44 @@ import (
internalManifest "github.com/containers/image/v5/internal/manifest"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/signature"
digest "github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
)

type instanceOperation int

const (
op_ignore instanceOperation = iota + 1
op_copyWithoutModification
//TODO: following states must be implemented
//op_copyAndReplicate
)

type instanceCopy struct {
digest digest.Digest
op instanceOperation
}

// instancesToCopy returns the list of digests which actually need to be copied to the new manifest list, ignoring the ones which are not needed.
func (c *copier) instancesToCopy(options *Options, list internalManifest.List) ([]instanceCopy, int) {
result := []instanceCopy{}
instanceDigests := list.Instances()
imagesToCopy := 0
for _, digest := range instanceDigests {
copyInstruction := instanceCopy{digest: digest, op: op_copyWithoutModification}
if options.ImageListSelection == CopySpecificImages &&
!slices.Contains(options.Instances, digest) {
copyInstruction.op = op_ignore
} else {
imagesToCopy++
}
result = append(result, copyInstruction)
}
return result, imagesToCopy
}

// copyMultipleImages copies some or all of an image list's instances, using
// policyContext to validate source image admissibility.
func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedToplevel *image.UnparsedImage) (copiedManifest []byte, retErr error) {
Expand Down Expand Up @@ -87,41 +120,45 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
}

// Copy each image, or just the ones we want to copy, in turn.
instanceDigests := updatedList.Instances()
/*instanceDigests := updatedList.Instances()
imagesToCopy := len(instanceDigests)
if options.ImageListSelection == CopySpecificImages {
imagesToCopy = len(options.Instances)
}
c.Printf("Copying %d of %d images in list\n", imagesToCopy, len(instanceDigests))
updates := make([]manifest.ListUpdate, len(instanceDigests))
}*/
copyInstances, imagesToCopy := c.instancesToCopy(options, updatedList)
c.Printf("Copying %d of %d images in list\n", imagesToCopy, len(copyInstances))
updates := make([]manifest.ListUpdate, len(copyInstances))
instancesCopied := 0
for i, instanceDigest := range instanceDigests {
if options.ImageListSelection == CopySpecificImages &&
!slices.Contains(options.Instances, instanceDigest) {
update, err := updatedList.Instance(instanceDigest)
for i, copyInstance := range copyInstances {
switch copyInstance.op {
case op_ignore:
update, err := updatedList.Instance(copyInstance.digest)
if err != nil {
return nil, err
}
logrus.Debugf("Skipping instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
logrus.Debugf("Skipping instance %s (%d/%d)", copyInstance.digest, i+1, len(copyInstances))
// Record the digest/size/type of the manifest that we didn't copy.
updates[i] = update
continue
case op_copyWithoutModification:
logrus.Debugf("Copying instance %s (%d/%d)", copyInstance.digest, i+1, len(copyInstances))
c.Printf("Copying image %s (%d/%d)\n", copyInstance.digest, instancesCopied+1, imagesToCopy)
unparsedInstance := image.UnparsedInstance(c.rawSource, &copyInstance.digest)
updatedManifest, updatedManifestType, updatedManifestDigest, err := c.copySingleImage(ctx, policyContext, options, unparsedToplevel, unparsedInstance, &copyInstance.digest)
if err != nil {
return nil, fmt.Errorf("copying image %d/%d from manifest list: %w", instancesCopied+1, imagesToCopy, err)
}
instancesCopied++
// Record the result of a possible conversion here.
update := manifest.ListUpdate{
Digest: updatedManifestDigest,
Size: int64(len(updatedManifest)),
MediaType: updatedManifestType,
}
updates[i] = update
default:
return nil, fmt.Errorf("invalid instance copy operation")
}
logrus.Debugf("Copying instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
c.Printf("Copying image %s (%d/%d)\n", instanceDigest, instancesCopied+1, imagesToCopy)
unparsedInstance := image.UnparsedInstance(c.rawSource, &instanceDigest)
updatedManifest, updatedManifestType, updatedManifestDigest, err := c.copySingleImage(ctx, policyContext, options, unparsedToplevel, unparsedInstance, &instanceDigest)
if err != nil {
return nil, fmt.Errorf("copying image %d/%d from manifest list: %w", instancesCopied+1, imagesToCopy, err)
}
instancesCopied++
// Record the result of a possible conversion here.
update := manifest.ListUpdate{
Digest: updatedManifestDigest,
Size: int64(len(updatedManifest)),
MediaType: updatedManifestType,
}
updates[i] = update
}

// Now reset the digest/size/types of the manifests in the list to account for any conversions that we made.
Expand Down

0 comments on commit 941cd13

Please sign in to comment.