mirror of
https://github.com/containers/podman
synced 2024-10-19 08:44:11 +00:00
Merge pull request #8395 from Luap99/podman-pod-ps-filters
Align the podman pod ps --filter behavior with podman ps
This commit is contained in:
commit
4434bd7978
|
@ -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**
|
||||
|
||||
|
|
|
@ -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' |
|
||||
|
|
|
@ -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,56 +70,70 @@ 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
|
||||
}
|
||||
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) {
|
||||
for _, filterValue := range filterValues {
|
||||
if strings.ToLower(status) == filterValue {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}, nil
|
||||
case "label":
|
||||
return func(p *libpod.Pod) bool {
|
||||
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 true
|
||||
}, nil
|
||||
}
|
||||
return nil, errors.Errorf("%s is an invalid filter", filter)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue