filters: use new FilterID function from c/common

Remove code duplication and use the new FilterID function from
c/common. Also remove the duplicated ComputeUntilTimestamp in podman use
the one from c/common as well.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2023-06-13 16:41:38 +02:00
parent 63f5116ad3
commit 8a90765b90
6 changed files with 23 additions and 124 deletions

View File

@ -5,7 +5,6 @@ import (
"io" "io"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/containers/storage/pkg/regexp"
) )
var ( var (
@ -18,9 +17,6 @@ var (
// This must NOT be changed from outside of Libpod. It should be a // This must NOT be changed from outside of Libpod. It should be a
// constant, but Go won't let us do that. // constant, but Go won't let us do that.
NameRegex = types.NameRegex NameRegex = types.NameRegex
// NotHexRegex is a regular expression to check if a string is
// a hexadecimal string.
NotHexRegex = regexp.Delayed(`[^0-9a-fA-F]`)
// RegexError is thrown in presence of an invalid container/pod name. // RegexError is thrown in presence of an invalid container/pod name.
RegexError = types.RegexError RegexError = types.RegexError
) )

View File

@ -3,16 +3,14 @@ package filters
import ( import (
"errors" "errors"
"fmt" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/containers/common/pkg/filters" "github.com/containers/common/pkg/filters"
cutil "github.com/containers/common/pkg/util" "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/util"
) )
// GenerateContainerFilterFuncs return ContainerFilter functions based of filter. // GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
@ -20,18 +18,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
switch filter { switch filter {
case "id": case "id":
return func(c *libpod.Container) bool { return func(c *libpod.Container) bool {
for _, want := range filterValues { return util.FilterID(c.ID(), filterValues)
isRegex := define.NotHexRegex.MatchString(want)
if isRegex {
match, err := regexp.MatchString(want, c.ID())
if err == nil && match {
return true
}
} else if strings.HasPrefix(c.ID(), strings.ToLower(want)) {
return true
}
}
return false
}, nil }, nil
case "label": case "label":
// we have to match that all given labels exits on that container // we have to match that all given labels exits on that container
@ -270,7 +257,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
return false return false
} }
for _, net := range networks { for _, net := range networks {
if cutil.StringInSlice(net, inputNetNames) { if util.StringInSlice(net, inputNetNames) {
return true return true
} }
} }
@ -324,7 +311,7 @@ func GeneratePruneContainerFilterFuncs(filter string, filterValues []string, r *
} }
func prepareUntilFilterFunc(filterValues []string) (func(container *libpod.Container) bool, error) { func prepareUntilFilterFunc(filterValues []string) (func(container *libpod.Container) bool, error) {
until, err := util.ComputeUntilTimestamp(filterValues) until, err := filters.ComputeUntilTimestamp(filterValues)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -3,15 +3,13 @@ package filters
import ( import (
"errors" "errors"
"fmt" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
"github.com/containers/common/pkg/filters" "github.com/containers/common/pkg/filters"
cutil "github.com/containers/common/pkg/util" "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/util"
) )
// GeneratePodFilterFunc takes a filter and filtervalue (key, value) // GeneratePodFilterFunc takes a filter and filtervalue (key, value)
@ -26,26 +24,11 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
if err != nil { if err != nil {
return false return false
} }
for _, want := range filterValues {
isRegex := define.NotHexRegex.MatchString(want)
if isRegex {
re, err := regexp.Compile(want)
if err != nil {
return false
}
for _, id := range ctrIds { for _, id := range ctrIds {
if re.MatchString(id) { if util.FilterID(id, filterValues) {
return true return true
} }
} }
} else {
for _, id := range ctrIds {
if strings.HasPrefix(id, strings.ToLower(want)) {
return true
}
}
}
}
return false return false
}, nil }, nil
case "ctr-names": case "ctr-names":
@ -78,7 +61,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
}, nil }, nil
case "ctr-status": case "ctr-status":
for _, filterValue := range filterValues { for _, filterValue := range filterValues {
if !cutil.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) {
return nil, fmt.Errorf("%s is not a valid status", filterValue) return nil, fmt.Errorf("%s is not a valid status", filterValue)
} }
} }
@ -107,18 +90,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
}, nil }, nil
case "id": case "id":
return func(p *libpod.Pod) bool { return func(p *libpod.Pod) bool {
for _, want := range filterValues { return util.FilterID(p.ID(), filterValues)
isRegex := define.NotHexRegex.MatchString(want)
if isRegex {
match, err := regexp.MatchString(want, p.ID())
if err == nil && match {
return true
}
} else if strings.HasPrefix(p.ID(), strings.ToLower(want)) {
return true
}
}
return false
}, nil }, nil
case "name": case "name":
return func(p *libpod.Pod) bool { return func(p *libpod.Pod) bool {
@ -126,7 +98,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
}, nil }, nil
case "status": case "status":
for _, filterValue := range filterValues { for _, filterValue := range filterValues {
if !cutil.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) {
return nil, fmt.Errorf("%s is not a valid pod status", filterValue) return nil, fmt.Errorf("%s is not a valid pod status", filterValue)
} }
} }
@ -149,7 +121,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
}, nil }, nil
case "until": case "until":
return func(p *libpod.Pod) bool { return func(p *libpod.Pod) bool {
until, err := util.ComputeUntilTimestamp(filterValues) until, err := filters.ComputeUntilTimestamp(filterValues)
if err != nil { if err != nil {
return false return false
} }
@ -182,7 +154,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
return false return false
} }
for _, net := range networks { for _, net := range networks {
if cutil.StringInSlice(net, inputNetNames) { if util.StringInSlice(net, inputNetNames) {
return true return true
} }
} }

View File

@ -6,14 +6,13 @@ import (
"regexp" "regexp"
"strings" "strings"
pruneFilters "github.com/containers/common/pkg/filters" "github.com/containers/common/pkg/filters"
"github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/pkg/util"
) )
func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) { func GenerateVolumeFilters(filtersValues url.Values) ([]libpod.VolumeFilter, error) {
var vf []libpod.VolumeFilter var vf []libpod.VolumeFilter
for filter, v := range filters { for filter, v := range filtersValues {
for _, val := range v { for _, val := range v {
switch filter { switch filter {
case "name": case "name":
@ -37,12 +36,12 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
case "label": case "label":
filter := val filter := val
vf = append(vf, func(v *libpod.Volume) bool { vf = append(vf, func(v *libpod.Volume) bool {
return pruneFilters.MatchLabelFilters([]string{filter}, v.Labels()) return filters.MatchLabelFilters([]string{filter}, v.Labels())
}) })
case "label!": case "label!":
filter := val filter := val
vf = append(vf, func(v *libpod.Volume) bool { vf = append(vf, func(v *libpod.Volume) bool {
return !pruneFilters.MatchLabelFilters([]string{filter}, v.Labels()) return !filters.MatchLabelFilters([]string{filter}, v.Labels())
}) })
case "opt": case "opt":
filterArray := strings.SplitN(val, "=", 2) filterArray := strings.SplitN(val, "=", 2)
@ -98,20 +97,20 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
return vf, nil return vf, nil
} }
func GeneratePruneVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) { func GeneratePruneVolumeFilters(filtersValues url.Values) ([]libpod.VolumeFilter, error) {
var vf []libpod.VolumeFilter var vf []libpod.VolumeFilter
for filter, v := range filters { for filter, v := range filtersValues {
for _, val := range v { for _, val := range v {
filterVal := val filterVal := val
switch filter { switch filter {
case "label": case "label":
vf = append(vf, func(v *libpod.Volume) bool { vf = append(vf, func(v *libpod.Volume) bool {
return pruneFilters.MatchLabelFilters([]string{filterVal}, v.Labels()) return filters.MatchLabelFilters([]string{filterVal}, v.Labels())
}) })
case "label!": case "label!":
filter := val filter := val
vf = append(vf, func(v *libpod.Volume) bool { vf = append(vf, func(v *libpod.Volume) bool {
return !pruneFilters.MatchLabelFilters([]string{filter}, v.Labels()) return !filters.MatchLabelFilters([]string{filter}, v.Labels())
}) })
case "until": case "until":
f, err := createUntilFilterVolumeFunction(filterVal) f, err := createUntilFilterVolumeFunction(filterVal)
@ -128,7 +127,7 @@ func GeneratePruneVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, erro
} }
func createUntilFilterVolumeFunction(filter string) (libpod.VolumeFilter, error) { func createUntilFilterVolumeFunction(filter string) (libpod.VolumeFilter, error) {
until, err := util.ComputeUntilTimestamp([]string{filter}) until, err := filters.ComputeUntilTimestamp([]string{filter})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -2,32 +2,11 @@ package util
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
"time"
"github.com/containers/podman/v4/pkg/timetype"
) )
// ComputeUntilTimestamp extracts until timestamp from filters
func ComputeUntilTimestamp(filterValues []string) (time.Time, error) {
invalid := time.Time{}
if len(filterValues) != 1 {
return invalid, errors.New("specify exactly one timestamp for until")
}
ts, err := timetype.GetTimestamp(filterValues[0], time.Now())
if err != nil {
return invalid, err
}
seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
if err != nil {
return invalid, err
}
return time.Unix(seconds, nanoseconds), nil
}
// filtersFromRequests extracts the "filters" parameter from the specified // filtersFromRequests extracts the "filters" parameter from the specified
// http.Request. The parameter can either be a `map[string][]string` as done // http.Request. The parameter can either be a `map[string][]string` as done
// in new versions of Docker and libpod, or a `map[string]map[string]bool` as // in new versions of Docker and libpod, or a `map[string]map[string]bool` as

View File

@ -79,37 +79,3 @@ func TestMatchLabelFilters(t *testing.T) {
}) })
} }
} }
func TestComputeUntilTimestamp(t *testing.T) {
tests := []struct {
name string
args []string
wantErr bool
}{
{
name: "Return error when more values in list",
args: []string{"5h", "6s"},
wantErr: true,
},
{
name: "Return error when invalid time",
args: []string{"invalidTime"},
wantErr: true,
},
{
name: "Do not return error when correct time format supplied",
args: []string{"44m"},
wantErr: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
_, err := ComputeUntilTimestamp(tt.args)
if (err != nil) != tt.wantErr {
t.Errorf("ComputeUntilTimestamp() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}