diff --git a/libimage/image_test.go b/libimage/image_test.go index bf3ea4083..d2761fad9 100644 --- a/libimage/image_test.go +++ b/libimage/image_test.go @@ -219,6 +219,24 @@ func TestTag(t *testing.T) { require.True(t, errors.Cause(err) == errTagDigest, "check for specific digest error") } +func TestLookupWithoutTag(t *testing.T) { + // Regression test for github.com/containers/podman/issues/11964. + runtime, cleanup := testNewRuntime(t) + defer cleanup() + ctx := context.Background() + + pullOptions := &PullOptions{} + pullOptions.Writer = os.Stdout + pulledImages, err := runtime.Pull(ctx, "docker.io/library/busybox:unstable", config.PullPolicyMissing, pullOptions) + require.NoError(t, err) + require.Len(t, pulledImages, 1) + + _, _, err = runtime.LookupImage("busybox", nil) + require.Error(t, err, "should not resolve to non-latest tag") + _, _, err = runtime.LookupImage("busybox:unstable", nil) + require.NoError(t, err, "should find local image") +} + func TestUntag(t *testing.T) { // Note: this will resolve pull from the GCR registry (see // testdata/registries.conf). diff --git a/libimage/runtime.go b/libimage/runtime.go index 7f25df200..a06790e33 100644 --- a/libimage/runtime.go +++ b/libimage/runtime.go @@ -282,7 +282,7 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image, } } - return r.lookupImageInDigestsAndRepoTags(originalName, options) + return r.lookupImageInDigests(originalName, options) } // lookupImageInLocalStorage looks up the specified candidate for name in the @@ -365,67 +365,31 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo return image, nil } -// lookupImageInDigestsAndRepoTags attempts to match name against any image in -// the local containers storage. If name is digested, it will be compared -// against image digests. Otherwise, it will be looked up in the repo tags. -func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, options *LookupImageOptions) (*Image, string, error) { - // Until now, we've tried very hard to find an image but now it is time - // for limbo. If the image includes a digest that we couldn't detect - // verbatim in the storage, we must have a look at all digests of all - // images. Those may change over time (e.g., via manifest lists). - // Both Podman and Buildah want us to do that dance. - allImages, err := r.ListImages(context.Background(), nil, nil) +// If name is a digested image, look at all images in the local storage and +// check whether a digest matches. +func (r *Runtime) lookupImageInDigests(name string, options *LookupImageOptions) (*Image, string, error) { + named, err := reference.ParseNormalizedNamed(name) if err != nil { return nil, "", err } - - if !shortnames.IsShortName(name) { - named, err := reference.ParseNormalizedNamed(name) - if err != nil { - return nil, "", err - } - digested, hasDigest := named.(reference.Digested) - if !hasDigest { - return nil, "", errors.Wrap(storage.ErrImageUnknown, name) - } - - logrus.Debug("Looking for image with matching recorded digests") - digest := digested.Digest() - for _, image := range allImages { - for _, d := range image.Digests() { - if d == digest { - return image, name, nil - } - } - } - + digested, hasDigest := named.(reference.Digested) + if !hasDigest { return nil, "", errors.Wrap(storage.ErrImageUnknown, name) } - // Podman compat: if we're looking for a short name but couldn't - // resolve it via the registries.conf dance, we need to look at *all* - // images and check if the name we're looking for matches a repo tag. - // Split the name into a repo/tag pair - split := strings.SplitN(name, ":", 2) - repo := split[0] - tag := "" - if len(split) == 2 { - tag = split[1] + logrus.Debug("Looking for image with matching recorded digests") + + allImages, err := r.ListImages(context.Background(), nil, nil) + if err != nil { + return nil, "", err } + + digest := digested.Digest() for _, image := range allImages { - named, err := image.inRepoTags(repo, tag) - if err != nil { - return nil, "", err - } - if named == nil { - continue - } - img, err := r.lookupImageInLocalStorage(name, named.String(), options) - if err != nil { - return nil, "", err - } - if img != nil { - return img, named.String(), err + for _, d := range image.Digests() { + if d == digest { + return image, name, nil + } } }