Filter containers by status.
A continuation of #7616. Adds `docker ps --filter=status=(restarting|running|paused|stopped)` option. Docker-DCO-1.1-Signed-off-by: Jessica Frazelle <jess@docker.com> (github: jfrazelle)
This commit is contained in:
parent
8128339bc8
commit
ea09f03682
5 changed files with 78 additions and 8 deletions
|
@ -1485,7 +1485,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
|||
last := cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
|
||||
|
||||
flFilter := opts.NewListOpts(nil)
|
||||
cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited=<int> - containers with exit code of <int>")
|
||||
cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited=<int> - containers with exit code of <int>\nstatus=(restarting|running|paused|exited)")
|
||||
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
|
|
|
@ -28,6 +28,7 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
|
|||
size = job.GetenvBool("size")
|
||||
psFilters filters.Args
|
||||
filt_exited []int
|
||||
filt_status []string
|
||||
)
|
||||
outs := engine.NewTable("Created", 0)
|
||||
|
||||
|
@ -45,6 +46,8 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
|
|||
}
|
||||
}
|
||||
|
||||
filt_status, _ = psFilters["status"]
|
||||
|
||||
names := map[string][]string{}
|
||||
daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
|
||||
names[e.ID()] = append(names[e.ID()], p)
|
||||
|
@ -99,6 +102,11 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
for _, status := range filt_status {
|
||||
if container.State.StateString() != strings.ToLower(status) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
displayed++
|
||||
out := &engine.Env{}
|
||||
out.Set("Id", container.ID)
|
||||
|
|
|
@ -46,6 +46,20 @@ func (s *State) String() string {
|
|||
return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||
}
|
||||
|
||||
// StateString returns a single string to describe state
|
||||
func (s *State) StateString() string {
|
||||
if s.Running {
|
||||
if s.Paused {
|
||||
return "paused"
|
||||
}
|
||||
if s.Restarting {
|
||||
return "restarting"
|
||||
}
|
||||
return "running"
|
||||
}
|
||||
return "exited"
|
||||
}
|
||||
|
||||
func wait(waitChan <-chan struct{}, timeout time.Duration) error {
|
||||
if timeout < 0 {
|
||||
<-waitChan
|
||||
|
|
|
@ -241,14 +241,15 @@ as the root. Wildcards are allowed but the search is not recursive.
|
|||
temp?
|
||||
|
||||
The first line above `*/temp*`, would ignore all files with names starting with
|
||||
`temp` from any subdirectory below the root directory, for example file named
|
||||
`/somedir/temporary.txt` will be ignored. The second line `*/*/temp*`, will
|
||||
`temp` from any subdirectory below the root directory. For example, a file named
|
||||
`/somedir/temporary.txt` would be ignored. The second line `*/*/temp*`, will
|
||||
ignore files starting with name `temp` from any subdirectory that is two levels
|
||||
below the root directory, for example a file `/somedir/subdir/temporary.txt` is
|
||||
ignored in this case. The last line in the above example `temp?`, will ignore
|
||||
the files that match the pattern from the root directory, for example files
|
||||
`tempa`, `tempb` are ignored from the root directory. Currently there is no
|
||||
support for regular expressions, formats like `[^temp*]` are ignored.
|
||||
below the root directory. For example, the file `/somedir/subdir/temporary.txt`
|
||||
would get ignored in this case. The last line in the above example `temp?`
|
||||
will ignore the files that match the pattern from the root directory.
|
||||
For example, the files `tempa`, `tempb` are ignored from the root directory.
|
||||
Currently there is no support for regular expressions. Formats
|
||||
like `[^temp*]` are ignored.
|
||||
|
||||
|
||||
See also:
|
||||
|
@ -943,6 +944,7 @@ further details.
|
|||
--before="" Show only container created before Id or Name, include non-running ones.
|
||||
-f, --filter=[] Provide filter values. Valid filters:
|
||||
exited=<int> - containers with exit code of <int>
|
||||
status=(restarting|running|paused|exited)
|
||||
-l, --latest=false Show only the latest created container, include non-running ones.
|
||||
-n=-1 Show n last created containers, include non-running ones.
|
||||
--no-trunc=false Don't truncate output
|
||||
|
|
|
@ -235,4 +235,50 @@ func TestPsListContainersSize(t *testing.T) {
|
|||
if foundSize != expectedSize {
|
||||
t.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
|
||||
}
|
||||
|
||||
deleteAllContainers()
|
||||
logDone("ps - test ps size")
|
||||
}
|
||||
|
||||
func TestPsListContainersFilterStatus(t *testing.T) {
|
||||
// FIXME: this should test paused, but it makes things hang and its wonky
|
||||
// this is because paused containers can't be controlled by signals
|
||||
|
||||
// start exited container
|
||||
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox")
|
||||
out, _, err := runCommandWithOutput(runCmd)
|
||||
errorOut(err, t, out)
|
||||
firstID := stripTrailingCharacters(out)
|
||||
|
||||
// make sure the exited cintainer is not running
|
||||
runCmd = exec.Command(dockerBinary, "wait", firstID)
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
errorOut(err, t, out)
|
||||
|
||||
// start running container
|
||||
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 360")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
errorOut(err, t, out)
|
||||
secondID := stripTrailingCharacters(out)
|
||||
|
||||
// filter containers by exited
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=status=exited")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
errorOut(err, t, out)
|
||||
containerOut := strings.TrimSpace(out)
|
||||
if containerOut != firstID[:12] {
|
||||
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
|
||||
}
|
||||
|
||||
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=status=running")
|
||||
out, _, err = runCommandWithOutput(runCmd)
|
||||
errorOut(err, t, out)
|
||||
containerOut = strings.TrimSpace(out)
|
||||
if containerOut != secondID[:12] {
|
||||
t.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
|
||||
}
|
||||
|
||||
deleteAllContainers()
|
||||
|
||||
logDone("ps - test ps filter status")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue