Skip to content

Commit cdf35b8

Browse files
committed
Reliably return the correct image ID from pull
Signed-off-by: Miloslav Trmač <[email protected]>
1 parent 8a5303a commit cdf35b8

File tree

6 files changed

+21
-51
lines changed

6 files changed

+21
-51
lines changed

libimage/copier.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ type Copier struct {
175175
// newCopier creates a Copier based on a runtime's system context.
176176
// Note that fields in options *may* overwrite the counterparts of
177177
// the specified system context. Please make sure to call `(*Copier).Close()`.
178-
func (r *Runtime) newCopier(options *CopyOptions) (*Copier, error) {
179-
return NewCopier(options, r.SystemContext())
178+
func (r *Runtime) newCopier(options *CopyOptions, reportResolvedReference *types.ImageReference) (*Copier, error) {
179+
return NewCopier(options, r.SystemContext(), reportResolvedReference)
180180
}
181181

182182
// storageAllowedPolicyScopes overrides the policy for local storage
@@ -223,7 +223,7 @@ func getDockerAuthConfig(name, passwd, creds, idToken string) (*types.DockerAuth
223223
// NewCopier creates a Copier based on a provided system context.
224224
// Note that fields in options *may* overwrite the counterparts of
225225
// the specified system context. Please make sure to call `(*Copier).Close()`.
226-
func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) {
226+
func NewCopier(options *CopyOptions, sc *types.SystemContext, reportResolvedReference *types.ImageReference) (*Copier, error) {
227227
c := Copier{extendTimeoutSocket: options.extendTimeoutSocket}
228228
sysContextCopy := *sc
229229
c.systemContext = &sysContextCopy
@@ -330,6 +330,7 @@ func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) {
330330
c.imageCopyOptions.SignBySigstorePrivateKeyFile = options.SignBySigstorePrivateKeyFile
331331
c.imageCopyOptions.SignSigstorePrivateKeyPassphrase = options.SignSigstorePrivateKeyPassphrase
332332
c.imageCopyOptions.ReportWriter = options.Writer
333+
c.imageCopyOptions.ReportResolvedReference = reportResolvedReference
333334

334335
defaultContainerConfig, err := config.Default()
335336
if err != nil {

libimage/import.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
104104
return "", err
105105
}
106106

107-
c, err := r.newCopier(&options.CopyOptions)
107+
c, err := r.newCopier(&options.CopyOptions, nil)
108108
if err != nil {
109109
return "", err
110110
}

libimage/manifest_list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma
792792
// NOTE: we're using the logic in copier to create a proper
793793
// types.SystemContext. This prevents us from having an error prone
794794
// code duplicate here.
795-
copier, err := m.image.runtime.newCopier(&options.CopyOptions)
795+
copier, err := m.image.runtime.newCopier(&options.CopyOptions, nil)
796796
if err != nil {
797797
return "", err
798798
}

libimage/pull.go

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ import (
1717
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
1818
dockerDaemonTransport "github.com/containers/image/v5/docker/daemon"
1919
"github.com/containers/image/v5/docker/reference"
20-
"github.com/containers/image/v5/manifest"
2120
ociArchiveTransport "github.com/containers/image/v5/oci/archive"
2221
ociTransport "github.com/containers/image/v5/oci/layout"
2322
"github.com/containers/image/v5/pkg/shortnames"
2423
storageTransport "github.com/containers/image/v5/storage"
24+
"github.com/containers/image/v5/transports"
2525
"github.com/containers/image/v5/transports/alltransports"
2626
"github.com/containers/image/v5/types"
2727
"github.com/containers/storage"
@@ -230,7 +230,7 @@ func nameFromAnnotations(annotations map[string]string) string {
230230
// copyFromDefault is the default copier for a number of transports. Other
231231
// transports require some specific dancing, sometimes Yoga.
232232
func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, options *CopyOptions) ([]string, error) {
233-
c, err := r.newCopier(options)
233+
c, err := r.newCopier(options, nil)
234234
if err != nil {
235235
return nil, err
236236
}
@@ -386,7 +386,7 @@ func (r *Runtime) copyFromDockerArchive(ctx context.Context, ref types.ImageRefe
386386

387387
// copyFromDockerArchiveReaderReference copies the specified readerRef from reader.
388388
func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, reader *dockerArchiveTransport.Reader, readerRef types.ImageReference, options *CopyOptions) ([]string, error) {
389-
c, err := r.newCopier(options)
389+
c, err := r.newCopier(options, nil)
390390
if err != nil {
391391
return nil, err
392392
}
@@ -456,40 +456,6 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference
456456
return pulledIDs, nil
457457
}
458458

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
467-
}
468-
destDigestedName, err := reference.WithDigest(reference.TrimNamed(destName), manifestDigest)
469-
if err != nil {
470-
return "", err
471-
}
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
477-
// different IDs, depending on which layers of the image were pulled using the
478-
// partial pull (are identified by TOC, not by uncompressed digest).
479-
//
480-
// At this point, from just the manifest digest, we can’t tell which image
481-
// is the one that was actually pulled. (They should all have the same contents
482-
// unless the image author is malicious.)
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)
489-
}
490-
return image.ID, nil
491-
}
492-
493459
// copySingleImageFromRegistry pulls the specified, possibly unqualified, name
494460
// from a registry. On successful pull it returns the ID of the image in local
495461
// storage (or, FIXME, a name/ID? that could be resolved in local storage)
@@ -632,7 +598,8 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
632598
if socketPath, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
633599
options.extendTimeoutSocket = socketPath
634600
}
635-
c, err := r.newCopier(&options.CopyOptions)
601+
var resolvedReference types.ImageReference
602+
c, err := r.newCopier(&options.CopyOptions, &resolvedReference)
636603
if err != nil {
637604
return "", err
638605
}
@@ -673,8 +640,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
673640
return "", err
674641
}
675642
}
676-
var manifestBytes []byte
677-
if manifestBytes, err = c.Copy(ctx, srcRef, destRef); err != nil {
643+
if _, err := c.Copy(ctx, srcRef, destRef); err != nil {
678644
logrus.Debugf("Error pulling candidate %s: %v", candidateString, err)
679645
pullErrors = append(pullErrors, err)
680646
continue
@@ -687,11 +653,14 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
687653
}
688654

689655
logrus.Debugf("Pulled candidate %s successfully", candidateString)
690-
ids, err := r.imageIDForPulledImage(candidate.Value, manifestBytes)
656+
if resolvedReference == nil { // resolvedReference should always be set for storageTransport destinations
657+
return "", fmt.Errorf("internal error: After pulling %s, resolvedReference is nil", candidateString)
658+
}
659+
_, image, err := storageTransport.ResolveReference(resolvedReference)
691660
if err != nil {
692-
return "", err
661+
return "", fmt.Errorf("resolving an already-resolved reference %q to the pulled image: %w", transports.ImageName(resolvedReference), err)
693662
}
694-
return ids, nil
663+
return image.ID, nil
695664
}
696665

697666
if localImage != nil && pullPolicy == config.PullPolicyNewer {

libimage/push.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options
109109
}
110110
}
111111

112-
c, err := r.newCopier(&options.CopyOptions)
112+
c, err := r.newCopier(&options.CopyOptions, nil)
113113
if err != nil {
114114
return nil, err
115115
}

libimage/save.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string
119119
return err
120120
}
121121

122-
c, err := r.newCopier(&options.CopyOptions)
122+
c, err := r.newCopier(&options.CopyOptions, nil)
123123
if err != nil {
124124
return err
125125
}
@@ -204,7 +204,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st
204204
copyOpts := options.CopyOptions
205205
copyOpts.dockerArchiveAdditionalTags = local.tags
206206

207-
c, err := r.newCopier(&copyOpts)
207+
c, err := r.newCopier(&copyOpts, nil)
208208
if err != nil {
209209
return err
210210
}

0 commit comments

Comments
 (0)