Skip to content

Commit

Permalink
move prune filter parsing to common
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
cdoern committed Jul 11, 2022
1 parent dd1c331 commit af4a15d
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 9 deletions.
9 changes: 5 additions & 4 deletions libimage/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -309,13 +310,13 @@ 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
return filtersPkg.MatchLabelFilters([]string{value}, labels, inverse), nil
}
}

Expand Down
7 changes: 5 additions & 2 deletions libnetwork/util/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,12 @@ func createPruneFilterFuncs(key string, filterValues []string) (types.FilterFunc
case "label":
// matches all labels
return func(net types.Network) bool {
return filters.MatchLabelFilters(filterValues, net.Labels)
return filters.MatchLabelFilters(filterValues, net.Labels, false)
}, nil
case "label!":
return func(net types.Network) bool {
return filters.MatchLabelFilters(filterValues, net.Labels, true)
}, nil

case "until":
until, err := filters.ComputeUntilTimestamp(filterValues)
if err != nil {
Expand Down
18 changes: 16 additions & 2 deletions pkg/filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"path/filepath"
"strings"
"time"

Expand Down Expand Up @@ -101,7 +102,7 @@ func PrepareFilters(r *http.Request) (map[string][]string, error) {
}

// MatchLabelFilters matches labels and returns true if they are valid
func MatchLabelFilters(filterValues []string, labels map[string]string) bool {
func MatchLabelFilters(filterValues []string, labels map[string]string, inverse bool) bool {
outer:
for _, filterValue := range filterValues {
filterArray := strings.SplitN(filterValue, "=", 2)
Expand All @@ -112,11 +113,24 @@ outer:
filterValue = ""
}
for labelKey, labelValue := range labels {
if labelKey == filterKey && (filterValue == "" || labelValue == filterValue) {
if inverse && ((labelKey != filterKey) || !matchPattern(filterKey, labelKey)) && (filterValue == "" || labelValue == filterValue) {
continue outer
} else if (labelKey == filterKey || matchPattern(filterKey, labelKey)) && (filterValue == "" || labelValue == filterValue) {
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
}
2 changes: 1 addition & 1 deletion pkg/filters/filters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestMatchLabelFilters(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if got := MatchLabelFilters(tt.args.filterValues, tt.args.labels); got != tt.want {
if got := MatchLabelFilters(tt.args.filterValues, tt.args.labels, false); got != tt.want {
t.Errorf("MatchLabelFilters() = %v, want %v", got, tt.want)
}
})
Expand Down

0 comments on commit af4a15d

Please sign in to comment.