* starting with filtering for exit codes. `docker ps -a --filter 'exited=1'`
* API doc for filter parameter
* formatting filters for help usage
* tweaks for review
This requires https://github.com/dotcloud/docker/pull/4430
Docker-DCO-1.1-Signed-off-by: Vincent Batts <vbatts@redhat.com> (github: vbatts)
| ... | ... |
@@ -1487,6 +1487,9 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
| 1487 | 1487 |
before := cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name, include non-running ones.")
|
| 1488 | 1488 |
last := cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
|
| 1489 | 1489 |
|
| 1490 |
+ var flFilter opts.ListOpts |
|
| 1491 |
+ cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values. Valid filters:\nexited=<int> - containers with exit code of <int>")
|
|
| 1492 |
+ |
|
| 1490 | 1493 |
if err := cmd.Parse(args); err != nil {
|
| 1491 | 1494 |
return nil |
| 1492 | 1495 |
} |
| ... | ... |
@@ -1510,6 +1513,24 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
| 1510 | 1510 |
v.Set("size", "1")
|
| 1511 | 1511 |
} |
| 1512 | 1512 |
|
| 1513 |
+ // Consolidate all filter flags, and sanity check them. |
|
| 1514 |
+ // They'll get processed in the daemon/server. |
|
| 1515 |
+ psFilterArgs := filters.Args{}
|
|
| 1516 |
+ for _, f := range flFilter.GetAll() {
|
|
| 1517 |
+ var err error |
|
| 1518 |
+ psFilterArgs, err = filters.ParseFlag(f, psFilterArgs) |
|
| 1519 |
+ if err != nil {
|
|
| 1520 |
+ return err |
|
| 1521 |
+ } |
|
| 1522 |
+ } |
|
| 1523 |
+ if len(psFilterArgs) > 0 {
|
|
| 1524 |
+ filterJson, err := filters.ToParam(psFilterArgs) |
|
| 1525 |
+ if err != nil {
|
|
| 1526 |
+ return err |
|
| 1527 |
+ } |
|
| 1528 |
+ v.Set("filters", filterJson)
|
|
| 1529 |
+ } |
|
| 1530 |
+ |
|
| 1513 | 1531 |
body, _, err := readBody(cli.call("GET", "/containers/json?"+v.Encode(), nil, false))
|
| 1514 | 1532 |
if err != nil {
|
| 1515 | 1533 |
return err |
| ... | ... |
@@ -339,6 +339,7 @@ func getContainersJSON(eng *engine.Engine, version version.Version, w http.Respo |
| 339 | 339 |
job.Setenv("since", r.Form.Get("since"))
|
| 340 | 340 |
job.Setenv("before", r.Form.Get("before"))
|
| 341 | 341 |
job.Setenv("limit", r.Form.Get("limit"))
|
| 342 |
+ job.Setenv("filters", r.Form.Get("filters"))
|
|
| 342 | 343 |
|
| 343 | 344 |
if version.GreaterThanOrEqualTo("1.5") {
|
| 344 | 345 |
streamJSON(job, w, false) |
| ... | ... |
@@ -3,11 +3,13 @@ package daemon |
| 3 | 3 |
import ( |
| 4 | 4 |
"errors" |
| 5 | 5 |
"fmt" |
| 6 |
+ "strconv" |
|
| 6 | 7 |
"strings" |
| 7 | 8 |
|
| 8 | 9 |
"github.com/docker/docker/pkg/graphdb" |
| 9 | 10 |
|
| 10 | 11 |
"github.com/docker/docker/engine" |
| 12 |
+ "github.com/docker/docker/pkg/parsers/filters" |
|
| 11 | 13 |
) |
| 12 | 14 |
|
| 13 | 15 |
// List returns an array of all containers registered in the daemon. |
| ... | ... |
@@ -24,9 +26,25 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
|
| 24 | 24 |
before = job.Getenv("before")
|
| 25 | 25 |
n = job.GetenvInt("limit")
|
| 26 | 26 |
size = job.GetenvBool("size")
|
| 27 |
+ psFilters filters.Args |
|
| 28 |
+ filt_exited []int |
|
| 27 | 29 |
) |
| 28 | 30 |
outs := engine.NewTable("Created", 0)
|
| 29 | 31 |
|
| 32 |
+ psFilters, err := filters.FromParam(job.Getenv("filters"))
|
|
| 33 |
+ if err != nil {
|
|
| 34 |
+ return job.Error(err) |
|
| 35 |
+ } |
|
| 36 |
+ if i, ok := psFilters["exited"]; ok {
|
|
| 37 |
+ for _, value := range i {
|
|
| 38 |
+ code, err := strconv.Atoi(value) |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ return job.Error(err) |
|
| 41 |
+ } |
|
| 42 |
+ filt_exited = append(filt_exited, code) |
|
| 43 |
+ } |
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 30 | 46 |
names := map[string][]string{}
|
| 31 | 47 |
daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
|
| 32 | 48 |
names[e.ID()] = append(names[e.ID()], p) |
| ... | ... |
@@ -69,6 +87,18 @@ func (daemon *Daemon) Containers(job *engine.Job) engine.Status {
|
| 69 | 69 |
return errLast |
| 70 | 70 |
} |
| 71 | 71 |
} |
| 72 |
+ if len(filt_exited) > 0 && !container.State.IsRunning() {
|
|
| 73 |
+ should_skip := true |
|
| 74 |
+ for _, code := range filt_exited {
|
|
| 75 |
+ if code == container.State.GetExitCode() {
|
|
| 76 |
+ should_skip = false |
|
| 77 |
+ break |
|
| 78 |
+ } |
|
| 79 |
+ } |
|
| 80 |
+ if should_skip {
|
|
| 81 |
+ return nil |
|
| 82 |
+ } |
|
| 83 |
+ } |
|
| 72 | 84 |
displayed++ |
| 73 | 85 |
out := &engine.Env{}
|
| 74 | 86 |
out.Set("Id", container.ID)
|
| ... | ... |
@@ -90,6 +90,8 @@ List containers |
| 90 | 90 |
non-running ones. |
| 91 | 91 |
- **size** – 1/True/true or 0/False/false, Show the containers |
| 92 | 92 |
sizes |
| 93 |
+ - **filters** – a JSON encoded value of the filters (a map[string][]string) |
|
| 94 |
+ to process on the images list. |
|
| 93 | 95 |
|
| 94 | 96 |
Status Codes: |
| 95 | 97 |
|
| ... | ... |
@@ -759,7 +761,7 @@ Copy files or folders of container `id` |
| 759 | 759 |
|
| 760 | 760 |
|
| 761 | 761 |
- **all** – 1/True/true or 0/False/false, default false |
| 762 |
- - **filters** – a json encoded value of the filters (a map[string][]string) to process on the images list. |
|
| 762 |
+ - **filters** – a JSON encoded value of the filters (a map[string][]string) to process on the images list. |
|
| 763 | 763 |
|
| 764 | 764 |
|
| 765 | 765 |
|
| ... | ... |
@@ -794,6 +794,7 @@ further details. |
| 794 | 794 |
|
| 795 | 795 |
-a, --all=false Show all containers. Only running containers are shown by default. |
| 796 | 796 |
--before="" Show only container created before Id or Name, include non-running ones. |
| 797 |
+ -f, --filter=[] Provide filter values (i.e. 'exited=0') |
|
| 797 | 798 |
-l, --latest=false Show only the latest created container, include non-running ones. |
| 798 | 799 |
-n=-1 Show n last created containers, include non-running ones. |
| 799 | 800 |
--no-trunc=false Don't truncate output |
| ... | ... |
@@ -811,6 +812,25 @@ Running `docker ps` showing 2 linked containers. |
| 811 | 811 |
`docker ps` will show only running containers by default. To see all containers: |
| 812 | 812 |
`docker ps -a` |
| 813 | 813 |
|
| 814 |
+### Filtering |
|
| 815 |
+ |
|
| 816 |
+The filtering flag (-f or --filter) format is a "key=value" pair. If there is more |
|
| 817 |
+than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bif=baz"`) |
|
| 818 |
+ |
|
| 819 |
+Current filters: |
|
| 820 |
+ * exited (int - the code of exited containers. Only useful with '--all') |
|
| 821 |
+ |
|
| 822 |
+ |
|
| 823 |
+#### Successfully exited containers |
|
| 824 |
+ |
|
| 825 |
+ $ sudo docker ps -a --filter 'exited=0' |
|
| 826 |
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
|
| 827 |
+ ea09c3c82f6e registry:latest /srv/run.sh 2 weeks ago Exited (0) 2 weeks ago 127.0.0.1:5000->5000/tcp desperate_leakey |
|
| 828 |
+ 106ea823fe4e fedora:latest /bin/sh -c 'bash -l' 2 weeks ago Exited (0) 2 weeks ago determined_albattani |
|
| 829 |
+ 48ee228c9464 fedora:20 bash 2 weeks ago Exited (0) 2 weeks ago tender_torvalds |
|
| 830 |
+ |
|
| 831 |
+This shows all the containers that have exited with status of '0' |
|
| 832 |
+ |
|
| 814 | 833 |
## pull |
| 815 | 834 |
|
| 816 | 835 |
Usage: docker pull NAME[:TAG] |