package network // import "github.com/docker/docker/daemon/network" import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/errdefs" "github.com/docker/docker/runconfig" "github.com/pkg/errors" ) // FilterNetworks filters network list according to user specified filter // and returns user chosen networks func FilterNetworks(nws []types.NetworkResource, filter filters.Args) ([]types.NetworkResource, error) { // if filter is empty, return original network list if filter.Len() == 0 { return nws, nil } displayNet := nws[:0] for _, nw := range nws { if filter.Contains("driver") { if !filter.ExactMatch("driver", nw.Driver) { continue } } if filter.Contains("name") { if !filter.Match("name", nw.Name) { continue } } if filter.Contains("id") { if !filter.Match("id", nw.ID) { continue } } if filter.Contains("label") { if !filter.MatchKVList("label", nw.Labels) { continue } } if filter.Contains("scope") { if !filter.ExactMatch("scope", nw.Scope) { continue } } if filter.Contains("idOrName") { if !filter.Match("name", nw.Name) && !filter.Match("id", nw.Name) { continue } } displayNet = append(displayNet, nw) } if values := filter.Get("dangling"); len(values) > 0 { if len(values) > 1 { return nil, errdefs.InvalidParameter(errors.New(`got more than one value for filter key "dangling"`)) } var danglingOnly bool switch values[0] { case "0", "false": // dangling is false already case "1", "true": danglingOnly = true default: return nil, errdefs.InvalidParameter(errors.New(`invalid value for filter 'dangling', must be "true" (or "1"), or "false" (or "0")`)) } displayNet = filterNetworkByUse(displayNet, danglingOnly) } if filter.Contains("type") { typeNet := []types.NetworkResource{} errFilter := filter.WalkValues("type", func(fval string) error { passList, err := filterNetworkByType(displayNet, fval) if err != nil { return err } typeNet = append(typeNet, passList...) return nil }) if errFilter != nil { return nil, errFilter } displayNet = typeNet } return displayNet, nil } func filterNetworkByUse(nws []types.NetworkResource, danglingOnly bool) []types.NetworkResource { retNws := []types.NetworkResource{} filterFunc := func(nw types.NetworkResource) bool { if danglingOnly { return !runconfig.IsPreDefinedNetwork(nw.Name) && len(nw.Containers) == 0 && len(nw.Services) == 0 } return runconfig.IsPreDefinedNetwork(nw.Name) || len(nw.Containers) > 0 || len(nw.Services) > 0 } for _, nw := range nws { if filterFunc(nw) { retNws = append(retNws, nw) } } return retNws } func filterNetworkByType(nws []types.NetworkResource, netType string) ([]types.NetworkResource, error) { retNws := []types.NetworkResource{} switch netType { case "builtin": for _, nw := range nws { if runconfig.IsPreDefinedNetwork(nw.Name) { retNws = append(retNws, nw) } } case "custom": for _, nw := range nws { if !runconfig.IsPreDefinedNetwork(nw.Name) { retNws = append(retNws, nw) } } default: return nil, errors.Errorf("invalid filter: 'type'='%s'", netType) } return retNws, nil }