From f08f3162f4ae92eb2d2d75b378d92722265dc618 Mon Sep 17 00:00:00 2001 From: Charlie Doern Date: Mon, 11 Jul 2022 13:34:01 -0400 Subject: [PATCH] move prune filter parsing to common there was some eerily similar code in c/common and in podman for creating filter functions for various types. Move some of it here and add support for the label!= filter in libimage and libnetwork that basically creates the inverse function of label= after this merges, will file a PR with the fix for containers within podman as well there is already a label!= test in libimage/filters_test. Libimage somehow lets this syntax slide even though it does not actually imact anything in podman see containers/podman#14182 Signed-off-by: Charlie Doern --- libimage/filters.go | 13 +++++++++---- libnetwork/util/filters.go | 5 ++++- pkg/filters/filters.go | 18 ++++++++++++++++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/libimage/filters.go b/libimage/filters.go index f9f73f527..ba926f437 100644 --- a/libimage/filters.go +++ b/libimage/filters.go @@ -159,8 +159,9 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp filter = filterIntermediate(ctx, intermediate, t) case "label": - filter = filterLabel(ctx, value) - + filter = filterLabel(ctx, value, false) + case "label!": + filter = filterLabel(ctx, value, true) case "readonly": readOnly, err := r.bool(duplicate, key, value) if err != nil { @@ -309,13 +310,17 @@ func filterReferences(value string) filterFunc { } // filterLabel creates a label for matching the specified value. -func filterLabel(ctx context.Context, value string) filterFunc { +func filterLabel(ctx context.Context, value string, inverse bool) filterFunc { return func(img *Image) (bool, error) { labels, err := img.Labels(ctx) if err != nil { return false, err } - return filtersPkg.MatchLabelFilters([]string{value}, labels), nil + val := filtersPkg.MatchLabelFilters([]string{value}, labels) + if inverse { + return !val, nil + } + return val, nil } } diff --git a/libnetwork/util/filters.go b/libnetwork/util/filters.go index 58d79d25b..af2af3b3d 100644 --- a/libnetwork/util/filters.go +++ b/libnetwork/util/filters.go @@ -65,7 +65,10 @@ func createPruneFilterFuncs(key string, filterValues []string) (types.FilterFunc return func(net types.Network) bool { return filters.MatchLabelFilters(filterValues, net.Labels) }, nil - + case "label!": + return func(net types.Network) bool { + return !filters.MatchLabelFilters(filterValues, net.Labels) + }, nil case "until": until, err := filters.ComputeUntilTimestamp(filterValues) if err != nil { diff --git a/pkg/filters/filters.go b/pkg/filters/filters.go index 53650efc9..314b0c419 100644 --- a/pkg/filters/filters.go +++ b/pkg/filters/filters.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "path/filepath" "strings" "time" @@ -112,11 +113,24 @@ outer: filterValue = "" } for labelKey, labelValue := range labels { - if labelKey == filterKey && (filterValue == "" || labelValue == filterValue) { - continue outer + if filterValue == "" || labelValue == filterValue { + if labelKey == filterKey || matchPattern(filterKey, labelKey) { + continue outer + } } } return false } return true } + +func matchPattern(pattern string, value string) bool { + if strings.Contains(pattern, "*") { + filter := fmt.Sprintf("*%s*", pattern) + filter = strings.ReplaceAll(filter, string(filepath.Separator), "|") + newName := strings.ReplaceAll(value, string(filepath.Separator), "|") + match, _ := filepath.Match(filter, newName) + return match + } + return false +}