diff --git a/daemon/network/filter.go b/daemon/network/filter.go index 893f707f7b..9ce28e3dcd 100644 --- a/daemon/network/filter.go +++ b/daemon/network/filter.go @@ -2,8 +2,6 @@ package network import ( "fmt" - "regexp" - "strings" "github.com/docker/docker/runconfig" "github.com/docker/engine-api/types/filters" @@ -13,27 +11,13 @@ import ( type filterHandler func([]libnetwork.Network, string) ([]libnetwork.Network, error) var ( - // supportedFilters predefined some supported filter handler function - supportedFilters = map[string]filterHandler{ - "type": filterNetworkByType, - "name": filterNetworkByName, - "id": filterNetworkByID, + // AcceptedFilters is an acceptable filters for validation + AcceptedFilters = map[string]bool{ + "type": true, + "name": true, + "id": true, + "label": true, } - - // AcceptedFilters is an acceptable filter flag list - // generated for validation. e.g. - // acceptedFilters = map[string]bool{ - // "type": true, - // "name": true, - // "id": true, - // } - AcceptedFilters = func() map[string]bool { - ret := make(map[string]bool) - for k := range supportedFilters { - ret[k] = true - } - return ret - }() ) func filterNetworkByType(nws []libnetwork.Network, netType string) (retNws []libnetwork.Network, err error) { @@ -56,34 +40,6 @@ func filterNetworkByType(nws []libnetwork.Network, netType string) (retNws []lib return retNws, nil } -func filterNetworkByName(nws []libnetwork.Network, name string) (retNws []libnetwork.Network, err error) { - for _, nw := range nws { - // exact match (fast path) - if nw.Name() == name { - retNws = append(retNws, nw) - continue - } - - // regexp match (slow path) - match, err := regexp.MatchString(name, nw.Name()) - if err != nil || !match { - continue - } else { - retNws = append(retNws, nw) - } - } - return retNws, nil -} - -func filterNetworkByID(nws []libnetwork.Network, id string) (retNws []libnetwork.Network, err error) { - for _, nw := range nws { - if strings.HasPrefix(nw.ID(), id) { - retNws = append(retNws, nw) - } - } - return retNws, nil -} - // FilterNetworks filters network list according to user specified filter // and returns user chosen networks func FilterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork.Network, error) { @@ -93,18 +49,40 @@ func FilterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork } var displayNet []libnetwork.Network - for fkey, fhandler := range supportedFilters { - errFilter := filter.WalkValues(fkey, func(fval string) error { - passList, err := fhandler(nws, fval) + for _, nw := range nws { + if filter.Include("name") { + if !filter.Match("name", nw.Name()) { + continue + } + } + if filter.Include("id") { + if !filter.Match("id", nw.ID()) { + continue + } + } + if filter.Include("label") { + if !filter.MatchKVList("label", nw.Info().Labels()) { + continue + } + } + displayNet = append(displayNet, nw) + } + + if filter.Include("type") { + var typeNet []libnetwork.Network + errFilter := filter.WalkValues("type", func(fval string) error { + passList, err := filterNetworkByType(displayNet, fval) if err != nil { return err } - displayNet = append(displayNet, passList...) + typeNet = append(typeNet, passList...) return nil }) if errFilter != nil { return nil, errFilter } + displayNet = typeNet } + return displayNet, nil } diff --git a/docs/reference/api/docker_remote_api.md b/docs/reference/api/docker_remote_api.md index cc61e080b1..39bf8a3369 100644 --- a/docs/reference/api/docker_remote_api.md +++ b/docs/reference/api/docker_remote_api.md @@ -118,6 +118,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`. ### v1.23 API changes diff --git a/docs/reference/api/docker_remote_api_v1.24.md b/docs/reference/api/docker_remote_api_v1.24.md index c898f44bbb..b5f9a1ec5f 100644 --- a/docs/reference/api/docker_remote_api_v1.24.md +++ b/docs/reference/api/docker_remote_api_v1.24.md @@ -2961,8 +2961,9 @@ Content-Type: application/json Query Parameters: - **filters** - JSON encoded network list filter. The filter value is one of: - - `name=` Matches all or part of a network name. - `id=` Matches all or part of a network id. + - `label=` or `label==` of a network label. + - `name=` Matches all or part of a network name. - `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks. Status Codes: diff --git a/docs/reference/commandline/network_ls.md b/docs/reference/commandline/network_ls.md index b12957a3a4..564c8be9d2 100644 --- a/docs/reference/commandline/network_ls.md +++ b/docs/reference/commandline/network_ls.md @@ -52,54 +52,10 @@ Multiple filter flags are combined as an `OR` filter. For example, The currently supported filters are: * id (network's id) +* label (`label=` or `label==`) * name (network's name) * type (custom|builtin) -#### Type - -The `type` filter supports two values; `builtin` displays predefined networks -(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. - -The following filter matches all user defined networks: - -```bash -$ docker network ls --filter type=custom -NETWORK ID NAME DRIVER -95e74588f40d foo bridge -63d1ff1f77b0 dev bridge -``` - -By having this flag it allows for batch cleanup. For example, use this filter -to delete all user defined networks: - -```bash -$ docker network rm `docker network ls --filter type=custom -q` -``` - -A warning will be issued when trying to remove a network that has containers -attached. - -#### Name - -The `name` filter matches on all or part of a network's name. - -The following filter matches all networks with a name containing the `foobar` string. - -```bash -$ docker network ls --filter name=foobar -NETWORK ID NAME DRIVER -06e7eef0a170 foobar bridge -``` - -You can also filter for a substring in a name as this shows: - -```bash -$ docker network ls --filter name=foo -NETWORK ID NAME DRIVER -95e74588f40d foo bridge -06e7eef0a170 foobar bridge -``` - #### ID The `id` filter matches on all or part of a network's ID. @@ -125,6 +81,73 @@ NETWORK ID NAME DRIVER 95e74588f40d foo bridge ``` +#### Label + +The `label` filter matches containers based on the presence of a `label` alone or a `label` and a +value. + +The following filter matches networks with the `usage` label regardless of its value. + +```bash +$ docker network ls -f "label=usage" +NETWORK ID NAME DRIVER +db9db329f835 test1 bridge +f6e212da9dfd test2 bridge +``` + +The following filter matches containers with the `usage` label with the `prod` value. + +```bash +$ docker network ls -f "label=usage=prod" +NETWORK ID NAME DRIVER +f6e212da9dfd test2 bridge +``` + +#### Name + +The `name` filter matches on all or part of a network's name. + +The following filter matches all networks with a name containing the `foobar` string. + +```bash +$ docker network ls --filter name=foobar +NETWORK ID NAME DRIVER +06e7eef0a170 foobar bridge +``` + +You can also filter for a substring in a name as this shows: + +```bash +$ docker network ls --filter name=foo +NETWORK ID NAME DRIVER +95e74588f40d foo bridge +06e7eef0a170 foobar bridge +``` + +#### Type + +The `type` filter supports two values; `builtin` displays predefined networks +(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. + +The following filter matches all user defined networks: + +```bash +$ docker network ls --filter type=custom +NETWORK ID NAME DRIVER +95e74588f40d foo bridge +63d1ff1f77b0 dev bridge +``` + +By having this flag it allows for batch cleanup. For example, use this filter +to delete all user defined networks: + +```bash +$ docker network rm `docker network ls --filter type=custom -q` +``` + +A warning will be issued when trying to remove a network that has containers +attached. + ## Related information * [network disconnect ](network_disconnect.md) diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index 429a2fffb3..2bccf84831 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -309,16 +309,23 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) { } func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) { + testNet := "testnet1" + testLabel := "foo" + testValue := "bar" out, _ := dockerCmd(c, "network", "create", "dev") defer func() { dockerCmd(c, "network", "rm", "dev") + dockerCmd(c, "network", "rm", testNet) }() networkID := strings.TrimSpace(out) - // filter with partial ID and partial name - // only show 'bridge' and 'dev' network - out, _ = dockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5], "-f", "name=dge") - assertNwList(c, out, []string{"bridge", "dev"}) + // filter with partial ID + // only show 'dev' network + out, _ = dockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5]) + assertNwList(c, out, []string{"dev"}) + + out, _ = dockerCmd(c, "network", "ls", "-f", "name=dge") + assertNwList(c, out, []string{"bridge"}) // only show built-in network (bridge, none, host) out, _ = dockerCmd(c, "network", "ls", "-f", "type=builtin") @@ -332,6 +339,19 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) { // it should be equivalent of ls without option out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin") assertNwList(c, out, []string{"bridge", "dev", "host", "none"}) + + out, _ = dockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet) + assertNwIsAvailable(c, testNet) + + out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel) + assertNwList(c, out, []string{testNet}) + + out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel+"="+testValue) + assertNwList(c, out, []string{testNet}) + + out, _ = dockerCmd(c, "network", "ls", "-f", "label=nonexistent") + outArr := strings.Split(strings.TrimSpace(out), "\n") + c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out)) } func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) { diff --git a/man/docker-network-ls.1.md b/man/docker-network-ls.1.md index 56a8334ae4..ff459059e7 100644 --- a/man/docker-network-ls.1.md +++ b/man/docker-network-ls.1.md @@ -47,54 +47,10 @@ Multiple filter flags are combined as an `OR` filter. For example, The currently supported filters are: * id (network's id) +* label (`label=` or `label==`) * name (network's name) * type (custom|builtin) -#### Type - -The `type` filter supports two values; `builtin` displays predefined networks -(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. - -The following filter matches all user defined networks: - -```bash -$ docker network ls --filter type=custom -NETWORK ID NAME DRIVER -95e74588f40d foo bridge -63d1ff1f77b0 dev bridge -``` - -By having this flag it allows for batch cleanup. For example, use this filter -to delete all user defined networks: - -```bash -$ docker network rm `docker network ls --filter type=custom -q` -``` - -A warning will be issued when trying to remove a network that has containers -attached. - -#### Name - -The `name` filter matches on all or part of a network's name. - -The following filter matches all networks with a name containing the `foobar` string. - -```bash -$ docker network ls --filter name=foobar -NETWORK ID NAME DRIVER -06e7eef0a170 foobar bridge -``` - -You can also filter for a substring in a name as this shows: - -```bash -$ docker network ls --filter name=foo -NETWORK ID NAME DRIVER -95e74588f40d foo bridge -06e7eef0a170 foobar bridge -``` - #### ID The `id` filter matches on all or part of a network's ID. @@ -120,6 +76,73 @@ NETWORK ID NAME DRIVER 95e74588f40d foo bridge ``` +#### Label + +The `label` filter matches containers based on the presence of a `label` alone or a `label` and a +value. + +The following filter matches networks with the `usage` label regardless of its value. + +```bash +$ docker network ls -f "label=usage" +NETWORK ID NAME DRIVER +db9db329f835 test1 bridge +f6e212da9dfd test2 bridge +``` + +The following filter matches containers with the `usage` label with the `prod` value. + +```bash +$ docker network ls -f "label=usage=prod" +NETWORK ID NAME DRIVER +f6e212da9dfd test2 bridge +``` + +#### Name + +The `name` filter matches on all or part of a network's name. + +The following filter matches all networks with a name containing the `foobar` string. + +```bash +$ docker network ls --filter name=foobar +NETWORK ID NAME DRIVER +06e7eef0a170 foobar bridge +``` + +You can also filter for a substring in a name as this shows: + +```bash +$ docker network ls --filter name=foo +NETWORK ID NAME DRIVER +95e74588f40d foo bridge +06e7eef0a170 foobar bridge +``` + +#### Type + +The `type` filter supports two values; `builtin` displays predefined networks +(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. + +The following filter matches all user defined networks: + +```bash +$ docker network ls --filter type=custom +NETWORK ID NAME DRIVER +95e74588f40d foo bridge +63d1ff1f77b0 dev bridge +``` + +By having this flag it allows for batch cleanup. For example, use this filter +to delete all user defined networks: + +```bash +$ docker network rm `docker network ls --filter type=custom -q` +``` + +A warning will be issued when trying to remove a network that has containers +attached. + # OPTIONS **-f**, **--filter**=*[]*