mirror of
https://github.com/moby/moby.git
synced 2025-08-01 05:47:11 +03:00
Add a new "is-task" ps filter
This makes it easier to list containers that are part of a task (swarm mode) and those who are not. Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
@ -2181,6 +2181,10 @@ _docker_ps() {
|
|||||||
__docker_complete_container_ids
|
__docker_complete_container_ids
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
is-task)
|
||||||
|
COMPREPLY=( $( compgen -W "true false" -- "${cur##*=}" ) )
|
||||||
|
return
|
||||||
|
;;
|
||||||
name)
|
name)
|
||||||
cur="${cur##*=}"
|
cur="${cur##*=}"
|
||||||
__docker_complete_container_names
|
__docker_complete_container_names
|
||||||
|
@ -333,6 +333,9 @@ __docker_complete_ps_filters() {
|
|||||||
(id)
|
(id)
|
||||||
__docker_containers_ids && ret=0
|
__docker_containers_ids && ret=0
|
||||||
;;
|
;;
|
||||||
|
(is-task)
|
||||||
|
_describe -t boolean-filter-opts "filter options" boolean_opts && ret=0
|
||||||
|
;;
|
||||||
(name)
|
(name)
|
||||||
__docker_containers_names && ret=0
|
__docker_containers_names && ret=0
|
||||||
;;
|
;;
|
||||||
|
@ -36,6 +36,7 @@ var acceptedPsFilterTags = map[string]bool{
|
|||||||
"since": true,
|
"since": true,
|
||||||
"volume": true,
|
"volume": true,
|
||||||
"network": true,
|
"network": true,
|
||||||
|
"is-task": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterationAction represents possible outcomes happening during the container iteration.
|
// iterationAction represents possible outcomes happening during the container iteration.
|
||||||
@ -79,11 +80,14 @@ type listContext struct {
|
|||||||
exitAllowed []int
|
exitAllowed []int
|
||||||
|
|
||||||
// beforeFilter is a filter to ignore containers that appear before the one given
|
// beforeFilter is a filter to ignore containers that appear before the one given
|
||||||
// this is used for --filter=before= and --before=, the latter is deprecated.
|
|
||||||
beforeFilter *container.Container
|
beforeFilter *container.Container
|
||||||
// sinceFilter is a filter to stop the filtering when the iterator arrive to the given container
|
// sinceFilter is a filter to stop the filtering when the iterator arrive to the given container
|
||||||
// this is used for --filter=since= and --since=, the latter is deprecated.
|
|
||||||
sinceFilter *container.Container
|
sinceFilter *container.Container
|
||||||
|
|
||||||
|
// taskFilter tells if we should filter based on wether a container is part of a task
|
||||||
|
taskFilter bool
|
||||||
|
// isTask tells us if the we should filter container that are a task (true) or not (false)
|
||||||
|
isTask bool
|
||||||
// ContainerListOptions is the filters set by the user
|
// ContainerListOptions is the filters set by the user
|
||||||
*types.ContainerListOptions
|
*types.ContainerListOptions
|
||||||
}
|
}
|
||||||
@ -241,6 +245,19 @@ func (daemon *Daemon) foldFilter(config *types.ContainerListOptions) (*listConte
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var taskFilter, isTask bool
|
||||||
|
if psFilters.Include("is-task") {
|
||||||
|
if psFilters.ExactMatch("is-task", "true") {
|
||||||
|
taskFilter = true
|
||||||
|
isTask = true
|
||||||
|
} else if psFilters.ExactMatch("is-task", "false") {
|
||||||
|
taskFilter = true
|
||||||
|
isTask = false
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("Invalid filter 'is-task=%s'", psFilters.Get("is-task"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var beforeContFilter, sinceContFilter *container.Container
|
var beforeContFilter, sinceContFilter *container.Container
|
||||||
|
|
||||||
err = psFilters.WalkValues("before", func(value string) error {
|
err = psFilters.WalkValues("before", func(value string) error {
|
||||||
@ -286,6 +303,8 @@ func (daemon *Daemon) foldFilter(config *types.ContainerListOptions) (*listConte
|
|||||||
exitAllowed: filtExited,
|
exitAllowed: filtExited,
|
||||||
beforeFilter: beforeContFilter,
|
beforeFilter: beforeContFilter,
|
||||||
sinceFilter: sinceContFilter,
|
sinceFilter: sinceContFilter,
|
||||||
|
taskFilter: taskFilter,
|
||||||
|
isTask: isTask,
|
||||||
ContainerListOptions: config,
|
ContainerListOptions: config,
|
||||||
names: daemon.nameIndex.GetAll(),
|
names: daemon.nameIndex.GetAll(),
|
||||||
}, nil
|
}, nil
|
||||||
@ -325,6 +344,12 @@ func includeContainerInList(container *container.Container, ctx *listContext) it
|
|||||||
return excludeContainer
|
return excludeContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.taskFilter {
|
||||||
|
if ctx.isTask != container.Managed {
|
||||||
|
return excludeContainer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do not include container if any of the labels don't match
|
// Do not include container if any of the labels don't match
|
||||||
if !ctx.filters.MatchKVList("label", container.Config.Labels) {
|
if !ctx.filters.MatchKVList("label", container.Config.Labels) {
|
||||||
return excludeContainer
|
return excludeContainer
|
||||||
|
@ -130,6 +130,8 @@ This section lists each version from latest to oldest. Each listing includes a
|
|||||||
instead of the default network if a trailing slash is provided, but no `name`
|
instead of the default network if a trailing slash is provided, but no `name`
|
||||||
or `id`.
|
or `id`.
|
||||||
* `DELETE /containers/(name)` endpoint now returns an error of `removal of container name is already in progress` with status code of 400, when container name is in a state of removal in progress.
|
* `DELETE /containers/(name)` endpoint now returns an error of `removal of container name is already in progress` with status code of 400, when container name is in a state of removal in progress.
|
||||||
|
* `GET /containers/json` now supports a `is-task` filter to filter
|
||||||
|
containers that are tasks (part of a service in swarm mode).
|
||||||
|
|
||||||
### v1.24 API changes
|
### v1.24 API changes
|
||||||
|
|
||||||
|
@ -229,6 +229,9 @@ List containers
|
|||||||
- `status=`(`created`|`restarting`|`running`|`removing`|`paused`|`exited`|`dead`)
|
- `status=`(`created`|`restarting`|`running`|`removing`|`paused`|`exited`|`dead`)
|
||||||
- `label=key` or `label="key=value"` of a container label
|
- `label=key` or `label="key=value"` of a container label
|
||||||
- `isolation=`(`default`|`process`|`hyperv`) (Windows daemon only)
|
- `isolation=`(`default`|`process`|`hyperv`) (Windows daemon only)
|
||||||
|
`id=<ID>` a container's ID
|
||||||
|
`name=<name>` a container's name
|
||||||
|
`is-task=`(`true`|`false`)
|
||||||
- `ancestor`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
|
- `ancestor`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
|
||||||
- `before`=(`<container id>` or `<container name>`)
|
- `before`=(`<container id>` or `<container name>`)
|
||||||
- `since`=(`<container id>` or `<container name>`)
|
- `since`=(`<container id>` or `<container name>`)
|
||||||
|
@ -27,6 +27,7 @@ Options:
|
|||||||
- since=(<container-name>|<container-id>)
|
- since=(<container-name>|<container-id>)
|
||||||
- ancestor=(<image-name>[:tag]|<image-id>|<image@digest>)
|
- ancestor=(<image-name>[:tag]|<image-id>|<image@digest>)
|
||||||
containers created from an image or a descendant.
|
containers created from an image or a descendant.
|
||||||
|
- is-task=(true|false)
|
||||||
--format string Pretty-print containers using a Go template
|
--format string Pretty-print containers using a Go template
|
||||||
--help Print usage
|
--help Print usage
|
||||||
-n, --last int Show n last created containers (includes all states) (default -1)
|
-n, --last int Show n last created containers (includes all states) (default -1)
|
||||||
|
@ -136,6 +136,7 @@ func assertContainerList(out string, expected []string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(vdemeester) Move this into a unit test in daemon package
|
||||||
func (s *DockerSuite) TestPsListContainersInvalidFilterName(c *check.C) {
|
func (s *DockerSuite) TestPsListContainersInvalidFilterName(c *check.C) {
|
||||||
out, _, err := dockerCmdWithError("ps", "-f", "invalidFilter=test")
|
out, _, err := dockerCmdWithError("ps", "-f", "invalidFilter=test")
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
|
@ -323,3 +323,33 @@ func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *check.C) {
|
|||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
c.Assert(out, checker.Not(checker.Contains), name)
|
c.Assert(out, checker.Not(checker.Contains), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *check.C) {
|
||||||
|
d := s.AddDaemon(c, true, true)
|
||||||
|
|
||||||
|
// Create a bare container
|
||||||
|
out, err := d.Cmd("run", "-d", "--name=bare-container", "busybox", "top")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
bareID := strings.TrimSpace(out)[:12]
|
||||||
|
// Create a service
|
||||||
|
name := "busybox-top"
|
||||||
|
out, err = d.Cmd("service", "create", "--name", name, "busybox", "top")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
||||||
|
|
||||||
|
// make sure task has been deployed.
|
||||||
|
waitAndAssert(c, defaultReconciliationTimeout, d.checkServiceRunningTasks(c, name), checker.Equals, 1)
|
||||||
|
|
||||||
|
// Filter non-tasks
|
||||||
|
out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=false")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
psOut := strings.TrimSpace(out)
|
||||||
|
c.Assert(psOut, checker.Equals, bareID, check.Commentf("Expected id %s, got %s for is-task label, output %q", bareID, psOut, out))
|
||||||
|
|
||||||
|
// Filter tasks
|
||||||
|
out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=true")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
lines := strings.Split(strings.Trim(out, "\n "), "\n")
|
||||||
|
c.Assert(lines, checker.HasLen, 1)
|
||||||
|
c.Assert(lines[0], checker.Not(checker.Equals), bareID, check.Commentf("Expected not %s, but got it for is-task label, output %q", bareID, out))
|
||||||
|
}
|
||||||
|
@ -32,6 +32,7 @@ the running containers.
|
|||||||
- status=(created|restarting|running|paused|exited|dead)
|
- status=(created|restarting|running|paused|exited|dead)
|
||||||
- name=<string> a container's name
|
- name=<string> a container's name
|
||||||
- id=<ID> a container's ID
|
- id=<ID> a container's ID
|
||||||
|
- is-task=(true|false) - containers that are a task (part of a service managed by swarm)
|
||||||
- before=(<container-name>|<container-id>)
|
- before=(<container-name>|<container-id>)
|
||||||
- since=(<container-name>|<container-id>)
|
- since=(<container-name>|<container-id>)
|
||||||
- ancestor=(<image-name>[:tag]|<image-id>|<image@digest>) - containers created from an image or a descendant.
|
- ancestor=(<image-name>[:tag]|<image-id>|<image@digest>) - containers created from an image or a descendant.
|
||||||
|
Reference in New Issue
Block a user