summaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-12-30 05:13:49 +0100
committerGitHub <noreply@github.com>2020-12-30 05:13:49 +0100
commit7f0771fa9401c26e942c67788bebc0041dfa3311 (patch)
treedc5d925da58c4658b26ba850ead3b09d67226e10 /pkg/domain
parent9c9f02aad773051fa742a874844f08f2fb567d3b (diff)
parent76afb50f3ae41a3cc43fca8cc41a2d2f1f1b6dcc (diff)
downloadpodman-7f0771fa9401c26e942c67788bebc0041dfa3311.tar.gz
podman-7f0771fa9401c26e942c67788bebc0041dfa3311.tar.bz2
podman-7f0771fa9401c26e942c67788bebc0041dfa3311.zip
Merge pull request #8809 from bblenard/bblenard-dev
Consolidate filter logic to pkg subdirectory
Diffstat (limited to 'pkg/domain')
-rw-r--r--pkg/domain/filters/containers.go239
-rw-r--r--pkg/domain/filters/pods.go139
-rw-r--r--pkg/domain/infra/abi/containers.go4
-rw-r--r--pkg/domain/infra/abi/pods.go4
4 files changed, 382 insertions, 4 deletions
diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go
new file mode 100644
index 000000000..6abdd6b57
--- /dev/null
+++ b/pkg/domain/filters/containers.go
@@ -0,0 +1,239 @@
+package filters
+
+import (
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/pkg/timetype"
+ "github.com/containers/podman/v2/pkg/util"
+ "github.com/pkg/errors"
+)
+
+// GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
+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 util.StringMatchRegexSlice(c.ID(), filterValues)
+ }, nil
+ case "label":
+ // we have to match that all given labels exits on that container
+ return func(c *libpod.Container) bool {
+ 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 true
+ }, nil
+ case "name":
+ // we only have to match one name
+ return func(c *libpod.Container) bool {
+ return util.StringMatchRegexSlice(c.Name(), filterValues)
+ }, nil
+ case "exited":
+ 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 err == nil && exited {
+ for _, exitCode := range exitCodes {
+ if ec == exitCode {
+ return true
+ }
+ }
+ }
+ return false
+ }, nil
+ case "status":
+ 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
+ }
+ state := status.String()
+ if status == define.ContainerStateConfigured {
+ state = "created"
+ } else if status == define.ContainerStateStopped {
+ state = "exited"
+ }
+ 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 {
+ 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":
+ 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
+ }
+ }
+ return func(c *libpod.Container) bool {
+ cc := c.Config()
+ return createTime.After(cc.CreatedTime)
+ }, nil
+ case "since":
+ 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
+ }
+ }
+ return func(c *libpod.Container) bool {
+ cc := c.Config()
+ return createTime.Before(cc.CreatedTime)
+ }, nil
+ case "volume":
+ //- volume=(<volume-name>|<mount-point-destination>)
+ return func(c *libpod.Container) bool {
+ containerConfig := c.Config()
+ var dest string
+ for _, filterValue := range filterValues {
+ arr := strings.SplitN(filterValue, ":", 2)
+ 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
+ }
+ 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
+ }, nil
+ case "health":
+ return func(c *libpod.Container) bool {
+ hcStatus, err := c.HealthCheckStatus()
+ if err != nil {
+ return false
+ }
+ for _, filterValue := range filterValues {
+ if hcStatus == filterValue {
+ return true
+ }
+ }
+ return false
+ }, nil
+ case "until":
+ 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
+ }
+ seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
+ if err != nil {
+ return nil, err
+ }
+ until := time.Unix(seconds, nanoseconds)
+ return func(c *libpod.Container) bool {
+ if !until.IsZero() && c.CreatedTime().After((until)) {
+ return true
+ }
+ return false
+ }, nil
+ case "pod":
+ var pods []*libpod.Pod
+ for _, podNameOrID := range filterValues {
+ p, err := r.LookupPod(podNameOrID)
+ if err != nil {
+ if errors.Cause(err) == define.ErrNoSuchPod {
+ continue
+ }
+ return nil, err
+ }
+ pods = append(pods, p)
+ }
+ return func(c *libpod.Container) bool {
+ // if no pods match, quick out
+ if len(pods) < 1 {
+ return false
+ }
+ // if the container has no pod id, quick out
+ if len(c.PodID()) < 1 {
+ return false
+ }
+ for _, p := range pods {
+ // we already looked up by name or id, so id match
+ // here is ok
+ if p.ID() == c.PodID() {
+ return true
+ }
+ }
+ return false
+ }, nil
+
+ }
+ return nil, errors.Errorf("%s is an invalid filter", filter)
+}
diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go
new file mode 100644
index 000000000..7e6b7f2cc
--- /dev/null
+++ b/pkg/domain/filters/pods.go
@@ -0,0 +1,139 @@
+package filters
+
+import (
+ "strconv"
+ "strings"
+
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/pkg/util"
+ "github.com/pkg/errors"
+)
+
+// GeneratePodFilterFunc takes a filter and filtervalue (key, value)
+// and generates a libpod function that can be used to filter
+// pods
+func GeneratePodFilterFunc(filter string, filterValues []string) (
+ func(pod *libpod.Pod) bool, error) {
+ switch filter {
+ case "ctr-ids":
+ return func(p *libpod.Pod) bool {
+ ctrIds, err := p.AllContainersByID()
+ if err != nil {
+ return false
+ }
+ for _, id := range ctrIds {
+ return util.StringMatchRegexSlice(id, filterValues)
+ }
+ return false
+ }, nil
+ case "ctr-names":
+ return func(p *libpod.Pod) bool {
+ ctrs, err := p.AllContainers()
+ if err != nil {
+ return false
+ }
+ for _, ctr := range ctrs {
+ return util.StringMatchRegexSlice(ctr.Name(), filterValues)
+ }
+ return false
+ }, nil
+ case "ctr-number":
+ return func(p *libpod.Pod) bool {
+ ctrIds, err := p.AllContainersByID()
+ if err != nil {
+ return false
+ }
+ for _, filterValue := range filterValues {
+ fVint, err2 := strconv.Atoi(filterValue)
+ if err2 != nil {
+ return false
+ }
+ if len(ctrIds) == fVint {
+ return true
+ }
+ }
+ return false
+ }, nil
+ case "ctr-status":
+ 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()
+ if err != nil {
+ return false
+ }
+ for _, ctrStatus := range ctrStatuses {
+ state := ctrStatus.String()
+ if ctrStatus == define.ContainerStateConfigured {
+ state = "created"
+ } else if ctrStatus == define.ContainerStateStopped {
+ state = "exited"
+ }
+ 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 util.StringMatchRegexSlice(p.ID(), filterValues)
+ }, nil
+ case "name":
+ return func(p *libpod.Pod) bool {
+ return util.StringMatchRegexSlice(p.Name(), filterValues)
+ }, nil
+ case "status":
+ 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
+ }
+ 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)
+}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index efb4f866f..cfb3421ba 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -16,12 +16,12 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/libpod/logs"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/checkpoint"
"github.com/containers/podman/v2/pkg/domain/entities"
+ dfilters "github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/terminal"
parallelctr "github.com/containers/podman/v2/pkg/parallel/ctr"
"github.com/containers/podman/v2/pkg/ps"
@@ -207,7 +207,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) {
filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod)
+ generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 11374e513..f108b770c 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -5,8 +5,8 @@ import (
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
- lpfilters "github.com/containers/podman/v2/libpod/filters"
"github.com/containers/podman/v2/pkg/domain/entities"
+ dfilters "github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/signal"
"github.com/containers/podman/v2/pkg/specgen"
"github.com/containers/podman/v2/pkg/specgen/generate"
@@ -288,7 +288,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
filters := make([]libpod.PodFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- f, err := lpfilters.GeneratePodFilterFunc(k, v)
+ f, err := dfilters.GeneratePodFilterFunc(k, v)
if err != nil {
return nil, err
}