diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/filters/containers.go | 163 | ||||
-rw-r--r-- | libpod/filters/pods.go | 97 |
2 files changed, 163 insertions, 97 deletions
diff --git a/libpod/filters/containers.go b/libpod/filters/containers.go index da1b5b263..2520c4f30 100644 --- a/libpod/filters/containers.go +++ b/libpod/filters/containers.go @@ -1,7 +1,6 @@ package lpfilters import ( - "regexp" "strconv" "strings" "time" @@ -11,101 +10,133 @@ import ( "github.com/containers/podman/v2/pkg/timetype" "github.com/containers/podman/v2/pkg/util" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) // GenerateContainerFilterFuncs return ContainerFilter functions based of filter. -func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) { +func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) { switch filter { case "id": + // we only have to match one ID return func(c *libpod.Container) bool { - return strings.Contains(c.ID(), filterValue) + return util.StringMatchRegexSlice(c.ID(), filterValues) }, nil case "label": - var filterArray = strings.SplitN(filterValue, "=", 2) - var filterKey = filterArray[0] - if len(filterArray) > 1 { - filterValue = filterArray[1] - } else { - filterValue = "" - } + // we have to match that all given labels exits on that container return func(c *libpod.Container) bool { - for labelKey, labelValue := range c.Labels() { - if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) { - return true + labels := c.Labels() + for _, filterValue := range filterValues { + matched := false + filterArray := strings.SplitN(filterValue, "=", 2) + filterKey := filterArray[0] + if len(filterArray) > 1 { + filterValue = filterArray[1] + } else { + filterValue = "" + } + for labelKey, labelValue := range labels { + if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) { + matched = true + break + } + } + if !matched { + return false } } - return false + return true }, nil case "name": + // we only have to match one name return func(c *libpod.Container) bool { - match, err := regexp.MatchString(filterValue, c.Name()) - if err != nil { - logrus.Errorf("Failed to compile regex for 'name' filter: %v", err) - return false - } - return match + return util.StringMatchRegexSlice(c.Name(), filterValues) }, nil case "exited": - exitCode, err := strconv.ParseInt(filterValue, 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "exited code out of range %q", filterValue) + var exitCodes []int32 + for _, exitCode := range filterValues { + ec, err := strconv.ParseInt(exitCode, 10, 32) + if err != nil { + return nil, errors.Wrapf(err, "exited code out of range %q", ec) + } + exitCodes = append(exitCodes, int32(ec)) } return func(c *libpod.Container) bool { ec, exited, err := c.ExitCode() - if ec == int32(exitCode) && err == nil && exited { - return true + if err == nil && exited { + for _, exitCode := range exitCodes { + if ec == exitCode { + return true + } + } } return false }, nil case "status": - if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { - return nil, errors.Errorf("%s is not a valid status", filterValue) + for _, filterValue := range filterValues { + if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { + return nil, errors.Errorf("%s is not a valid status", filterValue) + } } return func(c *libpod.Container) bool { status, err := c.State() if err != nil { return false } - if filterValue == "stopped" { - filterValue = "exited" - } state := status.String() if status == define.ContainerStateConfigured { state = "created" } else if status == define.ContainerStateStopped { state = "exited" } - return state == filterValue + for _, filterValue := range filterValues { + if filterValue == "stopped" { + filterValue = "exited" + } + if state == filterValue { + return true + } + } + return false }, nil case "ancestor": // This needs to refine to match docker // - ancestor=(<image-name>[:tag]|<image-id>| ⟨image@digest⟩) - containers created from an image or a descendant. return func(c *libpod.Container) bool { - containerConfig := c.Config() - if strings.Contains(containerConfig.RootfsImageID, filterValue) || strings.Contains(containerConfig.RootfsImageName, filterValue) { - return true + for _, filterValue := range filterValues { + containerConfig := c.Config() + if strings.Contains(containerConfig.RootfsImageID, filterValue) || strings.Contains(containerConfig.RootfsImageName, filterValue) { + return true + } } return false }, nil case "before": - ctr, err := r.LookupContainer(filterValue) - if err != nil { - return nil, errors.Errorf("unable to find container by name or id of %s", filterValue) + var createTime time.Time + for _, filterValue := range filterValues { + ctr, err := r.LookupContainer(filterValue) + if err != nil { + return nil, err + } + containerConfig := ctr.Config() + if createTime.IsZero() || createTime.After(containerConfig.CreatedTime) { + createTime = containerConfig.CreatedTime + } } - containerConfig := ctr.Config() - createTime := containerConfig.CreatedTime return func(c *libpod.Container) bool { cc := c.Config() return createTime.After(cc.CreatedTime) }, nil case "since": - ctr, err := r.LookupContainer(filterValue) - if err != nil { - return nil, errors.Errorf("unable to find container by name or id of %s", filterValue) + var createTime time.Time + for _, filterValue := range filterValues { + ctr, err := r.LookupContainer(filterValue) + if err != nil { + return nil, err + } + containerConfig := ctr.Config() + if createTime.IsZero() || createTime.After(containerConfig.CreatedTime) { + createTime = containerConfig.CreatedTime + } } - containerConfig := ctr.Config() - createTime := containerConfig.CreatedTime return func(c *libpod.Container) bool { cc := c.Config() return createTime.Before(cc.CreatedTime) @@ -115,17 +146,27 @@ func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) return func(c *libpod.Container) bool { containerConfig := c.Config() var dest string - arr := strings.Split(filterValue, ":") - source := arr[0] - if len(arr) == 2 { - dest = arr[1] - } - for _, mount := range containerConfig.Spec.Mounts { - if dest != "" && (mount.Source == source && mount.Destination == dest) { - return true + for _, filterValue := range filterValues { + arr := strings.SplitN(filterValue, ":", 2) + source := arr[0] + if len(arr) == 2 { + dest = arr[1] } - if dest == "" && mount.Source == source { - return true + for _, mount := range containerConfig.Spec.Mounts { + if dest != "" && (mount.Source == source && mount.Destination == dest) { + return true + } + if dest == "" && mount.Source == source { + return true + } + } + for _, vname := range containerConfig.NamedVolumes { + if dest != "" && (vname.Name == source && vname.Dest == dest) { + return true + } + if dest == "" && vname.Name == source { + return true + } } } return false @@ -136,10 +177,18 @@ func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) if err != nil { return false } - return hcStatus == filterValue + for _, filterValue := range filterValues { + if hcStatus == filterValue { + return true + } + } + return false }, nil case "until": - ts, err := timetype.GetTimestamp(filterValue, time.Now()) + if len(filterValues) != 1 { + return nil, errors.Errorf("specify exactly one timestamp for %s", filter) + } + ts, err := timetype.GetTimestamp(filterValues[0], time.Now()) if err != nil { return nil, err } diff --git a/libpod/filters/pods.go b/libpod/filters/pods.go index 3cd97728f..17b3f3ca9 100644 --- a/libpod/filters/pods.go +++ b/libpod/filters/pods.go @@ -1,7 +1,6 @@ package lpfilters import ( - "regexp" "strconv" "strings" @@ -9,13 +8,12 @@ import ( "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/util" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) // GeneratePodFilterFunc takes a filter and filtervalue (key, value) // and generates a libpod function that can be used to filter // pods -func GeneratePodFilterFunc(filter, filterValue string) ( +func GeneratePodFilterFunc(filter string, filterValues []string) ( func(pod *libpod.Pod) bool, error) { switch filter { case "ctr-ids": @@ -24,7 +22,10 @@ func GeneratePodFilterFunc(filter, filterValue string) ( if err != nil { return false } - return util.StringInSlice(filterValue, ctrIds) + for _, id := range ctrIds { + return util.StringMatchRegexSlice(id, filterValues) + } + return false }, nil case "ctr-names": return func(p *libpod.Pod) bool { @@ -33,9 +34,7 @@ func GeneratePodFilterFunc(filter, filterValue string) ( return false } for _, ctr := range ctrs { - if filterValue == ctr.Name() { - return true - } + return util.StringMatchRegexSlice(ctr.Name(), filterValues) } return false }, nil @@ -45,18 +44,22 @@ func GeneratePodFilterFunc(filter, filterValue string) ( if err != nil { return false } - - fVint, err2 := strconv.Atoi(filterValue) - if err2 != nil { - return false + for _, filterValue := range filterValues { + fVint, err2 := strconv.Atoi(filterValue) + if err2 != nil { + return false + } + if len(ctrIds) == fVint { + return true + } } - return len(ctrIds) == fVint + return false }, nil case "ctr-status": - if !util.StringInSlice(filterValue, - []string{"created", "restarting", "running", "paused", - "exited", "unknown"}) { - return nil, errors.Errorf("%s is not a valid status", filterValue) + for _, filterValue := range filterValues { + if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { + return nil, errors.Errorf("%s is not a valid status", filterValue) + } } return func(p *libpod.Pod) bool { ctrStatuses, err := p.Status() @@ -67,55 +70,69 @@ func GeneratePodFilterFunc(filter, filterValue string) ( state := ctrStatus.String() if ctrStatus == define.ContainerStateConfigured { state = "created" + } else if ctrStatus == define.ContainerStateStopped { + state = "exited" } - if state == filterValue { - return true + for _, filterValue := range filterValues { + if filterValue == "stopped" { + filterValue = "exited" + } + if state == filterValue { + return true + } } } return false }, nil case "id": return func(p *libpod.Pod) bool { - return strings.Contains(p.ID(), filterValue) + return util.StringMatchRegexSlice(p.ID(), filterValues) }, nil case "name": return func(p *libpod.Pod) bool { - match, err := regexp.MatchString(filterValue, p.Name()) - if err != nil { - logrus.Errorf("Failed to compile regex for 'name' filter: %v", err) - return false - } - return match + return util.StringMatchRegexSlice(p.Name(), filterValues) }, nil case "status": - if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { - return nil, errors.Errorf("%s is not a valid pod status", filterValue) + for _, filterValue := range filterValues { + if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { + return nil, errors.Errorf("%s is not a valid pod status", filterValue) + } } return func(p *libpod.Pod) bool { status, err := p.GetPodStatus() if err != nil { return false } - if strings.ToLower(status) == filterValue { - return true + for _, filterValue := range filterValues { + if strings.ToLower(status) == filterValue { + return true + } } return false }, nil case "label": - var filterArray = strings.SplitN(filterValue, "=", 2) - var filterKey = filterArray[0] - if len(filterArray) > 1 { - filterValue = filterArray[1] - } else { - filterValue = "" - } return func(p *libpod.Pod) bool { - for labelKey, labelValue := range p.Labels() { - if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) { - return true + labels := p.Labels() + for _, filterValue := range filterValues { + matched := false + filterArray := strings.SplitN(filterValue, "=", 2) + filterKey := filterArray[0] + if len(filterArray) > 1 { + filterValue = filterArray[1] + } else { + filterValue = "" + } + for labelKey, labelValue := range labels { + if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) { + matched = true + break + } + } + if !matched { + return false } } - return false + return true }, nil } return nil, errors.Errorf("%s is an invalid filter", filter) |