浏览代码

Merge pull request #21495 from HackToday/addnetworkfilter

Add network label filter support
Vincent Demeester 9 年之前
父节点
当前提交
75cc2c926b

+ 32 - 54
daemon/network/filter.go

@@ -2,8 +2,6 @@ package network
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"regexp"
-	"strings"
 
 
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/engine-api/types/filters"
 	"github.com/docker/engine-api/types/filters"
@@ -13,27 +11,13 @@ import (
 type filterHandler func([]libnetwork.Network, string) ([]libnetwork.Network, error)
 type filterHandler func([]libnetwork.Network, string) ([]libnetwork.Network, error)
 
 
 var (
 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) {
 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
 	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
 // FilterNetworks filters network list according to user specified filter
 // and returns user chosen networks
 // and returns user chosen networks
 func FilterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork.Network, error) {
 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
 	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 {
 			if err != nil {
 				return err
 				return err
 			}
 			}
-			displayNet = append(displayNet, passList...)
+			typeNet = append(typeNet, passList...)
 			return nil
 			return nil
 		})
 		})
 		if errFilter != nil {
 		if errFilter != nil {
 			return nil, errFilter
 			return nil, errFilter
 		}
 		}
+		displayNet = typeNet
 	}
 	}
+
 	return displayNet, nil
 	return displayNet, nil
 }
 }

+ 1 - 0
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.
 * `POST /containers/create` now takes `StorageOpt` field.
 * `GET /info` now returns `SecurityOptions` field, showing if `apparmor`, `seccomp`, or `selinux` is supported.
 * `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
 ### v1.23 API changes
 
 

+ 2 - 1
docs/reference/api/docker_remote_api_v1.24.md

@@ -2961,8 +2961,9 @@ Content-Type: application/json
 Query Parameters:
 Query Parameters:
 
 
 - **filters** - JSON encoded network list filter. The filter value is one of:
 - **filters** - JSON encoded network list filter. The filter value is one of:
-  -   `name=<network-name>` Matches all or part of a network name.
   -   `id=<network-id>` Matches all or part of a network id.
   -   `id=<network-id>` Matches all or part of a network id.
+  -   `label=<key>` or `label=<key>=<value>` of a network label.
+  -   `name=<network-name>` Matches all or part of a network name.
   -   `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks.
   -   `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks.
 
 
 Status Codes:
 Status Codes:

+ 47 - 24
docs/reference/commandline/network_ls.md

@@ -52,32 +52,56 @@ Multiple filter flags are combined as an `OR` filter. For example,
 The currently supported filters are:
 The currently supported filters are:
 
 
 * id (network's id)
 * id (network's id)
+* label (`label=<key>` or `label=<key>=<value>`)
 * name (network's name)
 * name (network's name)
 * type (custom|builtin)
 * type (custom|builtin)
 
 
-#### Type
+#### ID
 
 
-The `type` filter supports two values; `builtin` displays predefined networks
-(`bridge`, `none`, `host`), whereas `custom` displays user defined networks.
+The `id` filter matches on all or part of a network's ID.
 
 
-The following filter matches all user defined networks:
+The following filter matches all networks with an ID containing the
+`63d1ff1f77b0...` string.
 
 
 ```bash
 ```bash
-$ docker network ls --filter type=custom
+$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161
 NETWORK ID          NAME                DRIVER
 NETWORK ID          NAME                DRIVER
-95e74588f40d        foo                 bridge
 63d1ff1f77b0        dev                 bridge
 63d1ff1f77b0        dev                 bridge
 ```
 ```
 
 
-By having this flag it allows for batch cleanup. For example, use this filter
-to delete all user defined networks:
+You can also filter for a substring in an ID as this shows:
 
 
 ```bash
 ```bash
-$ docker network rm `docker network ls --filter type=custom -q`
+$ docker network ls --filter id=95e74588f40d
+NETWORK ID          NAME                DRIVER
+95e74588f40d        foo                 bridge
+
+$ docker network ls --filter id=95e
+NETWORK ID          NAME                DRIVER
+95e74588f40d        foo                 bridge
 ```
 ```
 
 
-A warning will be issued when trying to remove a network that has containers
-attached.
+#### 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
 #### Name
 
 
@@ -100,31 +124,30 @@ NETWORK ID          NAME                DRIVER
 06e7eef0a170        foobar              bridge
 06e7eef0a170        foobar              bridge
 ```
 ```
 
 
-#### ID
+#### Type
 
 
-The `id` filter matches on all or part of a network's ID.
+The `type` filter supports two values; `builtin` displays predefined networks
+(`bridge`, `none`, `host`), whereas `custom` displays user defined networks.
 
 
-The following filter matches all networks with an ID containing the
-`63d1ff1f77b0...` string.
+The following filter matches all user defined networks:
 
 
 ```bash
 ```bash
-$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161
+$ docker network ls --filter type=custom
 NETWORK ID          NAME                DRIVER
 NETWORK ID          NAME                DRIVER
+95e74588f40d        foo                 bridge
 63d1ff1f77b0        dev                 bridge
 63d1ff1f77b0        dev                 bridge
 ```
 ```
 
 
-You can also filter for a substring in an ID as this shows:
+By having this flag it allows for batch cleanup. For example, use this filter
+to delete all user defined networks:
 
 
 ```bash
 ```bash
-$ docker network ls --filter id=95e74588f40d
-NETWORK ID          NAME                DRIVER
-95e74588f40d        foo                 bridge
-
-$ docker network ls --filter id=95e
-NETWORK ID          NAME                DRIVER
-95e74588f40d        foo                 bridge
+$ 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
 ## Related information
 
 
 * [network disconnect ](network_disconnect.md)
 * [network disconnect ](network_disconnect.md)

+ 24 - 4
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) {
 func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
+	testNet := "testnet1"
+	testLabel := "foo"
+	testValue := "bar"
 	out, _ := dockerCmd(c, "network", "create", "dev")
 	out, _ := dockerCmd(c, "network", "create", "dev")
 	defer func() {
 	defer func() {
 		dockerCmd(c, "network", "rm", "dev")
 		dockerCmd(c, "network", "rm", "dev")
+		dockerCmd(c, "network", "rm", testNet)
 	}()
 	}()
 	networkID := strings.TrimSpace(out)
 	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)
 	// only show built-in network (bridge, none, host)
 	out, _ = dockerCmd(c, "network", "ls", "-f", "type=builtin")
 	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
 	// it should be equivalent of ls without option
 	out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin")
 	out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin")
 	assertNwList(c, out, []string{"bridge", "dev", "host", "none"})
 	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) {
 func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) {

+ 47 - 24
man/docker-network-ls.1.md

@@ -47,32 +47,56 @@ Multiple filter flags are combined as an `OR` filter. For example,
 The currently supported filters are:
 The currently supported filters are:
 
 
 * id (network's id)
 * id (network's id)
+* label (`label=<key>` or `label=<key>=<value>`)
 * name (network's name)
 * name (network's name)
 * type (custom|builtin)
 * type (custom|builtin)
 
 
-#### Type
+#### ID
 
 
-The `type` filter supports two values; `builtin` displays predefined networks
-(`bridge`, `none`, `host`), whereas `custom` displays user defined networks.
+The `id` filter matches on all or part of a network's ID.
 
 
-The following filter matches all user defined networks:
+The following filter matches all networks with an ID containing the
+`63d1ff1f77b0...` string.
 
 
 ```bash
 ```bash
-$ docker network ls --filter type=custom
+$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161
 NETWORK ID          NAME                DRIVER
 NETWORK ID          NAME                DRIVER
-95e74588f40d        foo                 bridge
 63d1ff1f77b0        dev                 bridge
 63d1ff1f77b0        dev                 bridge
 ```
 ```
 
 
-By having this flag it allows for batch cleanup. For example, use this filter
-to delete all user defined networks:
+You can also filter for a substring in an ID as this shows:
 
 
 ```bash
 ```bash
-$ docker network rm `docker network ls --filter type=custom -q`
+$ docker network ls --filter id=95e74588f40d
+NETWORK ID          NAME                DRIVER
+95e74588f40d        foo                 bridge
+
+$ docker network ls --filter id=95e
+NETWORK ID          NAME                DRIVER
+95e74588f40d        foo                 bridge
 ```
 ```
 
 
-A warning will be issued when trying to remove a network that has containers
-attached.
+#### 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
 #### Name
 
 
@@ -95,31 +119,30 @@ NETWORK ID          NAME                DRIVER
 06e7eef0a170        foobar              bridge
 06e7eef0a170        foobar              bridge
 ```
 ```
 
 
-#### ID
+#### Type
 
 
-The `id` filter matches on all or part of a network's ID.
+The `type` filter supports two values; `builtin` displays predefined networks
+(`bridge`, `none`, `host`), whereas `custom` displays user defined networks.
 
 
-The following filter matches all networks with an ID containing the
-`63d1ff1f77b0...` string.
+The following filter matches all user defined networks:
 
 
 ```bash
 ```bash
-$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161
+$ docker network ls --filter type=custom
 NETWORK ID          NAME                DRIVER
 NETWORK ID          NAME                DRIVER
+95e74588f40d        foo                 bridge
 63d1ff1f77b0        dev                 bridge
 63d1ff1f77b0        dev                 bridge
 ```
 ```
 
 
-You can also filter for a substring in an ID as this shows:
+By having this flag it allows for batch cleanup. For example, use this filter
+to delete all user defined networks:
 
 
 ```bash
 ```bash
-$ docker network ls --filter id=95e74588f40d
-NETWORK ID          NAME                DRIVER
-95e74588f40d        foo                 bridge
-
-$ docker network ls --filter id=95e
-NETWORK ID          NAME                DRIVER
-95e74588f40d        foo                 bridge
+$ 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
 # OPTIONS
 
 
 **-f**, **--filter**=*[]*
 **-f**, **--filter**=*[]*