Add filter support for `network ls` to hide predefined network,
then user can use "docker network rm `docker network ls -f type=custom`"
to delete a bundle of userdefined networks.
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
| ... | ... |
@@ -65,7 +65,7 @@ type apiClient interface {
|
| 65 | 65 |
NetworkCreate(options types.NetworkCreate) (types.NetworkCreateResponse, error) |
| 66 | 66 |
NetworkDisconnect(networkID, containerID string) error |
| 67 | 67 |
NetworkInspect(networkID string) (types.NetworkResource, error) |
| 68 |
- NetworkList() ([]types.NetworkResource, error) |
|
| 68 |
+ NetworkList(options types.NetworkListOptions) ([]types.NetworkResource, error) |
|
| 69 | 69 |
NetworkRemove(networkID string) error |
| 70 | 70 |
RegistryLogin(auth types.AuthConfig) (types.AuthResponse, error) |
| 71 | 71 |
ServerVersion() (types.Version, error) |
| ... | ... |
@@ -3,8 +3,10 @@ package lib |
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 | 5 |
"net/http" |
| 6 |
+ "net/url" |
|
| 6 | 7 |
|
| 7 | 8 |
"github.com/docker/docker/api/types" |
| 9 |
+ "github.com/docker/docker/api/types/filters" |
|
| 8 | 10 |
) |
| 9 | 11 |
|
| 10 | 12 |
// NetworkCreate creates a new network in the docker host. |
| ... | ... |
@@ -44,9 +46,18 @@ func (cli *Client) NetworkDisconnect(networkID, containerID string) error {
|
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 | 46 |
// NetworkList returns the list of networks configured in the docker host. |
| 47 |
-func (cli *Client) NetworkList() ([]types.NetworkResource, error) {
|
|
| 47 |
+func (cli *Client) NetworkList(options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
|
| 48 |
+ query := url.Values{}
|
|
| 49 |
+ if options.Filters.Len() > 0 {
|
|
| 50 |
+ filterJSON, err := filters.ToParam(options.Filters) |
|
| 51 |
+ if err != nil {
|
|
| 52 |
+ return nil, err |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ query.Set("filters", filterJSON)
|
|
| 56 |
+ } |
|
| 48 | 57 |
var networkResources []types.NetworkResource |
| 49 |
- resp, err := cli.get("/networks", nil, nil)
|
|
| 58 |
+ resp, err := cli.get("/networks", query, nil)
|
|
| 50 | 59 |
if err != nil {
|
| 51 | 60 |
return networkResources, err |
| 52 | 61 |
} |
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"text/tabwriter" |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/docker/api/types" |
| 10 |
+ "github.com/docker/docker/api/types/filters" |
|
| 10 | 11 |
"github.com/docker/docker/api/types/network" |
| 11 | 12 |
Cli "github.com/docker/docker/cli" |
| 12 | 13 |
"github.com/docker/docker/opts" |
| ... | ... |
@@ -138,12 +139,29 @@ func (cli *DockerCli) CmdNetworkLs(args ...string) error {
|
| 138 | 138 |
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
| 139 | 139 |
noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Do not truncate the output")
|
| 140 | 140 |
|
| 141 |
+ flFilter := opts.NewListOpts(nil) |
|
| 142 |
+ cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
|
|
| 143 |
+ |
|
| 141 | 144 |
cmd.Require(flag.Exact, 0) |
| 142 |
- if err := cmd.ParseFlags(args, true); err != nil {
|
|
| 145 |
+ err := cmd.ParseFlags(args, true) |
|
| 146 |
+ if err != nil {
|
|
| 143 | 147 |
return err |
| 144 | 148 |
} |
| 145 | 149 |
|
| 146 |
- networkResources, err := cli.client.NetworkList() |
|
| 150 |
+ // Consolidate all filter flags, and sanity check them early. |
|
| 151 |
+ // They'll get process after get response from server. |
|
| 152 |
+ netFilterArgs := filters.NewArgs() |
|
| 153 |
+ for _, f := range flFilter.GetAll() {
|
|
| 154 |
+ if netFilterArgs, err = filters.ParseFlag(f, netFilterArgs); err != nil {
|
|
| 155 |
+ return err |
|
| 156 |
+ } |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ options := types.NetworkListOptions{
|
|
| 160 |
+ Filters: netFilterArgs, |
|
| 161 |
+ } |
|
| 162 |
+ |
|
| 163 |
+ networkResources, err := cli.client.NetworkList(options) |
|
| 147 | 164 |
if err != nil {
|
| 148 | 165 |
return err |
| 149 | 166 |
} |
| ... | ... |
@@ -12,6 +12,7 @@ type Backend interface {
|
| 12 | 12 |
FindNetwork(idName string) (libnetwork.Network, error) |
| 13 | 13 |
GetNetwork(idName string, by int) (libnetwork.Network, error) |
| 14 | 14 |
GetNetworksByID(partialID string) []libnetwork.Network |
| 15 |
+ GetAllNetworks() []libnetwork.Network |
|
| 15 | 16 |
CreateNetwork(name, driver string, ipam network.IPAM, |
| 16 | 17 |
options map[string]string) (libnetwork.Network, error) |
| 17 | 18 |
ConnectContainerToNetwork(containerName, networkName string) error |
| 18 | 19 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,110 @@ |
| 0 |
+package network |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "regexp" |
|
| 5 |
+ "strings" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/api/types/filters" |
|
| 8 |
+ "github.com/docker/docker/runconfig" |
|
| 9 |
+ "github.com/docker/libnetwork" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+type filterHandler func([]libnetwork.Network, string) ([]libnetwork.Network, error) |
|
| 13 |
+ |
|
| 14 |
+var ( |
|
| 15 |
+ // supportedFilters predefined some supported filter handler function |
|
| 16 |
+ supportedFilters = map[string]filterHandler{
|
|
| 17 |
+ "type": filterNetworkByType, |
|
| 18 |
+ "name": filterNetworkByName, |
|
| 19 |
+ "id": filterNetworkByID, |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ // acceptFilters is an acceptable filter flag list |
|
| 23 |
+ // generated for validation. e.g. |
|
| 24 |
+ // acceptedFilters = map[string]bool{
|
|
| 25 |
+ // "type": true, |
|
| 26 |
+ // "name": true, |
|
| 27 |
+ // "id": true, |
|
| 28 |
+ // } |
|
| 29 |
+ acceptedFilters = func() map[string]bool {
|
|
| 30 |
+ ret := make(map[string]bool) |
|
| 31 |
+ for k := range supportedFilters {
|
|
| 32 |
+ ret[k] = true |
|
| 33 |
+ } |
|
| 34 |
+ return ret |
|
| 35 |
+ }() |
|
| 36 |
+) |
|
| 37 |
+ |
|
| 38 |
+func filterNetworkByType(nws []libnetwork.Network, netType string) (retNws []libnetwork.Network, err error) {
|
|
| 39 |
+ switch netType {
|
|
| 40 |
+ case "builtin": |
|
| 41 |
+ for _, nw := range nws {
|
|
| 42 |
+ if runconfig.IsPreDefinedNetwork(nw.Name()) {
|
|
| 43 |
+ retNws = append(retNws, nw) |
|
| 44 |
+ } |
|
| 45 |
+ } |
|
| 46 |
+ case "custom": |
|
| 47 |
+ for _, nw := range nws {
|
|
| 48 |
+ if !runconfig.IsPreDefinedNetwork(nw.Name()) {
|
|
| 49 |
+ retNws = append(retNws, nw) |
|
| 50 |
+ } |
|
| 51 |
+ } |
|
| 52 |
+ default: |
|
| 53 |
+ return nil, fmt.Errorf("Invalid filter: 'type'='%s'", netType)
|
|
| 54 |
+ } |
|
| 55 |
+ return retNws, nil |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+func filterNetworkByName(nws []libnetwork.Network, name string) (retNws []libnetwork.Network, err error) {
|
|
| 59 |
+ for _, nw := range nws {
|
|
| 60 |
+ // exact match (fast path) |
|
| 61 |
+ if nw.Name() == name {
|
|
| 62 |
+ retNws = append(retNws, nw) |
|
| 63 |
+ continue |
|
| 64 |
+ } |
|
| 65 |
+ |
|
| 66 |
+ // regexp match (slow path) |
|
| 67 |
+ match, err := regexp.MatchString(name, nw.Name()) |
|
| 68 |
+ if err != nil || !match {
|
|
| 69 |
+ continue |
|
| 70 |
+ } else {
|
|
| 71 |
+ retNws = append(retNws, nw) |
|
| 72 |
+ } |
|
| 73 |
+ } |
|
| 74 |
+ return retNws, nil |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+func filterNetworkByID(nws []libnetwork.Network, id string) (retNws []libnetwork.Network, err error) {
|
|
| 78 |
+ for _, nw := range nws {
|
|
| 79 |
+ if strings.HasPrefix(nw.ID(), id) {
|
|
| 80 |
+ retNws = append(retNws, nw) |
|
| 81 |
+ } |
|
| 82 |
+ } |
|
| 83 |
+ return retNws, nil |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// filterAllNetworks filter network list according to user specified filter |
|
| 87 |
+// and return user chosen networks |
|
| 88 |
+func filterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork.Network, error) {
|
|
| 89 |
+ // if filter is empty, return original network list |
|
| 90 |
+ if filter.Len() == 0 {
|
|
| 91 |
+ return nws, nil |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ var displayNet []libnetwork.Network |
|
| 95 |
+ for fkey, fhandler := range supportedFilters {
|
|
| 96 |
+ errFilter := filter.WalkValues(fkey, func(fval string) error {
|
|
| 97 |
+ passList, err := fhandler(nws, fval) |
|
| 98 |
+ if err != nil {
|
|
| 99 |
+ return err |
|
| 100 |
+ } |
|
| 101 |
+ displayNet = append(displayNet, passList...) |
|
| 102 |
+ return nil |
|
| 103 |
+ }) |
|
| 104 |
+ if errFilter != nil {
|
|
| 105 |
+ return nil, errFilter |
|
| 106 |
+ } |
|
| 107 |
+ } |
|
| 108 |
+ return displayNet, nil |
|
| 109 |
+} |
| ... | ... |
@@ -7,7 +7,6 @@ import ( |
| 7 | 7 |
|
| 8 | 8 |
"golang.org/x/net/context" |
| 9 | 9 |
|
| 10 |
- "github.com/Sirupsen/logrus" |
|
| 11 | 10 |
"github.com/docker/docker/api/server/httputils" |
| 12 | 11 |
"github.com/docker/docker/api/types" |
| 13 | 12 |
"github.com/docker/docker/api/types/filters" |
| ... | ... |
@@ -28,29 +27,24 @@ func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWrit |
| 28 | 28 |
return err |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 |
- list := []*types.NetworkResource{}
|
|
| 32 |
- netFilters.WalkValues("name", func(name string) error {
|
|
| 33 |
- if nw, err := n.backend.GetNetwork(name, daemon.NetworkByName); err == nil {
|
|
| 34 |
- list = append(list, buildNetworkResource(nw)) |
|
| 35 |
- } else {
|
|
| 36 |
- logrus.Errorf("failed to get network for filter=%s : %v", name, err)
|
|
| 31 |
+ if netFilters.Len() != 0 {
|
|
| 32 |
+ if err := netFilters.Validate(acceptedFilters); err != nil {
|
|
| 33 |
+ return err |
|
| 37 | 34 |
} |
| 38 |
- return nil |
|
| 39 |
- }) |
|
| 35 |
+ } |
|
| 40 | 36 |
|
| 41 |
- netFilters.WalkValues("id", func(id string) error {
|
|
| 42 |
- for _, nw := range n.backend.GetNetworksByID(id) {
|
|
| 43 |
- list = append(list, buildNetworkResource(nw)) |
|
| 44 |
- } |
|
| 45 |
- return nil |
|
| 46 |
- }) |
|
| 37 |
+ list := []*types.NetworkResource{}
|
|
| 47 | 38 |
|
| 48 |
- if !netFilters.Include("name") && !netFilters.Include("id") {
|
|
| 49 |
- nwList := n.backend.GetNetworksByID("")
|
|
| 50 |
- for _, nw := range nwList {
|
|
| 51 |
- list = append(list, buildNetworkResource(nw)) |
|
| 52 |
- } |
|
| 39 |
+ nwList := n.backend.GetAllNetworks() |
|
| 40 |
+ displayable, err := filterNetworks(nwList, netFilters) |
|
| 41 |
+ if err != nil {
|
|
| 42 |
+ return err |
|
| 53 | 43 |
} |
| 44 |
+ |
|
| 45 |
+ for _, nw := range displayable {
|
|
| 46 |
+ list = append(list, buildNetworkResource(nw)) |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 54 | 49 |
return httputils.WriteJSON(w, http.StatusOK, list) |
| 55 | 50 |
} |
| 56 | 51 |
|
| ... | ... |
@@ -86,6 +86,11 @@ type EventsOptions struct {
|
| 86 | 86 |
Filters filters.Args |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 |
+// NetworkListOptions holds parameters to filter the list of networks with. |
|
| 90 |
+type NetworkListOptions struct {
|
|
| 91 |
+ Filters filters.Args |
|
| 92 |
+} |
|
| 93 |
+ |
|
| 89 | 94 |
// HijackedResponse holds connection information for a hijacked request. |
| 90 | 95 |
type HijackedResponse struct {
|
| 91 | 96 |
Conn net.Conn |
| ... | ... |
@@ -85,6 +85,19 @@ func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
|
| 85 | 85 |
return list |
| 86 | 86 |
} |
| 87 | 87 |
|
| 88 |
+// GetAllNetworks returns a list containing all networks |
|
| 89 |
+func (daemon *Daemon) GetAllNetworks() []libnetwork.Network {
|
|
| 90 |
+ c := daemon.netController |
|
| 91 |
+ list := []libnetwork.Network{}
|
|
| 92 |
+ l := func(nw libnetwork.Network) bool {
|
|
| 93 |
+ list = append(list, nw) |
|
| 94 |
+ return false |
|
| 95 |
+ } |
|
| 96 |
+ c.WalkNetworks(l) |
|
| 97 |
+ |
|
| 98 |
+ return list |
|
| 99 |
+} |
|
| 100 |
+ |
|
| 88 | 101 |
// CreateNetwork creates a network with the given name, driver and other optional parameters |
| 89 | 102 |
func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string) (libnetwork.Network, error) {
|
| 90 | 103 |
c := daemon.netController |
| ... | ... |
@@ -109,6 +109,7 @@ This section lists each version from latest to oldest. Each listing includes a |
| 109 | 109 |
the push or pull completes. |
| 110 | 110 |
* `POST /containers/create` now allows you to set a read/write rate limit for a |
| 111 | 111 |
device (in bytes per second or IO per second). |
| 112 |
+* `GET /networks` now supports filtering by `name`, `id` and `type`. |
|
| 112 | 113 |
|
| 113 | 114 |
### v1.21 API changes |
| 114 | 115 |
|
| ... | ... |
@@ -2728,7 +2728,7 @@ Status Codes |
| 2728 | 2728 |
|
| 2729 | 2729 |
**Example request**: |
| 2730 | 2730 |
|
| 2731 |
- GET /networks HTTP/1.1 |
|
| 2731 |
+ GET /networks?filters={"type":{"custom":true}} HTTP/1.1
|
|
| 2732 | 2732 |
|
| 2733 | 2733 |
**Example response**: |
| 2734 | 2734 |
|
| ... | ... |
@@ -2794,11 +2794,12 @@ Content-Type: application/json |
| 2794 | 2794 |
] |
| 2795 | 2795 |
``` |
| 2796 | 2796 |
|
| 2797 |
- |
|
| 2798 |
- |
|
| 2799 | 2797 |
Query Parameters: |
| 2800 | 2798 |
|
| 2801 |
-- **filters** - JSON encoded value of the filters (a `map[string][]string`) to process on the networks list. Available filters: `name=[network-names]` , `id=[network-ids]` |
|
| 2799 |
+- **filters** - JSON encoded network list filter. The filter value is one of: |
|
| 2800 |
+ - `name=<network-name>` Matches all or part of a network name. |
|
| 2801 |
+ - `id=<network-id>` Matches all or part of a network id. |
|
| 2802 |
+ - `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks. |
|
| 2802 | 2803 |
|
| 2803 | 2804 |
Status Codes: |
| 2804 | 2805 |
|
| ... | ... |
@@ -13,6 +13,7 @@ parent = "smn_cli" |
| 13 | 13 |
Usage: docker network ls [OPTIONS] |
| 14 | 14 |
|
| 15 | 15 |
Lists all the networks created by the user |
| 16 |
+ -f, --filter=[] Filter output based on conditions provided |
|
| 16 | 17 |
--help=false Print usage |
| 17 | 18 |
--no-trunc=false Do not truncate the output |
| 18 | 19 |
-q, --quiet=false Only display numeric IDs |
| ... | ... |
@@ -38,8 +39,91 @@ NETWORK ID NAME |
| 38 | 38 |
c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47 host host |
| 39 | 39 |
7b369448dccbf865d397c8d2be0cda7cf7edc6b0945f77d2529912ae917a0185 bridge bridge |
| 40 | 40 |
95e74588f40db048e86320c6526440c504650a1ff3e9f7d60a497c4d2163e5bd foo bridge |
| 41 |
+63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 dev bridge |
|
| 41 | 42 |
``` |
| 42 | 43 |
|
| 44 |
+## Filtering |
|
| 45 |
+ |
|
| 46 |
+The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there |
|
| 47 |
+is more than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bif=baz"`). |
|
| 48 |
+Multiple filter flags are combined as an `OR` filter. For example, |
|
| 49 |
+`-f type=custom -f type=builtin` returns both `custom` and `builtin` networks. |
|
| 50 |
+ |
|
| 51 |
+The currently supported filters are: |
|
| 52 |
+ |
|
| 53 |
+* id (network's id) |
|
| 54 |
+* name (network's name) |
|
| 55 |
+* type (custom|builtin) |
|
| 56 |
+ |
|
| 57 |
+#### Type |
|
| 58 |
+ |
|
| 59 |
+The `type` filter supports two values; `builtin` displays predefined networks |
|
| 60 |
+(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. |
|
| 61 |
+ |
|
| 62 |
+The following filter matches all user defined networks: |
|
| 63 |
+ |
|
| 64 |
+```bash |
|
| 65 |
+$ docker network ls --filter type=custom |
|
| 66 |
+NETWORK ID NAME DRIVER |
|
| 67 |
+95e74588f40d foo bridge |
|
| 68 |
+63d1ff1f77b0 dev bridge |
|
| 69 |
+``` |
|
| 70 |
+ |
|
| 71 |
+By having this flag it allows for batch cleanup. For example, use this filter |
|
| 72 |
+to delete all user defined networks: |
|
| 73 |
+ |
|
| 74 |
+```bash |
|
| 75 |
+$ docker network rm `docker network ls --filter type=custom -q` |
|
| 76 |
+``` |
|
| 77 |
+ |
|
| 78 |
+A warning will be issued when trying to remove a network that has containers |
|
| 79 |
+attached. |
|
| 80 |
+ |
|
| 81 |
+#### Name |
|
| 82 |
+ |
|
| 83 |
+The `name` filter matches on all or part of a network's name. |
|
| 84 |
+ |
|
| 85 |
+The following filter matches all networks with a name containing the `foobar` string. |
|
| 86 |
+ |
|
| 87 |
+```bash |
|
| 88 |
+$ docker network ls --filter name=foobar |
|
| 89 |
+NETWORK ID NAME DRIVER |
|
| 90 |
+06e7eef0a170 foobar bridge |
|
| 91 |
+``` |
|
| 92 |
+ |
|
| 93 |
+You can also filter for a substring in a name as this shows: |
|
| 94 |
+ |
|
| 95 |
+```bash |
|
| 96 |
+$ docker ps --filter name=foo |
|
| 97 |
+NETWORK ID NAME DRIVER |
|
| 98 |
+95e74588f40d foo bridge |
|
| 99 |
+06e7eef0a170 foobar bridge |
|
| 100 |
+``` |
|
| 101 |
+ |
|
| 102 |
+#### ID |
|
| 103 |
+ |
|
| 104 |
+The `id` filter matches on all or part of a network's ID. |
|
| 105 |
+ |
|
| 106 |
+The following filter matches all networks with a name containing the |
|
| 107 |
+`06e7eef01700` string. |
|
| 108 |
+ |
|
| 109 |
+```bash |
|
| 110 |
+$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 |
|
| 111 |
+NETWORK ID NAME DRIVER |
|
| 112 |
+63d1ff1f77b0 dev bridge |
|
| 113 |
+``` |
|
| 114 |
+ |
|
| 115 |
+You can also filter for a substring in a ID as this shows: |
|
| 116 |
+ |
|
| 117 |
+```bash |
|
| 118 |
+$ docker ps --filter id=95e74588f40d |
|
| 119 |
+NETWORK ID NAME DRIVER |
|
| 120 |
+95e74588f40d foo bridge |
|
| 121 |
+ |
|
| 122 |
+$ docker ps --filter id=95e |
|
| 123 |
+NETWORK ID NAME DRIVER |
|
| 124 |
+95e74588f40d foo bridge |
|
| 125 |
+``` |
|
| 43 | 126 |
|
| 44 | 127 |
## Related information |
| 45 | 128 |
|
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"net/http" |
| 11 | 11 |
"net/http/httptest" |
| 12 | 12 |
"os" |
| 13 |
+ "sort" |
|
| 13 | 14 |
"strings" |
| 14 | 15 |
|
| 15 | 16 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -242,6 +243,25 @@ func isNwPresent(c *check.C, name string) bool {
|
| 242 | 242 |
return false |
| 243 | 243 |
} |
| 244 | 244 |
|
| 245 |
+// assertNwList checks network list retrived with ls command |
|
| 246 |
+// equals to expected network list |
|
| 247 |
+// note: out should be `network ls [option]` result |
|
| 248 |
+func assertNwList(c *check.C, out string, expectNws []string) {
|
|
| 249 |
+ lines := strings.Split(out, "\n") |
|
| 250 |
+ var nwList []string |
|
| 251 |
+ for _, line := range lines[1 : len(lines)-1] {
|
|
| 252 |
+ netFields := strings.Fields(line) |
|
| 253 |
+ // wrap all network name in nwList |
|
| 254 |
+ nwList = append(nwList, netFields[1]) |
|
| 255 |
+ } |
|
| 256 |
+ // first need to sort out and expected |
|
| 257 |
+ sort.StringSlice(nwList).Sort() |
|
| 258 |
+ sort.StringSlice(expectNws).Sort() |
|
| 259 |
+ |
|
| 260 |
+ // network ls should contains all expected networks |
|
| 261 |
+ c.Assert(nwList, checker.DeepEquals, expectNws) |
|
| 262 |
+} |
|
| 263 |
+ |
|
| 245 | 264 |
func getNwResource(c *check.C, name string) *types.NetworkResource {
|
| 246 | 265 |
out, _ := dockerCmd(c, "network", "inspect", name) |
| 247 | 266 |
nr := []types.NetworkResource{}
|
| ... | ... |
@@ -257,6 +277,32 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) {
|
| 257 | 257 |
} |
| 258 | 258 |
} |
| 259 | 259 |
|
| 260 |
+func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
|
|
| 261 |
+ out, _ := dockerCmd(c, "network", "create", "dev") |
|
| 262 |
+ defer func() {
|
|
| 263 |
+ dockerCmd(c, "network", "rm", "dev") |
|
| 264 |
+ }() |
|
| 265 |
+ containerID := strings.TrimSpace(out) |
|
| 266 |
+ |
|
| 267 |
+ // filter with partial ID and partial name |
|
| 268 |
+ // only show 'bridge' and 'dev' network |
|
| 269 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "id="+containerID[0:5], "-f", "name=dge") |
|
| 270 |
+ assertNwList(c, out, []string{"dev", "bridge"})
|
|
| 271 |
+ |
|
| 272 |
+ // only show built-in network (bridge, none, host) |
|
| 273 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "type=builtin") |
|
| 274 |
+ assertNwList(c, out, []string{"bridge", "none", "host"})
|
|
| 275 |
+ |
|
| 276 |
+ // only show custom networks (dev) |
|
| 277 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom") |
|
| 278 |
+ assertNwList(c, out, []string{"dev"})
|
|
| 279 |
+ |
|
| 280 |
+ // show all networks with filter |
|
| 281 |
+ // it should be equivalent of ls without option |
|
| 282 |
+ out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin") |
|
| 283 |
+ assertNwList(c, out, []string{"dev", "bridge", "host", "none"})
|
|
| 284 |
+} |
|
| 285 |
+ |
|
| 260 | 286 |
func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) {
|
| 261 | 287 |
dockerCmd(c, "network", "create", "test") |
| 262 | 288 |
assertNwIsAvailable(c, "test") |
| ... | ... |
@@ -6,6 +6,7 @@ docker-network-ls - list networks |
| 6 | 6 |
|
| 7 | 7 |
# SYNOPSIS |
| 8 | 8 |
**docker network ls** |
| 9 |
+[**-f**|**--filter**[=*[]*]] |
|
| 9 | 10 |
[**--no-trunc**[=*true*|*false*]] |
| 10 | 11 |
[**-q**|**--quiet**[=*true*|*false*]] |
| 11 | 12 |
[**--help**] |
| ... | ... |
@@ -16,7 +17,7 @@ Lists all the networks the Engine `daemon` knows about. This includes the |
| 16 | 16 |
networks that span across multiple hosts in a cluster, for example: |
| 17 | 17 |
|
| 18 | 18 |
```bash |
| 19 |
- $ sudo docker network ls |
|
| 19 |
+ $ docker network ls |
|
| 20 | 20 |
NETWORK ID NAME DRIVER |
| 21 | 21 |
7fca4eb8c647 bridge bridge |
| 22 | 22 |
9f904ee27bf5 none null |
| ... | ... |
@@ -27,16 +28,103 @@ networks that span across multiple hosts in a cluster, for example: |
| 27 | 27 |
Use the `--no-trunc` option to display the full network id: |
| 28 | 28 |
|
| 29 | 29 |
```bash |
| 30 |
-docker network ls --no-trunc |
|
| 30 |
+$ docker network ls --no-trunc |
|
| 31 | 31 |
NETWORK ID NAME DRIVER |
| 32 | 32 |
18a2866682b85619a026c81b98a5e375bd33e1b0936a26cc497c283d27bae9b3 none null |
| 33 | 33 |
c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47 host host |
| 34 | 34 |
7b369448dccbf865d397c8d2be0cda7cf7edc6b0945f77d2529912ae917a0185 bridge bridge |
| 35 | 35 |
95e74588f40db048e86320c6526440c504650a1ff3e9f7d60a497c4d2163e5bd foo bridge |
| 36 |
+63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 dev bridge |
|
| 37 |
+``` |
|
| 38 |
+ |
|
| 39 |
+## Filtering |
|
| 40 |
+ |
|
| 41 |
+The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there |
|
| 42 |
+is more than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bif=baz"`). |
|
| 43 |
+Multiple filter flags are combined as an `OR` filter. For example, |
|
| 44 |
+`-f type=custom -f type=builtin` returns both `custom` and `builtin` networks. |
|
| 45 |
+ |
|
| 46 |
+The currently supported filters are: |
|
| 47 |
+ |
|
| 48 |
+* id (network's id) |
|
| 49 |
+* name (network's name) |
|
| 50 |
+* type (custom|builtin) |
|
| 51 |
+ |
|
| 52 |
+#### Type |
|
| 53 |
+ |
|
| 54 |
+The `type` filter supports two values; `builtin` displays predefined networks |
|
| 55 |
+(`bridge`, `none`, `host`), whereas `custom` displays user defined networks. |
|
| 56 |
+ |
|
| 57 |
+The following filter matches all user defined networks: |
|
| 58 |
+ |
|
| 59 |
+```bash |
|
| 60 |
+$ docker network ls --filter type=custom |
|
| 61 |
+NETWORK ID NAME DRIVER |
|
| 62 |
+95e74588f40d foo bridge |
|
| 63 |
+63d1ff1f77b0 dev bridge |
|
| 64 |
+``` |
|
| 65 |
+ |
|
| 66 |
+By having this flag it allows for batch cleanup. For example, use this filter |
|
| 67 |
+to delete all user defined networks: |
|
| 68 |
+ |
|
| 69 |
+```bash |
|
| 70 |
+$ docker network rm `docker network ls --filter type=custom -q` |
|
| 71 |
+``` |
|
| 72 |
+ |
|
| 73 |
+A warning will be issued when trying to remove a network that has containers |
|
| 74 |
+attached. |
|
| 75 |
+ |
|
| 76 |
+#### Name |
|
| 77 |
+ |
|
| 78 |
+The `name` filter matches on all or part of a network's name. |
|
| 79 |
+ |
|
| 80 |
+The following filter matches all networks with a name containing the `foobar` string. |
|
| 81 |
+ |
|
| 82 |
+```bash |
|
| 83 |
+$ docker network ls --filter name=foobar |
|
| 84 |
+NETWORK ID NAME DRIVER |
|
| 85 |
+06e7eef0a170 foobar bridge |
|
| 86 |
+``` |
|
| 87 |
+ |
|
| 88 |
+You can also filter for a substring in a name as this shows: |
|
| 89 |
+ |
|
| 90 |
+```bash |
|
| 91 |
+$ docker ps --filter name=foo |
|
| 92 |
+NETWORK ID NAME DRIVER |
|
| 93 |
+95e74588f40d foo bridge |
|
| 94 |
+06e7eef0a170 foobar bridge |
|
| 95 |
+``` |
|
| 96 |
+ |
|
| 97 |
+#### ID |
|
| 98 |
+ |
|
| 99 |
+The `id` filter matches on all or part of a network's ID. |
|
| 100 |
+ |
|
| 101 |
+The following filter matches all networks with a name containing the |
|
| 102 |
+`06e7eef01700` string. |
|
| 103 |
+ |
|
| 104 |
+```bash |
|
| 105 |
+$ docker network ls --filter id=63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161 |
|
| 106 |
+NETWORK ID NAME DRIVER |
|
| 107 |
+63d1ff1f77b0 dev bridge |
|
| 108 |
+``` |
|
| 109 |
+ |
|
| 110 |
+You can also filter for a substring in a ID as this shows: |
|
| 111 |
+ |
|
| 112 |
+```bash |
|
| 113 |
+$ docker ps --filter id=95e74588f40d |
|
| 114 |
+NETWORK ID NAME DRIVER |
|
| 115 |
+95e74588f40d foo bridge |
|
| 116 |
+ |
|
| 117 |
+$ docker ps --filter id=95e |
|
| 118 |
+NETWORK ID NAME DRIVER |
|
| 119 |
+95e74588f40d foo bridge |
|
| 36 | 120 |
``` |
| 37 | 121 |
|
| 38 | 122 |
# OPTIONS |
| 39 | 123 |
|
| 124 |
+**-f**, **--filter**=*[]* |
|
| 125 |
+ filter output based on conditions provided. |
|
| 126 |
+ |
|
| 40 | 127 |
**--no-trunc**=*true*|*false* |
| 41 | 128 |
Do not truncate the output |
| 42 | 129 |
|