This patch did following:
1) Make filter check logic same as `docker ps ` filters
Right now docker container logic work as following:
when same filter used like below:
-f name=jack -f name=tom
it would get all containers name is jack or tom(it is or logic)
when different filter used like below:
-f name=jack -f id=7d1
it would get all containers name is jack and id contains 7d1(it is and logic)
It would make sense in many user cases, but it did lack of compliate filter cases,
like "I want to get containers name is jack or id=7d1", it could work around use
(get id=7d1 containers' name and get name=jack containers, and then construct the
final containers, they could be done in user side use shell or rest API)
2) Fix one network filter bug which could include duplicate result
when use -f name= -f id=, it would get duplicate results
3) Make id filter same as container id filter, which means match any string.
not use prefix match.
It is for consistent match logic
Closes: #21417
Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
| ... | ... |
@@ -2,8 +2,6 @@ package network |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
- "regexp" |
|
| 6 |
- "strings" |
|
| 7 | 5 |
|
| 8 | 6 |
"github.com/docker/docker/runconfig" |
| 9 | 7 |
"github.com/docker/engine-api/types/filters" |
| ... | ... |
@@ -13,27 +11,13 @@ import ( |
| 13 | 13 |
type filterHandler func([]libnetwork.Network, string) ([]libnetwork.Network, error) |
| 14 | 14 |
|
| 15 | 15 |
var ( |
| 16 |
- // supportedFilters predefined some supported filter handler function |
|
| 17 |
- supportedFilters = map[string]filterHandler{
|
|
| 18 |
- "type": filterNetworkByType, |
|
| 19 |
- "name": filterNetworkByName, |
|
| 20 |
- "id": filterNetworkByID, |
|
| 16 |
+ // AcceptedFilters is an acceptable filters for validation |
|
| 17 |
+ AcceptedFilters = map[string]bool{
|
|
| 18 |
+ "type": true, |
|
| 19 |
+ "name": true, |
|
| 20 |
+ "id": true, |
|
| 21 |
+ "label": true, |
|
| 21 | 22 |
} |
| 22 |
- |
|
| 23 |
- // AcceptedFilters is an acceptable filter flag list |
|
| 24 |
- // generated for validation. e.g. |
|
| 25 |
- // acceptedFilters = map[string]bool{
|
|
| 26 |
- // "type": true, |
|
| 27 |
- // "name": true, |
|
| 28 |
- // "id": true, |
|
| 29 |
- // } |
|
| 30 |
- AcceptedFilters = func() map[string]bool {
|
|
| 31 |
- ret := make(map[string]bool) |
|
| 32 |
- for k := range supportedFilters {
|
|
| 33 |
- ret[k] = true |
|
| 34 |
- } |
|
| 35 |
- return ret |
|
| 36 |
- }() |
|
| 37 | 23 |
) |
| 38 | 24 |
|
| 39 | 25 |
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 |
| 56 | 56 |
return retNws, nil |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 |
-func filterNetworkByName(nws []libnetwork.Network, name string) (retNws []libnetwork.Network, err error) {
|
|
| 60 |
- for _, nw := range nws {
|
|
| 61 |
- // exact match (fast path) |
|
| 62 |
- if nw.Name() == name {
|
|
| 63 |
- retNws = append(retNws, nw) |
|
| 64 |
- continue |
|
| 65 |
- } |
|
| 66 |
- |
|
| 67 |
- // regexp match (slow path) |
|
| 68 |
- match, err := regexp.MatchString(name, nw.Name()) |
|
| 69 |
- if err != nil || !match {
|
|
| 70 |
- continue |
|
| 71 |
- } else {
|
|
| 72 |
- retNws = append(retNws, nw) |
|
| 73 |
- } |
|
| 74 |
- } |
|
| 75 |
- return retNws, nil |
|
| 76 |
-} |
|
| 77 |
- |
|
| 78 |
-func filterNetworkByID(nws []libnetwork.Network, id string) (retNws []libnetwork.Network, err error) {
|
|
| 79 |
- for _, nw := range nws {
|
|
| 80 |
- if strings.HasPrefix(nw.ID(), id) {
|
|
| 81 |
- retNws = append(retNws, nw) |
|
| 82 |
- } |
|
| 83 |
- } |
|
| 84 |
- return retNws, nil |
|
| 85 |
-} |
|
| 86 |
- |
|
| 87 | 59 |
// FilterNetworks filters network list according to user specified filter |
| 88 | 60 |
// and returns user chosen networks |
| 89 | 61 |
func FilterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork.Network, error) {
|
| ... | ... |
@@ -93,18 +49,40 @@ func FilterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork |
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 | 95 |
var displayNet []libnetwork.Network |
| 96 |
- for fkey, fhandler := range supportedFilters {
|
|
| 97 |
- errFilter := filter.WalkValues(fkey, func(fval string) error {
|
|
| 98 |
- passList, err := fhandler(nws, fval) |
|
| 96 |
+ for _, nw := range nws {
|
|
| 97 |
+ if filter.Include("name") {
|
|
| 98 |
+ if !filter.Match("name", nw.Name()) {
|
|
| 99 |
+ continue |
|
| 100 |
+ } |
|
| 101 |
+ } |
|
| 102 |
+ if filter.Include("id") {
|
|
| 103 |
+ if !filter.Match("id", nw.ID()) {
|
|
| 104 |
+ continue |
|
| 105 |
+ } |
|
| 106 |
+ } |
|
| 107 |
+ if filter.Include("label") {
|
|
| 108 |
+ if !filter.MatchKVList("label", nw.Info().Labels()) {
|
|
| 109 |
+ continue |
|
| 110 |
+ } |
|
| 111 |
+ } |
|
| 112 |
+ displayNet = append(displayNet, nw) |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ if filter.Include("type") {
|
|
| 116 |
+ var typeNet []libnetwork.Network |
|
| 117 |
+ errFilter := filter.WalkValues("type", func(fval string) error {
|
|
| 118 |
+ passList, err := filterNetworkByType(displayNet, fval) |
|
| 99 | 119 |
if err != nil {
|
| 100 | 120 |
return err |
| 101 | 121 |
} |
| 102 |
- displayNet = append(displayNet, passList...) |
|
| 122 |
+ typeNet = append(typeNet, passList...) |
|
| 103 | 123 |
return nil |
| 104 | 124 |
}) |
| 105 | 125 |
if errFilter != nil {
|
| 106 | 126 |
return nil, errFilter |
| 107 | 127 |
} |
| 128 |
+ displayNet = typeNet |
|
| 108 | 129 |
} |
| 130 |
+ |
|
| 109 | 131 |
return displayNet, nil |
| 110 | 132 |
} |
| ... | ... |
@@ -118,6 +118,7 @@ This section lists each version from latest to oldest. Each listing includes a |
| 118 | 118 |
|
| 119 | 119 |
* `POST /containers/create` now takes `StorageOpt` field. |
| 120 | 120 |
* `GET /info` now returns `SecurityOptions` field, showing if `apparmor`, `seccomp`, or `selinux` is supported. |
| 121 |
+* `GET /networks` now supports filtering by `label`. |
|
| 121 | 122 |
|
| 122 | 123 |
### v1.23 API changes |
| 123 | 124 |
|
| ... | ... |
@@ -2947,8 +2947,9 @@ Content-Type: application/json |
| 2947 | 2947 |
Query Parameters: |
| 2948 | 2948 |
|
| 2949 | 2949 |
- **filters** - JSON encoded network list filter. The filter value is one of: |
| 2950 |
- - `name=<network-name>` Matches all or part of a network name. |
|
| 2951 | 2950 |
- `id=<network-id>` Matches all or part of a network id. |
| 2951 |
+ - `label=<key>` or `label=<key>=<value>` of a network label. |
|
| 2952 |
+ - `name=<network-name>` Matches all or part of a network name. |
|
| 2952 | 2953 |
- `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks. |
| 2953 | 2954 |
|
| 2954 | 2955 |
Status Codes: |
| ... | ... |
@@ -52,32 +52,56 @@ Multiple filter flags are combined as an `OR` filter. For example, |
| 52 | 52 |
The currently supported filters are: |
| 53 | 53 |
|
| 54 | 54 |
* id (network's id) |
| 55 |
+* label (`label=<key>` or `label=<key>=<value>`) |
|
| 55 | 56 |
* name (network's name) |
| 56 | 57 |
* type (custom|builtin) |
| 57 | 58 |
|
| 58 |
-#### Type |
|
| 59 |
+#### ID |
|
| 59 | 60 |
|
| 60 |
-The `type` filter supports two values; `builtin` displays predefined networks |
|
| 61 |
-(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. |
|
| 61 |
+The `id` filter matches on all or part of a network's ID. |
|
| 62 | 62 |
|
| 63 |
-The following filter matches all user defined networks: |
|
| 63 |
+The following filter matches all networks with an ID containing the |
|
| 64 |
+`63d1ff1f77b0...` string. |
|
| 64 | 65 |
|
| 65 | 66 |
```bash |
| 66 |
-$ docker network ls --filter type=custom |
|
| 67 |
+$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 |
|
| 67 | 68 |
NETWORK ID NAME DRIVER |
| 68 |
-95e74588f40d foo bridge |
|
| 69 | 69 |
63d1ff1f77b0 dev bridge |
| 70 | 70 |
``` |
| 71 | 71 |
|
| 72 |
-By having this flag it allows for batch cleanup. For example, use this filter |
|
| 73 |
-to delete all user defined networks: |
|
| 72 |
+You can also filter for a substring in an ID as this shows: |
|
| 74 | 73 |
|
| 75 | 74 |
```bash |
| 76 |
-$ docker network rm `docker network ls --filter type=custom -q` |
|
| 75 |
+$ docker network ls --filter id=95e74588f40d |
|
| 76 |
+NETWORK ID NAME DRIVER |
|
| 77 |
+95e74588f40d foo bridge |
|
| 78 |
+ |
|
| 79 |
+$ docker network ls --filter id=95e |
|
| 80 |
+NETWORK ID NAME DRIVER |
|
| 81 |
+95e74588f40d foo bridge |
|
| 77 | 82 |
``` |
| 78 | 83 |
|
| 79 |
-A warning will be issued when trying to remove a network that has containers |
|
| 80 |
-attached. |
|
| 84 |
+#### Label |
|
| 85 |
+ |
|
| 86 |
+The `label` filter matches containers based on the presence of a `label` alone or a `label` and a |
|
| 87 |
+value. |
|
| 88 |
+ |
|
| 89 |
+The following filter matches networks with the `usage` label regardless of its value. |
|
| 90 |
+ |
|
| 91 |
+```bash |
|
| 92 |
+$ docker network ls -f "label=usage" |
|
| 93 |
+NETWORK ID NAME DRIVER |
|
| 94 |
+db9db329f835 test1 bridge |
|
| 95 |
+f6e212da9dfd test2 bridge |
|
| 96 |
+``` |
|
| 97 |
+ |
|
| 98 |
+The following filter matches containers with the `usage` label with the `prod` value. |
|
| 99 |
+ |
|
| 100 |
+```bash |
|
| 101 |
+$ docker network ls -f "label=usage=prod" |
|
| 102 |
+NETWORK ID NAME DRIVER |
|
| 103 |
+f6e212da9dfd test2 bridge |
|
| 104 |
+``` |
|
| 81 | 105 |
|
| 82 | 106 |
#### Name |
| 83 | 107 |
|
| ... | ... |
@@ -100,31 +124,30 @@ NETWORK ID NAME DRIVER |
| 100 | 100 |
06e7eef0a170 foobar bridge |
| 101 | 101 |
``` |
| 102 | 102 |
|
| 103 |
-#### ID |
|
| 103 |
+#### Type |
|
| 104 | 104 |
|
| 105 |
-The `id` filter matches on all or part of a network's ID. |
|
| 105 |
+The `type` filter supports two values; `builtin` displays predefined networks |
|
| 106 |
+(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. |
|
| 106 | 107 |
|
| 107 |
-The following filter matches all networks with an ID containing the |
|
| 108 |
-`63d1ff1f77b0...` string. |
|
| 108 |
+The following filter matches all user defined networks: |
|
| 109 | 109 |
|
| 110 | 110 |
```bash |
| 111 |
-$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 |
|
| 111 |
+$ docker network ls --filter type=custom |
|
| 112 | 112 |
NETWORK ID NAME DRIVER |
| 113 |
+95e74588f40d foo bridge |
|
| 113 | 114 |
63d1ff1f77b0 dev bridge |
| 114 | 115 |
``` |
| 115 | 116 |
|
| 116 |
-You can also filter for a substring in an ID as this shows: |
|
| 117 |
+By having this flag it allows for batch cleanup. For example, use this filter |
|
| 118 |
+to delete all user defined networks: |
|
| 117 | 119 |
|
| 118 | 120 |
```bash |
| 119 |
-$ docker network ls --filter id=95e74588f40d |
|
| 120 |
-NETWORK ID NAME DRIVER |
|
| 121 |
-95e74588f40d foo bridge |
|
| 122 |
- |
|
| 123 |
-$ docker network ls --filter id=95e |
|
| 124 |
-NETWORK ID NAME DRIVER |
|
| 125 |
-95e74588f40d foo bridge |
|
| 121 |
+$ docker network rm `docker network ls --filter type=custom -q` |
|
| 126 | 122 |
``` |
| 127 | 123 |
|
| 124 |
+A warning will be issued when trying to remove a network that has containers |
|
| 125 |
+attached. |
|
| 126 |
+ |
|
| 128 | 127 |
## Related information |
| 129 | 128 |
|
| 130 | 129 |
* [network disconnect ](network_disconnect.md) |
| ... | ... |
@@ -308,16 +308,23 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) {
|
| 308 | 308 |
} |
| 309 | 309 |
|
| 310 | 310 |
func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
|
| 311 |
+ testNet := "testnet1" |
|
| 312 |
+ testLabel := "foo" |
|
| 313 |
+ testValue := "bar" |
|
| 311 | 314 |
out, _ := dockerCmd(c, "network", "create", "dev") |
| 312 | 315 |
defer func() {
|
| 313 | 316 |
dockerCmd(c, "network", "rm", "dev") |
| 317 |
+ dockerCmd(c, "network", "rm", testNet) |
|
| 314 | 318 |
}() |
| 315 | 319 |
networkID := strings.TrimSpace(out) |
| 316 | 320 |
|
| 317 |
- // filter with partial ID and partial name |
|
| 318 |
- // only show 'bridge' and 'dev' network |
|
| 319 |
- out, _ = dockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5], "-f", "name=dge") |
|
| 320 |
- assertNwList(c, out, []string{"bridge", "dev"})
|
|
| 321 |
+ // filter with partial ID |
|
| 322 |
+ // only show 'dev' network |
|
| 323 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5]) |
|
| 324 |
+ assertNwList(c, out, []string{"dev"})
|
|
| 325 |
+ |
|
| 326 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "name=dge") |
|
| 327 |
+ assertNwList(c, out, []string{"bridge"})
|
|
| 321 | 328 |
|
| 322 | 329 |
// only show built-in network (bridge, none, host) |
| 323 | 330 |
out, _ = dockerCmd(c, "network", "ls", "-f", "type=builtin") |
| ... | ... |
@@ -331,6 +338,19 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
|
| 331 | 331 |
// it should be equivalent of ls without option |
| 332 | 332 |
out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin") |
| 333 | 333 |
assertNwList(c, out, []string{"bridge", "dev", "host", "none"})
|
| 334 |
+ |
|
| 335 |
+ out, _ = dockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet) |
|
| 336 |
+ assertNwIsAvailable(c, testNet) |
|
| 337 |
+ |
|
| 338 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel) |
|
| 339 |
+ assertNwList(c, out, []string{testNet})
|
|
| 340 |
+ |
|
| 341 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel+"="+testValue) |
|
| 342 |
+ assertNwList(c, out, []string{testNet})
|
|
| 343 |
+ |
|
| 344 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "label=nonexistent") |
|
| 345 |
+ outArr := strings.Split(strings.TrimSpace(out), "\n") |
|
| 346 |
+ c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
|
|
| 334 | 347 |
} |
| 335 | 348 |
|
| 336 | 349 |
func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) {
|
| ... | ... |
@@ -47,32 +47,56 @@ Multiple filter flags are combined as an `OR` filter. For example, |
| 47 | 47 |
The currently supported filters are: |
| 48 | 48 |
|
| 49 | 49 |
* id (network's id) |
| 50 |
+* label (`label=<key>` or `label=<key>=<value>`) |
|
| 50 | 51 |
* name (network's name) |
| 51 | 52 |
* type (custom|builtin) |
| 52 | 53 |
|
| 53 |
-#### Type |
|
| 54 |
+#### ID |
|
| 54 | 55 |
|
| 55 |
-The `type` filter supports two values; `builtin` displays predefined networks |
|
| 56 |
-(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. |
|
| 56 |
+The `id` filter matches on all or part of a network's ID. |
|
| 57 | 57 |
|
| 58 |
-The following filter matches all user defined networks: |
|
| 58 |
+The following filter matches all networks with an ID containing the |
|
| 59 |
+`63d1ff1f77b0...` string. |
|
| 59 | 60 |
|
| 60 | 61 |
```bash |
| 61 |
-$ docker network ls --filter type=custom |
|
| 62 |
+$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 |
|
| 62 | 63 |
NETWORK ID NAME DRIVER |
| 63 |
-95e74588f40d foo bridge |
|
| 64 | 64 |
63d1ff1f77b0 dev bridge |
| 65 | 65 |
``` |
| 66 | 66 |
|
| 67 |
-By having this flag it allows for batch cleanup. For example, use this filter |
|
| 68 |
-to delete all user defined networks: |
|
| 67 |
+You can also filter for a substring in an ID as this shows: |
|
| 69 | 68 |
|
| 70 | 69 |
```bash |
| 71 |
-$ docker network rm `docker network ls --filter type=custom -q` |
|
| 70 |
+$ docker network ls --filter id=95e74588f40d |
|
| 71 |
+NETWORK ID NAME DRIVER |
|
| 72 |
+95e74588f40d foo bridge |
|
| 73 |
+ |
|
| 74 |
+$ docker network ls --filter id=95e |
|
| 75 |
+NETWORK ID NAME DRIVER |
|
| 76 |
+95e74588f40d foo bridge |
|
| 72 | 77 |
``` |
| 73 | 78 |
|
| 74 |
-A warning will be issued when trying to remove a network that has containers |
|
| 75 |
-attached. |
|
| 79 |
+#### Label |
|
| 80 |
+ |
|
| 81 |
+The `label` filter matches containers based on the presence of a `label` alone or a `label` and a |
|
| 82 |
+value. |
|
| 83 |
+ |
|
| 84 |
+The following filter matches networks with the `usage` label regardless of its value. |
|
| 85 |
+ |
|
| 86 |
+```bash |
|
| 87 |
+$ docker network ls -f "label=usage" |
|
| 88 |
+NETWORK ID NAME DRIVER |
|
| 89 |
+db9db329f835 test1 bridge |
|
| 90 |
+f6e212da9dfd test2 bridge |
|
| 91 |
+``` |
|
| 92 |
+ |
|
| 93 |
+The following filter matches containers with the `usage` label with the `prod` value. |
|
| 94 |
+ |
|
| 95 |
+```bash |
|
| 96 |
+$ docker network ls -f "label=usage=prod" |
|
| 97 |
+NETWORK ID NAME DRIVER |
|
| 98 |
+f6e212da9dfd test2 bridge |
|
| 99 |
+``` |
|
| 76 | 100 |
|
| 77 | 101 |
#### Name |
| 78 | 102 |
|
| ... | ... |
@@ -95,31 +119,30 @@ NETWORK ID NAME DRIVER |
| 95 | 95 |
06e7eef0a170 foobar bridge |
| 96 | 96 |
``` |
| 97 | 97 |
|
| 98 |
-#### ID |
|
| 98 |
+#### Type |
|
| 99 | 99 |
|
| 100 |
-The `id` filter matches on all or part of a network's ID. |
|
| 100 |
+The `type` filter supports two values; `builtin` displays predefined networks |
|
| 101 |
+(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. |
|
| 101 | 102 |
|
| 102 |
-The following filter matches all networks with an ID containing the |
|
| 103 |
-`63d1ff1f77b0...` string. |
|
| 103 |
+The following filter matches all user defined networks: |
|
| 104 | 104 |
|
| 105 | 105 |
```bash |
| 106 |
-$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 |
|
| 106 |
+$ docker network ls --filter type=custom |
|
| 107 | 107 |
NETWORK ID NAME DRIVER |
| 108 |
+95e74588f40d foo bridge |
|
| 108 | 109 |
63d1ff1f77b0 dev bridge |
| 109 | 110 |
``` |
| 110 | 111 |
|
| 111 |
-You can also filter for a substring in an ID as this shows: |
|
| 112 |
+By having this flag it allows for batch cleanup. For example, use this filter |
|
| 113 |
+to delete all user defined networks: |
|
| 112 | 114 |
|
| 113 | 115 |
```bash |
| 114 |
-$ docker network ls --filter id=95e74588f40d |
|
| 115 |
-NETWORK ID NAME DRIVER |
|
| 116 |
-95e74588f40d foo bridge |
|
| 117 |
- |
|
| 118 |
-$ docker network ls --filter id=95e |
|
| 119 |
-NETWORK ID NAME DRIVER |
|
| 120 |
-95e74588f40d foo bridge |
|
| 116 |
+$ docker network rm `docker network ls --filter type=custom -q` |
|
| 121 | 117 |
``` |
| 122 | 118 |
|
| 119 |
+A warning will be issued when trying to remove a network that has containers |
|
| 120 |
+attached. |
|
| 121 |
+ |
|
| 123 | 122 |
# OPTIONS |
| 124 | 123 |
|
| 125 | 124 |
**-f**, **--filter**=*[]* |