Skip to content

Commit

Permalink
Fix ID and Digest filters
Browse files Browse the repository at this point in the history
The id and digest filters for podman images was broken
as it would only match on the full ID or Digest, so when
users would give a substring of either not results would be
given even though there were matches.
Fix to check on prefix now instead.

Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
  • Loading branch information
umohnani8 committed Sep 28, 2023
1 parent 2adb1b5 commit 351d2f8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 8 deletions.
10 changes: 4 additions & 6 deletions libimage/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
filtersPkg "github.com/containers/common/pkg/filters"
"github.com/containers/common/pkg/timetype"
"github.com/containers/image/v5/docker/reference"
"github.com/opencontainers/go-digest"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -394,18 +393,17 @@ func filterDangling(ctx context.Context, value bool, tree *layerTree) filterFunc
// filterID creates an image-ID filter for matching the specified value.
func filterID(value string) filterFunc {
return func(img *Image) (bool, error) {
return img.ID() == value, nil
return strings.HasPrefix(img.ID(), value), nil
}
}

// filterDigest creates a digest filter for matching the specified value.
func filterDigest(value string) (filterFunc, error) {
d, err := digest.Parse(value)
if err != nil {
return nil, fmt.Errorf("invalid value %q for digest filter: %w", value, err)
if !strings.HasPrefix(value, "sha256:") {
return nil, fmt.Errorf("invalid value %q for digest filter", value)
}
return func(img *Image) (bool, error) {
return img.hasDigest(d), nil
return img.containsDigestPrefix(value), nil
}, nil
}

Expand Down
43 changes: 41 additions & 2 deletions libimage/filters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ func TestFilterDigest(t *testing.T) {
matches int
id string
}{
{string(busybox.Digest()), 1, busybox.ID()},
{string(alpine.Digest()), 1, alpine.ID()},
{string(busybox.Digest()[:10]), 1, busybox.ID()},
{string(alpine.Digest()[:10]), 1, alpine.ID()},
} {
listOptions := &ListImagesOptions{
Filters: []string{"digest=" + test.filter},
Expand All @@ -130,6 +130,45 @@ func TestFilterDigest(t *testing.T) {
assert.Error(t, err)
}

func TestFilterID(t *testing.T) {
busyboxLatest := "quay.io/libpod/busybox:latest"
alpineLatest := "quay.io/libpod/alpine:latest"

runtime, cleanup := testNewRuntime(t)
defer cleanup()
ctx := context.Background()

pullOptions := &PullOptions{}
pullOptions.Writer = os.Stdout

pulledImages, err := runtime.Pull(ctx, busyboxLatest, config.PullPolicyMissing, pullOptions)
require.NoError(t, err)
require.Len(t, pulledImages, 1)
busybox := pulledImages[0]

pulledImages, err = runtime.Pull(ctx, alpineLatest, config.PullPolicyMissing, pullOptions)
require.NoError(t, err)
require.Len(t, pulledImages, 1)
alpine := pulledImages[0]

for _, test := range []struct {
filter string
matches int
id string
}{
{busybox.ID()[:5], 1, busybox.ID()},
{alpine.ID()[:5], 1, alpine.ID()},
} {
listOptions := &ListImagesOptions{
Filters: []string{"id=" + test.filter},
}
listedImages, err := runtime.ListImages(ctx, nil, listOptions)
require.NoError(t, err, "%v", test)
require.Len(t, listedImages, test.matches, "%s -> %v", test.filter, listedImages)
require.Equal(t, listedImages[0].ID(), test.id)
}
}

func TestFilterManifest(t *testing.T) {
busyboxLatest := "quay.io/libpod/busybox:latest"
alpineLatest := "quay.io/libpod/alpine:latest"
Expand Down
11 changes: 11 additions & 0 deletions libimage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,17 @@ func (i *Image) hasDigest(wantedDigest digest.Digest) bool {
return false
}

// containsDigestPrefix returns whether the specified value matches any digest of the
// image. It checks for the prefix and not a full match.
func (i *Image) containsDigestPrefix(wantedDigestPrefix string) bool {
for _, d := range i.Digests() {
if strings.HasPrefix(d.String(), wantedDigestPrefix) {
return true
}
}
return false
}

// IsReadOnly returns whether the image is set read only.
func (i *Image) IsReadOnly() bool {
return i.storageImage.ReadOnly
Expand Down

0 comments on commit 351d2f8

Please sign in to comment.