From 4e024e3e7d4245cf05a04563908422ff55abc7d5 Mon Sep 17 00:00:00 2001 From: Sainath Grandhi Date: Fri, 27 May 2016 12:20:31 -0700 Subject: [PATCH 1/2] Adding network filter to docker ps command Signed-off-by: Sainath Grandhi Upstream-commit: 912af1ae8f22c4d9d7e478d0985a40b41ded2027 Component: engine --- components/engine/daemon/list.go | 14 +++++++ .../docs/reference/api/docker_remote_api.md | 1 + .../reference/api/docker_remote_api_v1.24.md | 1 + .../engine/docs/reference/commandline/ps.md | 13 ++++++- .../integration-cli/docker_cli_ps_test.go | 37 +++++++++++++++++++ components/engine/man/docker-ps.1.md | 1 + 6 files changed, 66 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/list.go b/components/engine/daemon/list.go index a0bf67b38b..1a26316293 100644 --- a/components/engine/daemon/list.go +++ b/components/engine/daemon/list.go @@ -33,6 +33,7 @@ var acceptedPsFilterTags = map[string]bool{ "status": true, "since": true, "volume": true, + "network": true, } // iterationAction represents possible outcomes happening during the container iteration. @@ -374,6 +375,19 @@ func includeContainerInList(container *container.Container, ctx *listContext) it } } + networkExist := fmt.Errorf("container part of network") + if ctx.filters.Include("network") { + err := ctx.filters.WalkValues("network", func(value string) error { + if network := container.NetworkSettings.Networks[value]; network != nil { + return networkExist + } + return nil + }) + if err != networkExist { + return excludeContainer + } + } + return includeContainer } diff --git a/components/engine/docs/reference/api/docker_remote_api.md b/components/engine/docs/reference/api/docker_remote_api.md index c384f7e2e4..19a11cda39 100644 --- a/components/engine/docs/reference/api/docker_remote_api.md +++ b/components/engine/docs/reference/api/docker_remote_api.md @@ -117,6 +117,7 @@ This section lists each version from latest to oldest. Each listing includes a * `POST /containers/create` now takes `StorageOpt` field. * `GET /info` now returns `SecurityOptions` field, showing if `apparmor`, `seccomp`, or `selinux` is supported. * `GET /networks` now supports filtering by `label` and `driver`. +* `GET /containers/json` now supports filtering containers by `network` name. * `POST /containers/create` now takes `MaximumIOps` and `MaximumIOBps` fields. Windows daemon only. * `POST /containers/create` now returns an HTTP 400 "bad parameter" message if no command is specified (instead of an HTTP 500 "server error") diff --git a/components/engine/docs/reference/api/docker_remote_api_v1.24.md b/components/engine/docs/reference/api/docker_remote_api_v1.24.md index 821340e05a..18cb84e9cf 100644 --- a/components/engine/docs/reference/api/docker_remote_api_v1.24.md +++ b/components/engine/docs/reference/api/docker_remote_api_v1.24.md @@ -223,6 +223,7 @@ Query Parameters: - `before`=(`` or ``) - `since`=(`` or ``) - `volume`=(`` or ``) + - `network`=(``) Status Codes: diff --git a/components/engine/docs/reference/commandline/ps.md b/components/engine/docs/reference/commandline/ps.md index 1dda728a7f..71c4fe5dc7 100644 --- a/components/engine/docs/reference/commandline/ps.md +++ b/components/engine/docs/reference/commandline/ps.md @@ -62,7 +62,7 @@ The currently supported filters are: * since (container's id or name) - filters containers created since given id or name * isolation (default|process|hyperv) (Windows daemon only) * volume (volume name or mount point) - filters containers that mount volumes. - +* network (network name) - filters containers connected to the provided network name #### Label @@ -207,6 +207,17 @@ The `volume` filter shows only containers that mount a specific volume or have a CONTAINER ID MOUNTS 9c3527ed70ce remote-volume +#### Network + +The `network` filter shows only containers that has endpoints on the provided network name. + + $docker run -d --net=net1 --name=test1 ubuntu top + $docker run -d --net=net2 --name=test2 ubuntu top + + $docker ps --filter network=net1 + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 9d4893ed80fe ubuntu "top" 10 minutes ago Up 10 minutes test1 + ## Formatting diff --git a/components/engine/integration-cli/docker_cli_ps_test.go b/components/engine/integration-cli/docker_cli_ps_test.go index 6e0ce2b392..6c07de352b 100644 --- a/components/engine/integration-cli/docker_cli_ps_test.go +++ b/components/engine/integration-cli/docker_cli_ps_test.go @@ -804,3 +804,40 @@ func (s *DockerSuite) TestPsFormatSize(c *check.C) { lines = strings.Split(out, "\n") c.Assert(lines[8], checker.HasPrefix, "size:", check.Commentf("Size should be appended on a newline")) } + +func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { + // create a container + out, _ := runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") + out, _ = runSleepingContainer(c, "--net=none", "--name=onnonenetwork") + + // Filter docker ps on network bridge + out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") + containerOut := strings.TrimSpace(string(out)) + + lines := strings.Split(containerOut, "\n") + + // skip header + lines = lines[1:] + + // ps output should have only one container + c.Assert(lines, checker.HasLen, 1) + + // Making sure onbridgenetwork is on the output + c.Assert(lines[0], checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n")) + + // Filter docker ps on networks bridge and none + out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") + containerOut = strings.TrimSpace(string(out)) + + lines = strings.Split(containerOut, "\n") + + // skip header + lines = lines[1:] + + //ps output should have both the containers + c.Assert(lines, checker.HasLen, 2) + + // Making sure onbridgenetwork and onnonenetwork is on the output + c.Assert(lines[0], checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n")) + c.Assert(lines[1], checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n")) +} diff --git a/components/engine/man/docker-ps.1.md b/components/engine/man/docker-ps.1.md index f567966487..0c2404b573 100644 --- a/components/engine/man/docker-ps.1.md +++ b/components/engine/man/docker-ps.1.md @@ -36,6 +36,7 @@ the running containers. - since=(|) - ancestor=([:tag]||) - containers created from an image or a descendant. - volume=(|) + - network=() - containers connected to the provided network name **--format**="*TEMPLATE*" Pretty-print containers using a Go template. From 94abb349403f468c5d2fb78d042c62121016335f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 6 Jun 2016 02:04:33 +0200 Subject: [PATCH 2/2] add support for filtering by network ID This adds support for filtering by network ID, to be consistent with other filter options. Note that only *full* matches are returned; this is consistent with other filters (e.g. volume), that also return full matches only. Signed-off-by: Sebastiaan van Stijn Upstream-commit: 7c46ba02e694ae540866b29ebf0dab76e556cc13 Component: engine --- components/engine/daemon/list.go | 7 +++- .../docs/reference/api/docker_remote_api.md | 2 +- .../reference/api/docker_remote_api_v1.24.md | 2 +- .../engine/docs/reference/commandline/ps.md | 32 +++++++++++---- .../integration-cli/docker_cli_ps_test.go | 39 +++++++++++++++---- components/engine/man/docker-ps.1.md | 2 +- 6 files changed, 65 insertions(+), 19 deletions(-) diff --git a/components/engine/daemon/list.go b/components/engine/daemon/list.go index 1a26316293..fd5b78dd60 100644 --- a/components/engine/daemon/list.go +++ b/components/engine/daemon/list.go @@ -378,9 +378,14 @@ func includeContainerInList(container *container.Container, ctx *listContext) it networkExist := fmt.Errorf("container part of network") if ctx.filters.Include("network") { err := ctx.filters.WalkValues("network", func(value string) error { - if network := container.NetworkSettings.Networks[value]; network != nil { + if _, ok := container.NetworkSettings.Networks[value]; ok { return networkExist } + for _, nw := range container.NetworkSettings.Networks { + if nw.NetworkID == value { + return networkExist + } + } return nil }) if err != networkExist { diff --git a/components/engine/docs/reference/api/docker_remote_api.md b/components/engine/docs/reference/api/docker_remote_api.md index 19a11cda39..8b87496f2a 100644 --- a/components/engine/docs/reference/api/docker_remote_api.md +++ b/components/engine/docs/reference/api/docker_remote_api.md @@ -117,7 +117,7 @@ This section lists each version from latest to oldest. Each listing includes a * `POST /containers/create` now takes `StorageOpt` field. * `GET /info` now returns `SecurityOptions` field, showing if `apparmor`, `seccomp`, or `selinux` is supported. * `GET /networks` now supports filtering by `label` and `driver`. -* `GET /containers/json` now supports filtering containers by `network` name. +* `GET /containers/json` now supports filtering containers by `network` name or id. * `POST /containers/create` now takes `MaximumIOps` and `MaximumIOBps` fields. Windows daemon only. * `POST /containers/create` now returns an HTTP 400 "bad parameter" message if no command is specified (instead of an HTTP 500 "server error") diff --git a/components/engine/docs/reference/api/docker_remote_api_v1.24.md b/components/engine/docs/reference/api/docker_remote_api_v1.24.md index 18cb84e9cf..d525a71944 100644 --- a/components/engine/docs/reference/api/docker_remote_api_v1.24.md +++ b/components/engine/docs/reference/api/docker_remote_api_v1.24.md @@ -223,7 +223,7 @@ Query Parameters: - `before`=(`` or ``) - `since`=(`` or ``) - `volume`=(`` or ``) - - `network`=(``) + - `network`=(`` or ``) Status Codes: diff --git a/components/engine/docs/reference/commandline/ps.md b/components/engine/docs/reference/commandline/ps.md index 71c4fe5dc7..c661c653dc 100644 --- a/components/engine/docs/reference/commandline/ps.md +++ b/components/engine/docs/reference/commandline/ps.md @@ -62,7 +62,7 @@ The currently supported filters are: * since (container's id or name) - filters containers created since given id or name * isolation (default|process|hyperv) (Windows daemon only) * volume (volume name or mount point) - filters containers that mount volumes. -* network (network name) - filters containers connected to the provided network name +* network (network id or name) - filters containers connected to the provided network #### Label @@ -209,15 +209,33 @@ The `volume` filter shows only containers that mount a specific volume or have a #### Network -The `network` filter shows only containers that has endpoints on the provided network name. +The `network` filter shows only containers that are connected to a network with +a given name or id. - $docker run -d --net=net1 --name=test1 ubuntu top - $docker run -d --net=net2 --name=test2 ubuntu top +The following filter matches all containers that are connected to a network +with a name containing `net1`. - $docker ps --filter network=net1 - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 9d4893ed80fe ubuntu "top" 10 minutes ago Up 10 minutes test1 +```bash +$ docker run -d --net=net1 --name=test1 ubuntu top +$ docker run -d --net=net2 --name=test2 ubuntu top +$ docker ps --filter network=net1 +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +9d4893ed80fe ubuntu "top" 10 minutes ago Up 10 minutes test1 +``` + +The network filter matches on both the network's name and id. The following +example shows all containers that are attached to the `net1` network, using +the network id as a filter; + +```bash +$ docker network inspect --format "{{.ID}}" net1 +8c0b4110ae930dbe26b258de9bc34a03f98056ed6f27f991d32919bfe401d7c5 + +$ docker ps --filter network=8c0b4110ae930dbe26b258de9bc34a03f98056ed6f27f991d32919bfe401d7c5 +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +9d4893ed80fe ubuntu "top" 10 minutes ago Up 10 minutes test1 +``` ## Formatting diff --git a/components/engine/integration-cli/docker_cli_ps_test.go b/components/engine/integration-cli/docker_cli_ps_test.go index 6c07de352b..a4ee9a9f65 100644 --- a/components/engine/integration-cli/docker_cli_ps_test.go +++ b/components/engine/integration-cli/docker_cli_ps_test.go @@ -806,15 +806,30 @@ func (s *DockerSuite) TestPsFormatSize(c *check.C) { } func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { - // create a container - out, _ := runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") - out, _ = runSleepingContainer(c, "--net=none", "--name=onnonenetwork") + // TODO default network on Windows is not called "bridge", and creating a + // custom network fails on Windows fails with "Error response from daemon: plugin not found") + testRequires(c, DaemonIsLinux) + + // create some containers + runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") + runSleepingContainer(c, "--net=none", "--name=onnonenetwork") + + // Filter docker ps on non existing network + out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist") + containerOut := strings.TrimSpace(string(out)) + lines := strings.Split(containerOut, "\n") + + // skip header + lines = lines[1:] + + // ps output should have no containers + c.Assert(lines, checker.HasLen, 0) // Filter docker ps on network bridge out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") - containerOut := strings.TrimSpace(string(out)) + containerOut = strings.TrimSpace(string(out)) - lines := strings.Split(containerOut, "\n") + lines = strings.Split(containerOut, "\n") // skip header lines = lines[1:] @@ -823,7 +838,7 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { c.Assert(lines, checker.HasLen, 1) // Making sure onbridgenetwork is on the output - c.Assert(lines[0], checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n")) + c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n")) // Filter docker ps on networks bridge and none out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") @@ -838,6 +853,14 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { c.Assert(lines, checker.HasLen, 2) // Making sure onbridgenetwork and onnonenetwork is on the output - c.Assert(lines[0], checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n")) - c.Assert(lines[1], checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n")) + c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n")) + c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n")) + + nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge") + + // Filter by network ID + out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID) + containerOut = strings.TrimSpace(string(out)) + + c.Assert(containerOut, checker.Contains, "onbridgenetwork") } diff --git a/components/engine/man/docker-ps.1.md b/components/engine/man/docker-ps.1.md index 0c2404b573..14c770121f 100644 --- a/components/engine/man/docker-ps.1.md +++ b/components/engine/man/docker-ps.1.md @@ -36,7 +36,7 @@ the running containers. - since=(|) - ancestor=([:tag]||) - containers created from an image or a descendant. - volume=(|) - - network=() - containers connected to the provided network name + - network=(|) - containers connected to the provided network **--format**="*TEMPLATE*" Pretty-print containers using a Go template.