Construct a network.Filter from the filters.Args only once per API
request so we don't waste cycles re-validating an already validated
filter. Since (*Daemon).NetworksPrune is implemented in terms of
(Cluster).GetNetworks, that method now accepts a network.Filter instead
of a filter.Args. Change the signature of (*Daemon).GetNetworks for
consistency as both of the GetNetworks methods are used by network API
route handlers.
Signed-off-by: Cory Snider <csnider@mirantis.com>
| ... | ... |
@@ -1,9 +1,9 @@ |
| 1 | 1 |
package daemon |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "github.com/moby/moby/api/types/filters" |
|
| 5 | 4 |
"github.com/moby/moby/api/types/network" |
| 6 | 5 |
lncluster "github.com/moby/moby/v2/daemon/libnetwork/cluster" |
| 6 |
+ dnetwork "github.com/moby/moby/v2/daemon/network" |
|
| 7 | 7 |
) |
| 8 | 8 |
|
| 9 | 9 |
// Cluster is the interface for [github.com/moby/moby/v2/daemon/cluster.Cluster]. |
| ... | ... |
@@ -22,6 +22,6 @@ type ClusterStatus interface {
|
| 22 | 22 |
// NetworkManager provides methods to manage networks |
| 23 | 23 |
type NetworkManager interface {
|
| 24 | 24 |
GetNetwork(input string) (network.Inspect, error) |
| 25 |
- GetNetworks(filters.Args) ([]network.Inspect, error) |
|
| 25 |
+ GetNetworks(dnetwork.Filter) ([]network.Inspect, error) |
|
| 26 | 26 |
RemoveNetwork(input string) error |
| 27 | 27 |
} |
| ... | ... |
@@ -2,6 +2,7 @@ package convert |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"strings" |
| 5 |
+ "time" |
|
| 5 | 6 |
|
| 6 | 7 |
gogotypes "github.com/gogo/protobuf/types" |
| 7 | 8 |
"github.com/moby/moby/api/types/network" |
| ... | ... |
@@ -270,6 +271,11 @@ func (nw FilterNetwork) Scope() string {
|
| 270 | 270 |
return scope.Swarm |
| 271 | 271 |
} |
| 272 | 272 |
|
| 273 |
+func (nw FilterNetwork) Created() time.Time {
|
|
| 274 |
+ t, _ := gogotypes.TimestampFromProto(nw.N.Meta.CreatedAt) |
|
| 275 |
+ return t |
|
| 276 |
+} |
|
| 277 |
+ |
|
| 273 | 278 |
func (nw FilterNetwork) HasContainerAttachments() bool {
|
| 274 | 279 |
// Not tracked in swarmkit |
| 275 | 280 |
return false |
| ... | ... |
@@ -5,7 +5,6 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/containerd/log" |
| 8 |
- "github.com/moby/moby/api/types/filters" |
|
| 9 | 8 |
"github.com/moby/moby/api/types/network" |
| 10 | 9 |
types "github.com/moby/moby/api/types/swarm" |
| 11 | 10 |
"github.com/moby/moby/v2/daemon/cluster/convert" |
| ... | ... |
@@ -16,25 +15,11 @@ import ( |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 | 18 |
// GetNetworks returns all current cluster managed networks. |
| 19 |
-func (c *Cluster) GetNetworks(filter filters.Args) ([]network.Inspect, error) {
|
|
| 20 |
- flt, err := networkSettings.NewFilter(filter) |
|
| 21 |
- if err != nil {
|
|
| 22 |
- return nil, err |
|
| 23 |
- } |
|
| 24 |
- |
|
| 25 |
- var f *swarmapi.ListNetworksRequest_Filters |
|
| 26 |
- |
|
| 27 |
- if filter.Len() > 0 {
|
|
| 28 |
- f = &swarmapi.ListNetworksRequest_Filters{}
|
|
| 29 |
- |
|
| 30 |
- if filter.Contains("name") {
|
|
| 31 |
- f.Names = filter.Get("name")
|
|
| 32 |
- f.NamePrefixes = filter.Get("name")
|
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- if filter.Contains("id") {
|
|
| 36 |
- f.IDPrefixes = filter.Get("id")
|
|
| 37 |
- } |
|
| 19 |
+func (c *Cluster) GetNetworks(filter networkSettings.Filter) ([]network.Inspect, error) {
|
|
| 20 |
+ f := &swarmapi.ListNetworksRequest_Filters{
|
|
| 21 |
+ Names: filter.Get("name"),
|
|
| 22 |
+ NamePrefixes: filter.Get("name"),
|
|
| 23 |
+ IDPrefixes: filter.Get("id"),
|
|
| 38 | 24 |
} |
| 39 | 25 |
|
| 40 | 26 |
list, err := c.listNetworks(context.TODO(), f) |
| ... | ... |
@@ -46,7 +31,7 @@ func (c *Cluster) GetNetworks(filter filters.Args) ([]network.Inspect, error) {
|
| 46 | 46 |
if n.Spec.Annotations.Labels["com.docker.swarm.predefined"] == "true" {
|
| 47 | 47 |
continue |
| 48 | 48 |
} |
| 49 |
- if flt.Matches(convert.FilterNetwork{N: n}) {
|
|
| 49 |
+ if filter.Matches(convert.FilterNetwork{N: n}) {
|
|
| 50 | 50 |
filtered = append(filtered, convert.BasicNetworkFromGRPC(*n)) |
| 51 | 51 |
} |
| 52 | 52 |
} |
| ... | ... |
@@ -17,7 +17,6 @@ import ( |
| 17 | 17 |
"github.com/docker/go-connections/nat" |
| 18 | 18 |
containertypes "github.com/moby/moby/api/types/container" |
| 19 | 19 |
"github.com/moby/moby/api/types/events" |
| 20 |
- "github.com/moby/moby/api/types/filters" |
|
| 21 | 20 |
networktypes "github.com/moby/moby/api/types/network" |
| 22 | 21 |
clustertypes "github.com/moby/moby/v2/daemon/cluster/provider" |
| 23 | 22 |
"github.com/moby/moby/v2/daemon/config" |
| ... | ... |
@@ -591,16 +590,11 @@ func (daemon *Daemon) deleteNetwork(nw *libnetwork.Network, dynamic bool) error |
| 591 | 591 |
} |
| 592 | 592 |
|
| 593 | 593 |
// GetNetworks returns a list of all networks |
| 594 |
-func (daemon *Daemon) GetNetworks(filter filters.Args, config backend.NetworkListConfig) ([]networktypes.Inspect, error) {
|
|
| 595 |
- flt, err := network.NewFilter(filter) |
|
| 596 |
- if err != nil {
|
|
| 597 |
- return nil, err |
|
| 598 |
- } |
|
| 599 |
- |
|
| 594 |
+func (daemon *Daemon) GetNetworks(filter network.Filter, config backend.NetworkListConfig) ([]networktypes.Inspect, error) {
|
|
| 600 | 595 |
allNetworks := daemon.getAllNetworks() |
| 601 | 596 |
networks := make([]networktypes.Inspect, 0, len(allNetworks)) |
| 602 | 597 |
for _, n := range allNetworks {
|
| 603 |
- if flt.Matches(n) {
|
|
| 598 |
+ if filter.Matches(n) {
|
|
| 604 | 599 |
nr := buildNetworkResource(n) |
| 605 | 600 |
if config.Detailed {
|
| 606 | 601 |
nr.Containers = buildContainerAttachments(n) |
| ... | ... |
@@ -1,7 +1,10 @@ |
| 1 | 1 |
package network |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "time" |
|
| 5 |
+ |
|
| 4 | 6 |
"github.com/moby/moby/api/types/filters" |
| 7 |
+ "github.com/moby/moby/v2/daemon/internal/timestamp" |
|
| 5 | 8 |
"github.com/moby/moby/v2/errdefs" |
| 6 | 9 |
"github.com/pkg/errors" |
| 7 | 10 |
) |
| ... | ... |
@@ -10,6 +13,7 @@ type Filter struct {
|
| 10 | 10 |
args filters.Args |
| 11 | 11 |
|
| 12 | 12 |
filterByUse, danglingOnly bool |
| 13 |
+ until time.Time |
|
| 13 | 14 |
} |
| 14 | 15 |
|
| 15 | 16 |
type FilterNetwork interface {
|
| ... | ... |
@@ -18,6 +22,7 @@ type FilterNetwork interface {
|
| 18 | 18 |
ID() string |
| 19 | 19 |
Labels() map[string]string |
| 20 | 20 |
Scope() string |
| 21 |
+ Created() time.Time |
|
| 21 | 22 |
HasContainerAttachments() bool |
| 22 | 23 |
HasServiceAttachments() bool |
| 23 | 24 |
} |
| ... | ... |
@@ -46,7 +51,31 @@ func NewFilter(args filters.Args) (Filter, error) {
|
| 46 | 46 |
if err := args.WalkValues("type", validateNetworkTypeFilter); err != nil {
|
| 47 | 47 |
return Filter{}, err
|
| 48 | 48 |
} |
| 49 |
- return Filter{args: args, filterByUse: filterByUse, danglingOnly: danglingOnly}, nil
|
|
| 49 |
+ until := time.Time{}
|
|
| 50 |
+ if untilFilters := args.Get("until"); len(untilFilters) > 0 {
|
|
| 51 |
+ if len(untilFilters) > 1 {
|
|
| 52 |
+ return Filter{}, errdefs.InvalidParameter(errors.New("more than one until filter specified"))
|
|
| 53 |
+ } |
|
| 54 |
+ ts, err := timestamp.GetTimestamp(untilFilters[0], time.Now()) |
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ return Filter{}, errdefs.InvalidParameter(err)
|
|
| 57 |
+ } |
|
| 58 |
+ seconds, nanoseconds, err := timestamp.ParseTimestamps(ts, 0) |
|
| 59 |
+ if err != nil {
|
|
| 60 |
+ return Filter{}, errdefs.InvalidParameter(err)
|
|
| 61 |
+ } |
|
| 62 |
+ until = time.Unix(seconds, nanoseconds) |
|
| 63 |
+ } |
|
| 64 |
+ return Filter{
|
|
| 65 |
+ args: args, |
|
| 66 |
+ filterByUse: filterByUse, |
|
| 67 |
+ danglingOnly: danglingOnly, |
|
| 68 |
+ until: until, |
|
| 69 |
+ }, nil |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+func (f Filter) Get(key string) []string {
|
|
| 73 |
+ return f.args.Get(key) |
|
| 50 | 74 |
} |
| 51 | 75 |
|
| 52 | 76 |
// Matches returns true if nw satisfies the filter criteria. |
| ... | ... |
@@ -67,6 +96,10 @@ func (f Filter) Matches(nw FilterNetwork) bool {
|
| 67 | 67 |
!f.args.MatchKVList("label", nw.Labels()) {
|
| 68 | 68 |
return false |
| 69 | 69 |
} |
| 70 |
+ if f.args.Contains("label!") &&
|
|
| 71 |
+ f.args.MatchKVList("label!", nw.Labels()) {
|
|
| 72 |
+ return false |
|
| 73 |
+ } |
|
| 70 | 74 |
if f.args.Contains("scope") &&
|
| 71 | 75 |
!f.args.ExactMatch("scope", nw.Scope()) {
|
| 72 | 76 |
return false |
| ... | ... |
@@ -84,6 +117,10 @@ func (f Filter) Matches(nw FilterNetwork) bool {
|
| 84 | 84 |
!matchesType(netTypes, nw) {
|
| 85 | 85 |
return false |
| 86 | 86 |
} |
| 87 |
+ if !f.until.IsZero() && |
|
| 88 |
+ nw.Created().After(f.until) {
|
|
| 89 |
+ return false |
|
| 90 |
+ } |
|
| 87 | 91 |
return true |
| 88 | 92 |
} |
| 89 | 93 |
|
| ... | ... |
@@ -4,6 +4,7 @@ package network |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"testing" |
| 7 |
+ "time" |
|
| 7 | 8 |
|
| 8 | 9 |
"gotest.tools/v3/assert" |
| 9 | 10 |
is "gotest.tools/v3/assert/cmp" |
| ... | ... |
@@ -20,6 +21,7 @@ type mockFilterNetwork struct {
|
| 20 | 20 |
id string |
| 21 | 21 |
labels map[string]string |
| 22 | 22 |
scope string |
| 23 |
+ created time.Time |
|
| 23 | 24 |
containers bool |
| 24 | 25 |
services bool |
| 25 | 26 |
} |
| ... | ... |
@@ -44,6 +46,10 @@ func (n mockFilterNetwork) Scope() string {
|
| 44 | 44 |
return n.scope |
| 45 | 45 |
} |
| 46 | 46 |
|
| 47 |
+func (n mockFilterNetwork) Created() time.Time {
|
|
| 48 |
+ return n.created |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 47 | 51 |
func (n mockFilterNetwork) HasContainerAttachments() bool {
|
| 48 | 52 |
return n.containers |
| 49 | 53 |
} |
| ... | ... |
@@ -55,41 +61,47 @@ func (n mockFilterNetwork) HasServiceAttachments() bool {
|
| 55 | 55 |
func TestFilter(t *testing.T) {
|
| 56 | 56 |
networks := []mockFilterNetwork{
|
| 57 | 57 |
{
|
| 58 |
- name: network.NetworkHost, |
|
| 59 |
- id: "ubfg", // ROT13(name) |
|
| 60 |
- driver: "host", |
|
| 61 |
- scope: "local", |
|
| 58 |
+ name: network.NetworkHost, |
|
| 59 |
+ id: "ubfg", // ROT13(name) |
|
| 60 |
+ driver: "host", |
|
| 61 |
+ scope: "local", |
|
| 62 |
+ created: time.Date(2025, time.June, 1, 0, 0, 0, 0, time.Local), |
|
| 62 | 63 |
}, |
| 63 | 64 |
{
|
| 64 |
- name: network.NetworkBridge, |
|
| 65 |
- id: "oevqtr", |
|
| 66 |
- driver: "bridge", |
|
| 67 |
- scope: "local", |
|
| 65 |
+ name: network.NetworkBridge, |
|
| 66 |
+ id: "oevqtr", |
|
| 67 |
+ driver: "bridge", |
|
| 68 |
+ scope: "local", |
|
| 69 |
+ created: time.Date(2025, time.June, 1, 0, 0, 0, 0, time.Local), |
|
| 68 | 70 |
}, |
| 69 | 71 |
{
|
| 70 |
- name: network.NetworkNone, |
|
| 71 |
- id: "abar", |
|
| 72 |
- driver: "null", |
|
| 73 |
- scope: "local", |
|
| 72 |
+ name: network.NetworkNone, |
|
| 73 |
+ id: "abar", |
|
| 74 |
+ driver: "null", |
|
| 75 |
+ scope: "local", |
|
| 76 |
+ created: time.Date(2025, time.June, 1, 0, 0, 0, 0, time.Local), |
|
| 74 | 77 |
}, |
| 75 | 78 |
{
|
| 76 |
- name: "myoverlay", |
|
| 77 |
- id: "zlbireynl", |
|
| 78 |
- driver: "overlay", |
|
| 79 |
- scope: "swarm", |
|
| 79 |
+ name: "myoverlay", |
|
| 80 |
+ id: "zlbireynl", |
|
| 81 |
+ driver: "overlay", |
|
| 82 |
+ scope: "swarm", |
|
| 83 |
+ created: time.Date(2024, time.June, 1, 12, 0, 0, 0, time.Local), |
|
| 80 | 84 |
}, |
| 81 | 85 |
{
|
| 82 |
- name: "mydrivernet", |
|
| 83 |
- id: "zlqevirearg", |
|
| 84 |
- driver: "mydriver", |
|
| 85 |
- scope: "local", |
|
| 86 |
- labels: map[string]string{"foo": "bar"},
|
|
| 86 |
+ name: "mydrivernet", |
|
| 87 |
+ id: "zlqevirearg", |
|
| 88 |
+ driver: "mydriver", |
|
| 89 |
+ scope: "local", |
|
| 90 |
+ labels: map[string]string{"foo": "bar"},
|
|
| 91 |
+ created: time.Date(2024, time.December, 1, 2, 0, 0, 0, time.Local), |
|
| 87 | 92 |
}, |
| 88 | 93 |
{
|
| 89 |
- name: "mykvnet", |
|
| 90 |
- id: "zlxiarg", |
|
| 91 |
- driver: "mykvdriver", |
|
| 92 |
- scope: "global", |
|
| 94 |
+ name: "mykvnet", |
|
| 95 |
+ id: "zlxiarg", |
|
| 96 |
+ driver: "mykvdriver", |
|
| 97 |
+ scope: "global", |
|
| 98 |
+ created: time.Date(2025, time.January, 1, 0, 0, 0, 0, time.Local), |
|
| 93 | 99 |
}, |
| 94 | 100 |
{
|
| 95 | 101 |
name: "networkwithcontainer", |
| ... | ... |
@@ -97,6 +109,7 @@ func TestFilter(t *testing.T) {
|
| 97 | 97 |
driver: "nwc", |
| 98 | 98 |
scope: "local", |
| 99 | 99 |
containers: true, |
| 100 |
+ created: time.Date(2025, time.June, 1, 0, 0, 0, 0, time.Local), |
|
| 100 | 101 |
}, |
| 101 | 102 |
{
|
| 102 | 103 |
name: "networkwithservice", |
| ... | ... |
@@ -104,6 +117,14 @@ func TestFilter(t *testing.T) {
|
| 104 | 104 |
driver: "nwc", |
| 105 | 105 |
scope: "local", |
| 106 | 106 |
services: true, |
| 107 |
+ created: time.Date(2025, time.June, 1, 0, 0, 0, 0, time.Local), |
|
| 108 |
+ }, |
|
| 109 |
+ {
|
|
| 110 |
+ name: "idoverlap", |
|
| 111 |
+ id: "aaaaa0my0bbbbbb", |
|
| 112 |
+ driver: "nwc", |
|
| 113 |
+ scope: "local", |
|
| 114 |
+ created: time.Date(2025, time.February, 1, 0, 0, 0, 0, time.Local), |
|
| 107 | 115 |
}, |
| 108 | 116 |
} |
| 109 | 117 |
|
| ... | ... |
@@ -142,7 +163,7 @@ func TestFilter(t *testing.T) {
|
| 142 | 142 |
{
|
| 143 | 143 |
subtest: "type=custom", |
| 144 | 144 |
filter: filters.NewArgs(filters.Arg("type", "custom")),
|
| 145 |
- results: []string{"myoverlay", "mydrivernet", "mykvnet", "networkwithcontainer", "networkwithservice"},
|
|
| 145 |
+ results: []string{"myoverlay", "mydrivernet", "mykvnet", "networkwithcontainer", "networkwithservice", "idoverlap"},
|
|
| 146 | 146 |
}, |
| 147 | 147 |
{
|
| 148 | 148 |
subtest: "type=builtin", |
| ... | ... |
@@ -157,7 +178,7 @@ func TestFilter(t *testing.T) {
|
| 157 | 157 |
{
|
| 158 | 158 |
subtest: "scope=local", |
| 159 | 159 |
filter: filters.NewArgs(filters.Arg("scope", "local")),
|
| 160 |
- results: []string{network.NetworkHost, network.NetworkBridge, network.NetworkNone, "mydrivernet", "networkwithcontainer", "networkwithservice"},
|
|
| 160 |
+ results: []string{network.NetworkHost, network.NetworkBridge, network.NetworkNone, "mydrivernet", "networkwithcontainer", "networkwithservice", "idoverlap"},
|
|
| 161 | 161 |
}, |
| 162 | 162 |
{
|
| 163 | 163 |
subtest: "scope=swarm", |
| ... | ... |
@@ -172,12 +193,12 @@ func TestFilter(t *testing.T) {
|
| 172 | 172 |
{
|
| 173 | 173 |
subtest: "dangling=true", |
| 174 | 174 |
filter: filters.NewArgs(filters.Arg("dangling", "true")),
|
| 175 |
- results: []string{"myoverlay", "mydrivernet", "mykvnet"},
|
|
| 175 |
+ results: []string{"myoverlay", "mydrivernet", "mykvnet", "idoverlap"},
|
|
| 176 | 176 |
}, |
| 177 | 177 |
{
|
| 178 | 178 |
subtest: "dangling=1", |
| 179 | 179 |
filter: filters.NewArgs(filters.Arg("dangling", "1")),
|
| 180 |
- results: []string{"myoverlay", "mydrivernet", "mykvnet"},
|
|
| 180 |
+ results: []string{"myoverlay", "mydrivernet", "mykvnet", "idoverlap"},
|
|
| 181 | 181 |
}, |
| 182 | 182 |
{
|
| 183 | 183 |
subtest: "dangling=false", |
| ... | ... |
@@ -227,6 +248,31 @@ func TestFilter(t *testing.T) {
|
| 227 | 227 |
filter: filters.NewArgs(filters.Arg("id", "argjbex")),
|
| 228 | 228 |
results: []string{"networkwithcontainer", "networkwithservice"},
|
| 229 | 229 |
}, |
| 230 |
+ {
|
|
| 231 |
+ subtest: "id=my", |
|
| 232 |
+ filter: filters.NewArgs(filters.Arg("id", "my")),
|
|
| 233 |
+ results: []string{"idoverlap"},
|
|
| 234 |
+ }, |
|
| 235 |
+ {
|
|
| 236 |
+ subtest: "label!=foo", |
|
| 237 |
+ filter: filters.NewArgs(filters.Arg("label!", "foo")),
|
|
| 238 |
+ results: []string{network.NetworkHost, network.NetworkBridge, network.NetworkNone, "myoverlay", "mykvnet", "networkwithcontainer", "networkwithservice", "idoverlap"},
|
|
| 239 |
+ }, |
|
| 240 |
+ {
|
|
| 241 |
+ subtest: "until=2025-01-01", |
|
| 242 |
+ filter: filters.NewArgs(filters.Arg("until", "2025-01-01")),
|
|
| 243 |
+ results: []string{"myoverlay", "mydrivernet", "mykvnet"},
|
|
| 244 |
+ }, |
|
| 245 |
+ {
|
|
| 246 |
+ subtest: "until=2024-12-01T01:00:00", |
|
| 247 |
+ filter: filters.NewArgs(filters.Arg("until", "2024-12-01T01:00:00")),
|
|
| 248 |
+ results: []string{"myoverlay"},
|
|
| 249 |
+ }, |
|
| 250 |
+ {
|
|
| 251 |
+ subtest: "MultipleTerms=until", |
|
| 252 |
+ filter: filters.NewArgs(filters.Arg("until", "2024-12-01T01:00:00"), filters.Arg("until", "2h")),
|
|
| 253 |
+ err: "more than one until filter specified", |
|
| 254 |
+ }, |
|
| 230 | 255 |
} |
| 231 | 256 |
|
| 232 | 257 |
for _, testCase := range testCases {
|
| ... | ... |
@@ -13,6 +13,7 @@ import ( |
| 13 | 13 |
"github.com/moby/moby/v2/daemon/internal/lazyregexp" |
| 14 | 14 |
"github.com/moby/moby/v2/daemon/internal/timestamp" |
| 15 | 15 |
"github.com/moby/moby/v2/daemon/libnetwork" |
| 16 |
+ dnetwork "github.com/moby/moby/v2/daemon/network" |
|
| 16 | 17 |
"github.com/moby/moby/v2/daemon/server/backend" |
| 17 | 18 |
"github.com/moby/moby/v2/errdefs" |
| 18 | 19 |
"github.com/pkg/errors" |
| ... | ... |
@@ -96,11 +97,9 @@ func (daemon *Daemon) ContainersPrune(ctx context.Context, pruneFilters filters. |
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 | 98 |
// localNetworksPrune removes unused local networks |
| 99 |
-func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filters.Args) *network.PruneReport {
|
|
| 99 |
+func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters dnetwork.Filter) *network.PruneReport {
|
|
| 100 | 100 |
rep := &network.PruneReport{}
|
| 101 | 101 |
|
| 102 |
- until, _ := getUntilFromPruneFilters(pruneFilters) |
|
| 103 |
- |
|
| 104 | 102 |
// When the function returns true, the walk will stop. |
| 105 | 103 |
daemon.netController.WalkNetworks(func(nw *libnetwork.Network) bool {
|
| 106 | 104 |
select {
|
| ... | ... |
@@ -112,10 +111,7 @@ func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filte |
| 112 | 112 |
if nw.ConfigOnly() {
|
| 113 | 113 |
return false |
| 114 | 114 |
} |
| 115 |
- if !until.IsZero() && nw.Created().After(until) {
|
|
| 116 |
- return false |
|
| 117 |
- } |
|
| 118 |
- if !matchLabels(pruneFilters, nw.Labels()) {
|
|
| 115 |
+ if !pruneFilters.Matches(nw) {
|
|
| 119 | 116 |
return false |
| 120 | 117 |
} |
| 121 | 118 |
if !nw.IsPruneable() {
|
| ... | ... |
@@ -137,11 +133,9 @@ func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filte |
| 137 | 137 |
var networkIsInUse = lazyregexp.New(`network ([[:alnum:]]+) is in use`) |
| 138 | 138 |
|
| 139 | 139 |
// clusterNetworksPrune removes unused cluster networks |
| 140 |
-func (daemon *Daemon) clusterNetworksPrune(ctx context.Context, pruneFilters filters.Args) (*network.PruneReport, error) {
|
|
| 140 |
+func (daemon *Daemon) clusterNetworksPrune(ctx context.Context, pruneFilters dnetwork.Filter) (*network.PruneReport, error) {
|
|
| 141 | 141 |
rep := &network.PruneReport{}
|
| 142 | 142 |
|
| 143 |
- until, _ := getUntilFromPruneFilters(pruneFilters) |
|
| 144 |
- |
|
| 145 | 143 |
cluster := daemon.GetCluster() |
| 146 | 144 |
|
| 147 | 145 |
if !cluster.IsManager() {
|
| ... | ... |
@@ -162,12 +156,6 @@ func (daemon *Daemon) clusterNetworksPrune(ctx context.Context, pruneFilters fil |
| 162 | 162 |
// Routing-mesh network removal has to be explicitly invoked by user |
| 163 | 163 |
continue |
| 164 | 164 |
} |
| 165 |
- if !until.IsZero() && nw.Created.After(until) {
|
|
| 166 |
- continue |
|
| 167 |
- } |
|
| 168 |
- if !matchLabels(pruneFilters, nw.Labels) {
|
|
| 169 |
- continue |
|
| 170 |
- } |
|
| 171 | 165 |
// https://github.com/moby/moby/issues/24186 |
| 172 | 166 |
// `docker network inspect` unfortunately displays ONLY those containers that are local to that node. |
| 173 | 167 |
// So we try to remove it anyway and check the error |
| ... | ... |
@@ -187,19 +175,20 @@ func (daemon *Daemon) clusterNetworksPrune(ctx context.Context, pruneFilters fil |
| 187 | 187 |
} |
| 188 | 188 |
|
| 189 | 189 |
// NetworksPrune removes unused networks |
| 190 |
-func (daemon *Daemon) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (*network.PruneReport, error) {
|
|
| 190 |
+func (daemon *Daemon) NetworksPrune(ctx context.Context, filterArgs filters.Args) (*network.PruneReport, error) {
|
|
| 191 | 191 |
if !daemon.pruneRunning.CompareAndSwap(false, true) {
|
| 192 | 192 |
return nil, errPruneRunning |
| 193 | 193 |
} |
| 194 | 194 |
defer daemon.pruneRunning.Store(false) |
| 195 | 195 |
|
| 196 | 196 |
// make sure that only accepted filters have been received |
| 197 |
- err := pruneFilters.Validate(networksAcceptedFilters) |
|
| 197 |
+ err := filterArgs.Validate(networksAcceptedFilters) |
|
| 198 | 198 |
if err != nil {
|
| 199 | 199 |
return nil, err |
| 200 | 200 |
} |
| 201 | 201 |
|
| 202 |
- if _, err := getUntilFromPruneFilters(pruneFilters); err != nil {
|
|
| 202 |
+ pruneFilters, err := dnetwork.NewFilter(filterArgs) |
|
| 203 |
+ if err != nil {
|
|
| 203 | 204 |
return nil, err |
| 204 | 205 |
} |
| 205 | 206 |
|
| ... | ... |
@@ -5,13 +5,14 @@ import ( |
| 5 | 5 |
|
| 6 | 6 |
"github.com/moby/moby/api/types/filters" |
| 7 | 7 |
"github.com/moby/moby/api/types/network" |
| 8 |
+ dnetwork "github.com/moby/moby/v2/daemon/network" |
|
| 8 | 9 |
"github.com/moby/moby/v2/daemon/server/backend" |
| 9 | 10 |
) |
| 10 | 11 |
|
| 11 | 12 |
// Backend is all the methods that need to be implemented |
| 12 | 13 |
// to provide network specific functionality. |
| 13 | 14 |
type Backend interface {
|
| 14 |
- GetNetworks(filters.Args, backend.NetworkListConfig) ([]network.Inspect, error) |
|
| 15 |
+ GetNetworks(dnetwork.Filter, backend.NetworkListConfig) ([]network.Inspect, error) |
|
| 15 | 16 |
CreateNetwork(ctx context.Context, nc network.CreateRequest) (*network.CreateResponse, error) |
| 16 | 17 |
ConnectContainerToNetwork(ctx context.Context, containerName, networkName string, endpointConfig *network.EndpointSettings) error |
| 17 | 18 |
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error |
| ... | ... |
@@ -22,7 +23,7 @@ type Backend interface {
|
| 22 | 22 |
// ClusterBackend is all the methods that need to be implemented |
| 23 | 23 |
// to provide cluster network specific functionality. |
| 24 | 24 |
type ClusterBackend interface {
|
| 25 |
- GetNetworks(filters.Args) ([]network.Inspect, error) |
|
| 25 |
+ GetNetworks(dnetwork.Filter) ([]network.Inspect, error) |
|
| 26 | 26 |
GetNetwork(name string) (network.Inspect, error) |
| 27 | 27 |
GetNetworksByName(name string) ([]network.Inspect, error) |
| 28 | 28 |
CreateNetwork(nc network.CreateRequest) (string, error) |
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/moby/moby/api/types/versions" |
| 12 | 12 |
"github.com/moby/moby/v2/daemon/libnetwork" |
| 13 | 13 |
"github.com/moby/moby/v2/daemon/libnetwork/scope" |
| 14 |
+ dnetwork "github.com/moby/moby/v2/daemon/network" |
|
| 14 | 15 |
"github.com/moby/moby/v2/daemon/server/backend" |
| 15 | 16 |
"github.com/moby/moby/v2/daemon/server/httputils" |
| 16 | 17 |
"github.com/moby/moby/v2/daemon/server/networkbackend" |
| ... | ... |
@@ -23,12 +24,17 @@ func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWrit |
| 23 | 23 |
return err |
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 |
- filter, err := filters.FromJSON(r.Form.Get("filters"))
|
|
| 26 |
+ filterArgs, err := filters.FromJSON(r.Form.Get("filters"))
|
|
| 27 | 27 |
if err != nil {
|
| 28 | 28 |
return err |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 |
- if err := network.ValidateFilters(filter); err != nil {
|
|
| 31 |
+ if err := network.ValidateFilters(filterArgs); err != nil {
|
|
| 32 |
+ return err |
|
| 33 |
+ } |
|
| 34 |
+ |
|
| 35 |
+ filter, err := dnetwork.NewFilter(filterArgs) |
|
| 36 |
+ if err != nil {
|
|
| 32 | 37 |
return err |
| 33 | 38 |
} |
| 34 | 39 |
|
| ... | ... |
@@ -114,10 +120,15 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r |
| 114 | 114 |
|
| 115 | 115 |
// TODO(@cpuguy83): All this logic for figuring out which network to return does not belong here |
| 116 | 116 |
// Instead there should be a backend function to just get one network. |
| 117 |
- filter := filters.NewArgs(filters.Arg("idOrName", term))
|
|
| 117 |
+ filterArgs := filters.NewArgs(filters.Arg("idOrName", term))
|
|
| 118 | 118 |
if networkScope != "" {
|
| 119 |
- filter.Add("scope", networkScope)
|
|
| 119 |
+ filterArgs.Add("scope", networkScope)
|
|
| 120 |
+ } |
|
| 121 |
+ filter, err := dnetwork.NewFilter(filterArgs) |
|
| 122 |
+ if err != nil {
|
|
| 123 |
+ return err |
|
| 120 | 124 |
} |
| 125 |
+ |
|
| 121 | 126 |
networks, _ := n.backend.GetNetworks(filter, backend.NetworkListConfig{Detailed: true, Verbose: verbose})
|
| 122 | 127 |
for _, nw := range networks {
|
| 123 | 128 |
if nw.ID == term {
|
| ... | ... |
@@ -322,7 +333,10 @@ func (n *networkRouter) findUniqueNetwork(term string) (network.Inspect, error) |
| 322 | 322 |
listByFullName := map[string]network.Inspect{}
|
| 323 | 323 |
listByPartialID := map[string]network.Inspect{}
|
| 324 | 324 |
|
| 325 |
- filter := filters.NewArgs(filters.Arg("idOrName", term))
|
|
| 325 |
+ filter, err := dnetwork.NewFilter(filters.NewArgs(filters.Arg("idOrName", term)))
|
|
| 326 |
+ if err != nil {
|
|
| 327 |
+ return network.Inspect{}, err
|
|
| 328 |
+ } |
|
| 326 | 329 |
networks, _ := n.backend.GetNetworks(filter, backend.NetworkListConfig{Detailed: true})
|
| 327 | 330 |
for _, nw := range networks {
|
| 328 | 331 |
if nw.ID == term {
|