Skip to content

Commit 29eb80e

Browse files
author
Wayne Song
committedJan 5, 2017
Support more filters in network list operations
This is necessary when doing `docker stack rm` in Docker 1.13+ engines, because the CLI client deletes networks by doing a network list call with a label filter and then deleting everything that gets returned. If you do this against Swarm, then you wind up deleting all of your networks. Signed-off-by: Wayne Song <[email protected]>
1 parent 1537eeb commit 29eb80e

File tree

3 files changed

+76
-29
lines changed

3 files changed

+76
-29
lines changed
 

‎api/handlers.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ func getNetworks(c *context, w http.ResponseWriter, r *http.Request) {
277277
}
278278

279279
out := []*apitypes.NetworkResource{}
280-
networks := c.cluster.Networks().Filter(filters.Get("name"), filters.Get("id"), types)
280+
networks := c.cluster.Networks().Filter(filters)
281281
for _, network := range networks {
282282
tmp := (*network).NetworkResource
283283
if tmp.Scope == "local" {

‎cluster/network.go

+25-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"strings"
55

66
"github.com/docker/docker/api/types"
7+
"github.com/docker/docker/api/types/filters"
78
"github.com/docker/docker/pkg/stringid"
89
)
910

@@ -45,35 +46,43 @@ func (networks Networks) Uniq() Networks {
4546
return uniq
4647
}
4748

48-
// Filter returns networks filtered by names or ids
49-
func (networks Networks) Filter(names []string, ids []string, types []string) Networks {
50-
typeFilter := func(network *Network) bool {
51-
if len(types) > 0 {
52-
for _, typ := range types {
53-
if typ == "custom" && !network.isPreDefined() {
54-
return true
55-
}
56-
if typ == "builtin" && network.isPreDefined() {
57-
return true
58-
}
49+
// Filter returns networks filtered by names, IDs, labels, etc.
50+
func (networks Networks) Filter(filter filters.Args) Networks {
51+
includeFilter := func(network *Network) bool {
52+
for _, typ := range filter.Get("type") {
53+
if typ == "custom" && network.isPreDefined() {
54+
return false
55+
}
56+
if typ == "builtin" && !network.isPreDefined() {
57+
return false
58+
}
59+
}
60+
if filter.Include("label") {
61+
if !filter.MatchKVList("label", network.Labels) {
62+
return false
63+
}
64+
}
65+
if filter.Include("driver") {
66+
if !filter.ExactMatch("driver", network.Driver) {
67+
return false
5968
}
60-
} else {
61-
return true
6269
}
63-
return false
70+
return true
6471
}
6572

73+
names := filter.Get("name")
74+
ids := filter.Get("id")
6675
out := Networks{}
6776
if len(names) == 0 && len(ids) == 0 {
6877
for _, network := range networks.Uniq() {
69-
if typeFilter(network) {
78+
if includeFilter(network) {
7079
out = append(out, network)
7180
}
7281
}
7382
} else {
7483
for _, idOrName := range append(names, ids...) {
7584
if network := networks.Get(idOrName); network != nil {
76-
if typeFilter(network) {
85+
if includeFilter(network) {
7786
out = append(out, network)
7887
}
7988
}

‎cluster/network_test.go

+50-12
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,76 @@
11
package cluster
22

33
import (
4+
"sort"
45
"testing"
56

67
"github.com/docker/docker/api/types"
8+
"github.com/docker/docker/api/types/filters"
79
"github.com/stretchr/testify/assert"
810
)
911

1012
func TestNetworksFilter(t *testing.T) {
1113
engine := &Engine{ID: "id"}
1214
networks := Networks{
1315
{types.NetworkResource{
14-
ID: "ababababab",
15-
Name: "something",
16+
ID: "ababababab",
17+
Name: "something",
18+
Driver: "overlay",
19+
Labels: map[string]string{"testlabel": "testvalue1"},
1620
}, engine},
1721
{types.NetworkResource{
18-
ID: "aaaaaaaaaa1",
19-
Name: "network_name",
22+
ID: "aaaaaaaaaa1",
23+
Name: "network_name",
24+
Driver: "bridge",
25+
Labels: map[string]string{"testlabel": "testvalue2"},
2026
}, engine},
2127
{types.NetworkResource{
22-
ID: "bbbbbbbbbb",
23-
Name: "somethingelse",
28+
ID: "bbbbbbbbbb",
29+
Name: "somethingelse",
30+
Driver: "overlay",
31+
Labels: map[string]string{"testlabel": "testvalue3"},
2432
}, engine},
2533
{types.NetworkResource{
26-
ID: "aaaaaaaaa2",
27-
Name: "foo",
34+
ID: "aaaaaaaaaa2",
35+
Name: "host",
36+
Driver: "bridge",
2837
}, engine},
2938
}
3039

31-
filtered := networks.Filter([]string{"network_name"}, []string{"abababab"}, nil)
32-
assert.Equal(t, len(filtered), 2)
33-
for _, network := range filtered {
34-
assert.True(t, network.ID == "aaaaaaaaaa1" || network.ID == "ababababab")
40+
checkNetworks := func(t *testing.T, filtered Networks, expectedIDs ...string) {
41+
sort.Strings(expectedIDs)
42+
foundIDs := []string{}
43+
for _, network := range filtered {
44+
foundIDs = append(foundIDs, network.ID)
45+
}
46+
sort.Strings(foundIDs)
47+
assert.Equal(t, expectedIDs, foundIDs)
3548
}
49+
50+
filter := filters.NewArgs()
51+
filter.Add("name", "network_name")
52+
filter.Add("id", "abababab")
53+
checkNetworks(t, networks.Filter(filter), "aaaaaaaaaa1", "ababababab")
54+
55+
filter = filters.NewArgs()
56+
filter.Add("type", "builtin")
57+
checkNetworks(t, networks.Filter(filter), "aaaaaaaaaa2")
58+
59+
filter = filters.NewArgs()
60+
filter.Add("type", "custom")
61+
checkNetworks(t, networks.Filter(filter), "aaaaaaaaaa1", "ababababab", "bbbbbbbbbb")
62+
63+
filter = filters.NewArgs()
64+
filter.Add("driver", "overlay")
65+
checkNetworks(t, networks.Filter(filter), "ababababab", "bbbbbbbbbb")
66+
67+
filter = filters.NewArgs()
68+
filter.Add("label", "testlabel")
69+
checkNetworks(t, networks.Filter(filter), "aaaaaaaaaa1", "ababababab", "bbbbbbbbbb")
70+
71+
filter = filters.NewArgs()
72+
filter.Add("label", "testlabel=testvalue1")
73+
checkNetworks(t, networks.Filter(filter), "ababababab")
3674
}
3775

3876
func TestNetworkUniq(t *testing.T) {

0 commit comments

Comments
 (0)
Please sign in to comment.