Skip to content

Commit 78c8c08

Browse files
committed
Improve image ID lookup for pulled images
- Use the image's repo, not just the digest, to be more precise when zstd:chunked ambiguities are involved - Remove the multi-platform lookup code, it is never used Signed-off-by: Miloslav Trmač <[email protected]>
1 parent d7dfa8b commit 78c8c08

File tree

1 file changed

+23
-38
lines changed

1 file changed

+23
-38
lines changed

libimage/pull.go

Lines changed: 23 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"github.com/containers/image/v5/transports/alltransports"
2626
"github.com/containers/image/v5/types"
2727
"github.com/containers/storage"
28-
digest "github.com/opencontainers/go-digest"
2928
ociSpec "github.com/opencontainers/image-spec/specs-go/v1"
3029
"github.com/sirupsen/logrus"
3130
)
@@ -457,52 +456,38 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
457456
return pulledIDs, nil
458457
}
459458

460-
// imageIDForManifest() parses the manifest of the copied image and then looks
461-
// up the ID of the matching image. There's a small slice of time, between
462-
// when we copy the image into local storage and when we go to look for it
463-
// using the name that we gave it when we copied it, when the name we wanted to
464-
// assign to the image could have been moved, but the image's ID will remain
465-
// the same until it is deleted.
466-
func (r *Runtime) imageIDForManifest(manifestBytes []byte, sys *types.SystemContext) (string, error) {
467-
var imageDigest digest.Digest
468-
manifestType := manifest.GuessMIMEType(manifestBytes)
469-
if manifest.MIMETypeIsMultiImage(manifestType) {
470-
list, err := manifest.ListFromBlob(manifestBytes, manifestType)
471-
if err != nil {
472-
return "", fmt.Errorf("parsing manifest list: %w", err)
473-
}
474-
d, err := list.ChooseInstance(sys)
475-
if err != nil {
476-
return "", fmt.Errorf("choosing instance from manifest list: %w", err)
477-
}
478-
imageDigest = d
479-
} else {
480-
d, err := manifest.Digest(manifestBytes)
481-
if err != nil {
482-
return "", errors.New("digesting manifest")
483-
}
484-
imageDigest = d
459+
// imageIDForPulledImage makes a best-effort guess at an image ID for
460+
// a just-pulled image written to destName, where the pull returned manifestBytes
461+
func (r *Runtime) imageIDForPulledImage(destName reference.Named, manifestBytes []byte) (string, error) {
462+
// The caller, copySingleImageFromRegistry, never triggers a multi-platform copy, so manifestBytes
463+
// is always a single-platform manifest instance.
464+
manifestDigest, err := manifest.Digest(manifestBytes)
465+
if err != nil {
466+
return "", err
485467
}
486-
images, err := r.store.ImagesByDigest(imageDigest)
468+
destDigestedName, err := reference.WithDigest(reference.TrimNamed(destName), manifestDigest)
487469
if err != nil {
488-
return "", fmt.Errorf("listing images by manifest digest: %w", err)
470+
return "", err
489471
}
490-
491-
// If you have additionStores defined and the same image stored in
492-
// both storage and additional store, it can be output twice.
493-
//
494-
// Worse, with zstd:chunked partial pulls, the same image can have several
472+
storeRef, err := storageTransport.Transport.NewStoreReference(r.store, destDigestedName, "")
473+
if err != nil {
474+
return "", err
475+
}
476+
// With zstd:chunked partial pulls, the same image can have several
495477
// different IDs, depending on which layers of the image were pulled using the
496478
// partial pull (are identified by TOC, not by uncompressed digest).
497479
//
498480
// At this point, from just the manifest digest, we can’t tell which image
499481
// is the one that was actually pulled. (They should all have the same contents
500482
// unless the image author is malicious.)
501-
// So just return the first matching image ID.
502-
if len(images) == 0 {
503-
return "", fmt.Errorf("identifying new image by manifest digest: %w", storage.ErrImageUnknown)
483+
//
484+
// FIXME: To return an accurate value, c/image would need to return the image ID,
485+
// not just manifestBytes.
486+
_, image, err := storageTransport.ResolveReference(storeRef)
487+
if err != nil {
488+
return "", fmt.Errorf("looking up a just-pulled image: %w", err)
504489
}
505-
return images[0].ID, nil
490+
return image.ID, nil
506491
}
507492

508493
// copySingleImageFromRegistry pulls the specified, possibly unqualified, name
@@ -702,7 +687,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
702687
}
703688

704689
logrus.Debugf("Pulled candidate %s successfully", candidateString)
705-
ids, err := r.imageIDForManifest(manifestBytes, sys)
690+
ids, err := r.imageIDForPulledImage(candidate.Value, manifestBytes)
706691
if err != nil {
707692
return "", err
708693
}

0 commit comments

Comments
 (0)