From ee08c8772e96d86fc7b9657f11240774f425af39 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 libnetwork only. Libimage already supports it. after this merges, will file a PR with the fix for containers within podman as well see containers/podman#14182 Signed-off-by: Charlie Doern --- libimage/filters.go | 1 - libnetwork/util/filters.go | 5 +++- libnetwork/util/filters_test.go | 47 +++++++++++++++++++++++++++++++++ pkg/filters/filters.go | 18 +++++++++++-- 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 libnetwork/util/filters_test.go diff --git a/libimage/filters.go b/libimage/filters.go index f9f73f527..7f7211aa1 100644 --- a/libimage/filters.go +++ b/libimage/filters.go @@ -160,7 +160,6 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp case "label": filter = filterLabel(ctx, value) - case "readonly": readOnly, err := r.bool(duplicate, key, value) if err != 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/libnetwork/util/filters_test.go b/libnetwork/util/filters_test.go new file mode 100644 index 000000000..cb1e09986 --- /dev/null +++ b/libnetwork/util/filters_test.go @@ -0,0 +1,47 @@ +package util + +import "testing" + +func TestGenerateFilterFunc(t *testing.T) { + testValues := []string{ + "", + "test", + "", + } + type args struct { + keys []string + labels []string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "Match when all filters the same as labels", + args: args{ + keys: []string{"label", "label", "label"}, + labels: testValues, + }, + want: true, + }, + { + name: "Match with inverse", + args: args{ + keys: []string{"label", "label", "label!"}, + labels: testValues, + }, + want: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + for _, entry := range tt.args.keys { + if _, err := createFilterFuncs(entry, tt.args.labels); err != nil { + t.Errorf("createPruneFilterFuncs() failed on %s with entry %s: %s", tt.name, entry, err.Error()) + } + } + }) + } +} 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 +}