Add filters for image and manifest

For compatibility mode, we need to have a filter that gets rid of
manifest lists from the list of all images.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh 2021-12-14 10:19:57 -05:00
parent 9555cb154f
commit 862adf81e6
2 changed files with 71 additions and 5 deletions

View File

@ -21,10 +21,12 @@ type filterFunc func(*Image) (bool, error)
// Apply the specified filters. At least one filter of each key must apply.
func (i *Image) applyFilters(filters map[string][]filterFunc) (bool, error) {
matches := false
for key := range filters { // and
matches := false
matches = false
for _, filter := range filters[key] { // or
match, err := filter(i)
var err error
matches, err = filter(i)
if err != nil {
// Some images may have been corrupted in the
// meantime, so do an extra check and make the
@ -35,15 +37,15 @@ func (i *Image) applyFilters(filters map[string][]filterFunc) (bool, error) {
}
return false, err
}
if match {
return true, nil
if matches {
break
}
}
if !matches {
return false, nil
}
}
return false, nil
return matches, nil
}
// filterImages returns a slice of images which are passing all specified
@ -160,6 +162,14 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
}
filter = filterReadOnly(readOnly)
case "manifest":
manifest, err := r.bool(duplicate, key, value)
if err != nil {
return nil, err
}
duplicate[key] = true
filter = filterManifest(ctx, manifest)
case "reference":
filter = filterReferences(value)
@ -229,6 +239,17 @@ func (r *Runtime) bool(duplicate map[string]bool, key, value string) (bool, erro
return set, nil
}
// filterManifest filters whether or not the image is a manifest list
func filterManifest(ctx context.Context, value bool) filterFunc {
return func(img *Image) (bool, error) {
isManifestList, err := img.IsManifestList(ctx)
if err != nil {
return false, err
}
return isManifestList == value, nil
}
}
// filterReferences creates a reference filter for matching the specified value.
func filterReferences(value string) filterFunc {
return func(img *Image) (bool, error) {

View File

@ -70,3 +70,48 @@ func TestFilterReference(t *testing.T) {
require.Len(t, listedImages, test.matches, "%s -> %v", test.filter, listedImages)
}
}
func TestFilterManifest(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)
pulledImages, err = runtime.Pull(ctx, alpineLatest, config.PullPolicyMissing, pullOptions)
require.NoError(t, err)
require.Len(t, pulledImages, 1)
_, err = runtime.CreateManifestList("manifest-alpine")
require.NoError(t, err)
for _, test := range []struct {
filters []string
matches int
}{
{nil, 3},
{[]string{"manifest=false"}, 2},
{[]string{"manifest=true"}, 1},
{[]string{"reference=busybox"}, 1},
{[]string{"reference=*alpine"}, 2},
{[]string{"manifest=true", "reference=*alpine"}, 1},
{[]string{"manifest=false", "reference=*alpine"}, 1},
{[]string{"manifest=true", "reference=busybox"}, 0},
{[]string{"manifest=false", "reference=busybox"}, 1},
} {
listOptions := &ListImagesOptions{
Filters: test.filters,
}
listedImages, err := runtime.ListImages(ctx, nil, listOptions)
require.NoError(t, err, "%v", test)
require.Len(t, listedImages, test.matches, "%s -> %v", test.filters, listedImages)
}
}