summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-11-18 21:16:21 +0100
committerGitHub <noreply@github.com>2020-11-18 21:16:21 +0100
commit4434bd797842c3015c0e6132eaf2509fed370c26 (patch)
tree07576e5d9c5b37f06a48bc027ce1c1d73852c8e7
parent8672c4dea05366ae65c609a4d7f7d848d1cf04e0 (diff)
parente7fd9234cd0e6a23e32dd31c912ac47883b59738 (diff)
downloadpodman-4434bd797842c3015c0e6132eaf2509fed370c26.tar.gz
podman-4434bd797842c3015c0e6132eaf2509fed370c26.tar.bz2
podman-4434bd797842c3015c0e6132eaf2509fed370c26.zip
Merge pull request #8395 from Luap99/podman-pod-ps-filters
Align the podman pod ps --filter behavior with podman ps
-rw-r--r--docs/source/markdown/podman-pod-ps.1.md24
-rw-r--r--docs/source/markdown/podman-ps.1.md8
-rw-r--r--libpod/filters/pods.go97
-rw-r--r--pkg/api/handlers/utils/pods.go14
-rw-r--r--pkg/domain/infra/abi/pods.go17
-rw-r--r--test/e2e/pod_ps_test.go26
6 files changed, 114 insertions, 72 deletions
diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md
index 94747cd10..e1d60d765 100644
--- a/docs/source/markdown/podman-pod-ps.1.md
+++ b/docs/source/markdown/podman-pod-ps.1.md
@@ -80,19 +80,23 @@ Default: created
#### **--filter**, **-f**=*filter*
-Filter output based on conditions given
+Filter output based on conditions given.
+Multiple filters can be given with multiple uses of the --filter flag.
+Filters with the same key work inclusive with the only exception being
+`label` which is exclusive. Filters with different keys always work exclusive.
Valid filters are listed below:
-| **Filter** | **Description** |
-| --------------- | ------------------------------------------------------------------- |
-| id | [ID] Pod's ID |
-| name | [Name] Pod's name |
-| label | [Key] or [Key=Value] Label assigned to a container |
-| ctr-names | Container name within the pod |
-| ctr-ids | Container ID within the pod |
-| ctr-status | Container status within the pod |
-| ctr-number | Number of containers in the pod |
+| **Filter** | **Description** |
+| ---------- | ------------------------------------------------------------------------------------- |
+| id | [ID] Pod's ID (accepts regex) |
+| name | [Name] Pod's name (accepts regex) |
+| label | [Key] or [Key=Value] Label assigned to a container |
+| status | Pod's status: `stopped`, `running`, `paused`, `exited`, `dead`, `created`, `degraded` |
+| ctr-names | Container name within the pod (accepts regex) |
+| ctr-ids | Container ID within the pod (accepts regex) |
+| ctr-status | Container status within the pod |
+| ctr-number | Number of containers in the pod |
#### **--help**, **-h**
diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md
index 5869f2307..f542daf4c 100644
--- a/docs/source/markdown/podman-ps.1.md
+++ b/docs/source/markdown/podman-ps.1.md
@@ -44,15 +44,15 @@ Display external containers that are not controlled by Podman but are stored in
Filter what containers are shown in the output.
Multiple filters can be given with multiple uses of the --filter flag.
-If multiple filters are given, only containers which match all of the given filters will be shown.
-Results will be drawn from all containers, regardless of whether --all was given.
+Filters with the same key work inclusive with the only exception being
+`label` which is exclusive. Filters with different keys always work exclusive.
Valid filters are listed below:
| **Filter** | **Description** |
| --------------- | -------------------------------------------------------------------------------- |
-| id | [ID] Container's ID |
-| name | [Name] Container's name |
+| id | [ID] Container's ID (accepts regex) |
+| name | [Name] Container's name (accepts regex) |
| label | [Key] or [Key=Value] Label assigned to a container |
| exited | [Int] Container's exit code |
| status | [Status] Container's status: 'created', 'exited', 'paused', 'running', 'unknown' |
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)
diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go
index 54ebe2d29..7506dbfd1 100644
--- a/pkg/api/handlers/utils/pods.go
+++ b/pkg/api/handlers/utils/pods.go
@@ -11,8 +11,7 @@ import (
func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport, error) {
var (
- pods []*libpod.Pod
- filters []libpod.PodFilter
+ pods []*libpod.Pod
)
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@@ -30,14 +29,13 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
UnSupportedParameter("digests")
}
+ filters := make([]libpod.PodFilter, 0, len(query.Filters))
for k, v := range query.Filters {
- for _, filter := range v {
- f, err := lpfilters.GeneratePodFilterFunc(k, filter)
- if err != nil {
- return nil, err
- }
- filters = append(filters, f)
+ f, err := lpfilters.GeneratePodFilterFunc(k, v)
+ if err != nil {
+ return nil, err
}
+ filters = append(filters, f)
}
pods, err := runtime.Pods(filters...)
if err != nil {
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 258640a81..11374e513 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -282,20 +282,17 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp
func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
var (
- err error
- filters = []libpod.PodFilter{}
- pds = []*libpod.Pod{}
+ err error
+ pds = []*libpod.Pod{}
)
+ filters := make([]libpod.PodFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- for _, filter := range v {
- f, err := lpfilters.GeneratePodFilterFunc(k, filter)
- if err != nil {
- return nil, err
- }
- filters = append(filters, f)
-
+ f, err := lpfilters.GeneratePodFilterFunc(k, v)
+ if err != nil {
+ return nil, err
}
+ filters = append(filters, f)
}
if options.Latest {
pod, err := ic.Libpod.GetLatestPod()
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 5d63d5985..ea8d10e78 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -194,12 +194,24 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(ContainSubstring(podid1))
Expect(session.OutputToString()).To(Not(ContainSubstring(podid2)))
+ session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "ctr-names=test", "--filter", "ctr-status=running"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(podid1))
+ Expect(session.OutputToString()).To(Not(ContainSubstring(podid2)))
+
session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", fmt.Sprintf("ctr-ids=%s", cid)})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring(podid2))
Expect(session.OutputToString()).To(Not(ContainSubstring(podid1)))
+ session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "ctr-ids=" + cid[:40], "--filter", "ctr-ids=" + cid + "$"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(podid2))
+ Expect(session.OutputToString()).To(Not(ContainSubstring(podid1)))
+
_, ec3, podid3 := podmanTest.CreatePod("")
Expect(ec3).To(Equal(0))
@@ -210,6 +222,13 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(ContainSubstring(podid2))
Expect(session.OutputToString()).To(Not(ContainSubstring(podid3)))
+ session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "ctr-number=1", "--filter", "ctr-number=0"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(podid1))
+ Expect(session.OutputToString()).To(ContainSubstring(podid2))
+ Expect(session.OutputToString()).To(ContainSubstring(podid3))
+
session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "ctr-status=running"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -224,6 +243,13 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(Not(ContainSubstring(podid1)))
Expect(session.OutputToString()).To(Not(ContainSubstring(podid3)))
+ session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "ctr-status=exited", "--filter", "ctr-status=running"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(podid1))
+ Expect(session.OutputToString()).To(ContainSubstring(podid2))
+ Expect(session.OutputToString()).To(Not(ContainSubstring(podid3)))
+
session = podmanTest.Podman([]string{"pod", "ps", "-q", "--no-trunc", "--filter", "ctr-status=created"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))