Skip to content

Commit

Permalink
libimage: enforce "latest" tag when looking up images
Browse files Browse the repository at this point in the history
Make sure to enforce the "latest" tag when looking up images in the
local storage.  Also make sure that digested short-names are subject
to the extended digest lookups.

Context: containers/podman/issues/11964
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
  • Loading branch information
vrothberg committed Nov 22, 2021
1 parent d24a196 commit 196b5aa
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 31 deletions.
7 changes: 4 additions & 3 deletions libimage/image.go
Expand Up @@ -624,8 +624,7 @@ func (i *Image) NamedRepoTags() ([]reference.Named, error) {
}

// inRepoTags looks for the specified name/tag pair in the image's repo tags.
// Note that tag may be empty.
func (i *Image) inRepoTags(name, tag string) (reference.Named, error) {
func (i *Image) inRepoTags(namedTagged reference.NamedTagged) (reference.Named, error) {
repoTags, err := i.NamedRepoTags()
if err != nil {
return nil, err
Expand All @@ -636,8 +635,10 @@ func (i *Image) inRepoTags(name, tag string) (reference.Named, error) {
return nil, err
}

name := namedTagged.Name()
tag := namedTagged.Tag()
for _, pair := range pairs {
if tag != "" && tag != pair.Tag {
if tag != pair.Tag {
continue
}
if !strings.HasSuffix(pair.Name, name) {
Expand Down
21 changes: 13 additions & 8 deletions libimage/pull_test.go
Expand Up @@ -85,35 +85,40 @@ func TestPullPlatforms(t *testing.T) {
localArch := goruntime.GOARCH
localOS := goruntime.GOOS

pulledImages, err := runtime.Pull(ctx, "busybox", config.PullPolicyAlways, pullOptions)
withTag := "busybox:musl"

pulledImages, err := runtime.Pull(ctx, withTag, config.PullPolicyAlways, pullOptions)
require.NoError(t, err, "pull busybox")
require.Len(t, pulledImages, 1)

image, _, err := runtime.LookupImage("busybox", nil)
image, _, err := runtime.LookupImage(withTag, nil)
require.NoError(t, err, "lookup busybox")
require.NotNil(t, image, "lookup busybox")

image, _, err = runtime.LookupImage("busybox", &LookupImageOptions{Architecture: localArch})
_, _, err = runtime.LookupImage("busybox", nil)
require.Error(t, err, "untagged image resolves to non-existent :latest")

image, _, err = runtime.LookupImage(withTag, &LookupImageOptions{Architecture: localArch})
require.NoError(t, err, "lookup busybox - by local arch")
require.NotNil(t, image, "lookup busybox - by local arch")

image, _, err = runtime.LookupImage("busybox", &LookupImageOptions{OS: localOS})
image, _, err = runtime.LookupImage(withTag, &LookupImageOptions{OS: localOS})
require.NoError(t, err, "lookup busybox - by local arch")
require.NotNil(t, image, "lookup busybox - by local arch")

_, _, err = runtime.LookupImage("busybox", &LookupImageOptions{Architecture: "bogus"})
_, _, err = runtime.LookupImage(withTag, &LookupImageOptions{Architecture: "bogus"})
require.Error(t, err, "lookup busybox - bogus arch")

_, _, err = runtime.LookupImage("busybox", &LookupImageOptions{OS: "bogus"})
_, _, err = runtime.LookupImage(withTag, &LookupImageOptions{OS: "bogus"})
require.Error(t, err, "lookup busybox - bogus OS")

pullOptions.Architecture = "arm"
pulledImages, err = runtime.Pull(ctx, "busybox", config.PullPolicyAlways, pullOptions)
pulledImages, err = runtime.Pull(ctx, withTag, config.PullPolicyAlways, pullOptions)
require.NoError(t, err, "pull busybox - arm")
require.Len(t, pulledImages, 1)
pullOptions.Architecture = ""

image, _, err = runtime.LookupImage("busybox", &LookupImageOptions{Architecture: "arm"})
image, _, err = runtime.LookupImage(withTag, &LookupImageOptions{Architecture: "arm"})
require.NoError(t, err, "lookup busybox - by arm")
require.NotNil(t, image, "lookup busybox - by local arch")
}
36 changes: 16 additions & 20 deletions libimage/runtime.go
Expand Up @@ -389,16 +389,17 @@ func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, options *LookupIm
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)
}
ref, err := reference.Parse(name)
if err != nil {
return nil, "", err
}
named, isNamed := ref.(reference.Named)
if !isNamed {
return nil, "", errors.Wrap(storage.ErrImageUnknown, name)
}

digested, isDigested := named.(reference.Digested)
if isDigested {
logrus.Debug("Looking for image with matching recorded digests")
digest := digested.Digest()
for _, image := range allImages {
Expand All @@ -408,22 +409,17 @@ func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, options *LookupIm
}
}
}

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]
if !shortnames.IsShortName(name) {
return nil, "", errors.Wrap(storage.ErrImageUnknown, name)
}

named = reference.TagNameOnly(named) // Make sure to add ":latest" if needed
namedTagged, _ := named.(reference.NamedTagged)
for _, image := range allImages {
named, err := image.inRepoTags(repo, tag)
named, err := image.inRepoTags(namedTagged)
if err != nil {
return nil, "", err
}
Expand Down

0 comments on commit 196b5aa

Please sign in to comment.