MCPcopy Create free account
hub / github.com/containers/image / copySingleImage

Method copySingleImage

copy/single.go:63–318  ·  view source on GitHub ↗

copySingleImage copies a single (non-manifest-list) image unparsedImage, using c.policyContext to validate source image admissibility.

(ctx context.Context, unparsedImage *image.UnparsedImage, targetInstance *digest.Digest, opts copySingleImageOptions)

Source from the content-addressed store, hash-verified

61// copySingleImage copies a single (non-manifest-list) image unparsedImage, using c.policyContext to validate
62// source image admissibility.
63func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.UnparsedImage, targetInstance *digest.Digest, opts copySingleImageOptions) (copySingleImageResult, error) {
64 // The caller is handling manifest lists; this could happen only if a manifest list contains a manifest list.
65 // Make sure we fail cleanly in such cases.
66 multiImage, err := isMultiImage(ctx, unparsedImage)
67 if err != nil {
68 // FIXME FIXME: How to name a reference for the sub-image?
69 return copySingleImageResult{}, fmt.Errorf("determining manifest MIME type for %s: %w", transports.ImageName(unparsedImage.Reference()), err)
70 }
71 if multiImage {
72 return copySingleImageResult{}, fmt.Errorf("Unexpectedly received a manifest list instead of a manifest for a single image")
73 }
74
75 // Please keep this policy check BEFORE reading any other information about the image.
76 // (The multiImage check above only matches the MIME type, which we have received anyway.
77 // Actual parsing of anything should be deferred.)
78 if allowed, err := c.policyContext.IsRunningImageAllowed(ctx, unparsedImage); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
79 return copySingleImageResult{}, fmt.Errorf("Source image rejected: %w", err)
80 }
81 src, err := image.FromUnparsedImage(ctx, c.options.SourceCtx, unparsedImage)
82 if err != nil {
83 return copySingleImageResult{}, fmt.Errorf("initializing image from source %s: %w", transports.ImageName(c.rawSource.Reference()), err)
84 }
85
86 // If the destination is a digested reference, make a note of that, determine what digest value we're
87 // expecting, and check that the source manifest matches it. If the source manifest doesn't, but it's
88 // one item from a manifest list that matches it, accept that as a match.
89 destIsDigestedReference := false
90 if named := c.dest.Reference().DockerReference(); named != nil {
91 if digested, ok := named.(reference.Digested); ok {
92 destIsDigestedReference = true
93 matches, err := manifest.MatchesDigest(src.ManifestBlob, digested.Digest())
94 if err != nil {
95 return copySingleImageResult{}, fmt.Errorf("computing digest of source image's manifest: %w", err)
96 }
97 if !matches {
98 manifestList, _, err := c.unparsedToplevel.Manifest(ctx)
99 if err != nil {
100 return copySingleImageResult{}, fmt.Errorf("reading manifest from source image: %w", err)
101 }
102 matches, err = manifest.MatchesDigest(manifestList, digested.Digest())
103 if err != nil {
104 return copySingleImageResult{}, fmt.Errorf("computing digest of source image's manifest: %w", err)
105 }
106 if !matches {
107 return copySingleImageResult{}, errors.New("Digest of source image's manifest would not match destination reference")
108 }
109 }
110 }
111 }
112
113 if err := prepareImageConfigForDest(ctx, c.options.DestinationCtx, src, c.dest); err != nil {
114 return copySingleImageResult{}, err
115 }
116
117 sigs, err := c.sourceSignatures(ctx, src,
118 "Getting image source signatures",
119 "Checking if image destination supports signatures")
120 if err != nil {

Callers 2

copyMultipleImagesMethod · 0.95
ImageFunction · 0.95

Calls 15

sourceSignaturesMethod · 0.95
PrintfMethod · 0.95
copyLayersMethod · 0.95
createSignaturesMethod · 0.95
ImageNameFunction · 0.92
FromUnparsedImageFunction · 0.92
MatchesDigestFunction · 0.92
isMultiImageFunction · 0.85

Tested by

no test coverage detected