Skip to content

Commit

Permalink
Merge pull request moby#17782 from WeiZhang555/network-ls-nopre
Browse files Browse the repository at this point in the history
Add filter for `network ls` to hide predefined network
  • Loading branch information
thaJeztah committed Dec 23, 2015
2 parents 1105caa + 26dd026 commit 4432a89
Show file tree
Hide file tree
Showing 13 changed files with 403 additions and 31 deletions.
2 changes: 1 addition & 1 deletion api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type apiClient interface {
NetworkCreate(options types.NetworkCreate) (types.NetworkCreateResponse, error)
NetworkDisconnect(networkID, containerID string) error
NetworkInspect(networkID string) (types.NetworkResource, error)
NetworkList() ([]types.NetworkResource, error)
NetworkList(options types.NetworkListOptions) ([]types.NetworkResource, error)
NetworkRemove(networkID string) error
RegistryLogin(auth types.AuthConfig) (types.AuthResponse, error)
ServerVersion() (types.Version, error)
Expand Down
15 changes: 13 additions & 2 deletions api/client/lib/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package lib
import (
"encoding/json"
"net/http"
"net/url"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
)

// NetworkCreate creates a new network in the docker host.
Expand Down Expand Up @@ -44,9 +46,18 @@ func (cli *Client) NetworkDisconnect(networkID, containerID string) error {
}

// NetworkList returns the list of networks configured in the docker host.
func (cli *Client) NetworkList() ([]types.NetworkResource, error) {
func (cli *Client) NetworkList(options types.NetworkListOptions) ([]types.NetworkResource, error) {
query := url.Values{}
if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters)
if err != nil {
return nil, err
}

query.Set("filters", filterJSON)
}
var networkResources []types.NetworkResource
resp, err := cli.get("/networks", nil, nil)
resp, err := cli.get("/networks", query, nil)
if err != nil {
return networkResources, err
}
Expand Down
22 changes: 20 additions & 2 deletions api/client/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"text/tabwriter"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/network"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
Expand Down Expand Up @@ -138,12 +139,29 @@ func (cli *DockerCli) CmdNetworkLs(args ...string) error {
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Do not truncate the output")

flFilter := opts.NewListOpts(nil)
cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")

cmd.Require(flag.Exact, 0)
if err := cmd.ParseFlags(args, true); err != nil {
err := cmd.ParseFlags(args, true)
if err != nil {
return err
}

networkResources, err := cli.client.NetworkList()
// Consolidate all filter flags, and sanity check them early.
// They'll get process after get response from server.
netFilterArgs := filters.NewArgs()
for _, f := range flFilter.GetAll() {
if netFilterArgs, err = filters.ParseFlag(f, netFilterArgs); err != nil {
return err
}
}

options := types.NetworkListOptions{
Filters: netFilterArgs,
}

networkResources, err := cli.client.NetworkList(options)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions api/server/router/network/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Backend interface {
FindNetwork(idName string) (libnetwork.Network, error)
GetNetwork(idName string, by int) (libnetwork.Network, error)
GetNetworksByID(partialID string) []libnetwork.Network
GetAllNetworks() []libnetwork.Network
CreateNetwork(name, driver string, ipam network.IPAM,
options map[string]string) (libnetwork.Network, error)
ConnectContainerToNetwork(containerName, networkName string) error
Expand Down
110 changes: 110 additions & 0 deletions api/server/router/network/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package network

import (
"fmt"
"regexp"
"strings"

"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/runconfig"
"github.com/docker/libnetwork"
)

type filterHandler func([]libnetwork.Network, string) ([]libnetwork.Network, error)

var (
// supportedFilters predefined some supported filter handler function
supportedFilters = map[string]filterHandler{
"type": filterNetworkByType,
"name": filterNetworkByName,
"id": filterNetworkByID,
}

// acceptFilters is an acceptable filter flag list
// generated for validation. e.g.
// acceptedFilters = map[string]bool{
// "type": true,
// "name": true,
// "id": true,
// }
acceptedFilters = func() map[string]bool {
ret := make(map[string]bool)
for k := range supportedFilters {
ret[k] = true
}
return ret
}()
)

func filterNetworkByType(nws []libnetwork.Network, netType string) (retNws []libnetwork.Network, err error) {
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, fmt.Errorf("Invalid filter: 'type'='%s'", netType)
}
return retNws, nil
}

func filterNetworkByName(nws []libnetwork.Network, name string) (retNws []libnetwork.Network, err error) {
for _, nw := range nws {
// exact match (fast path)
if nw.Name() == name {
retNws = append(retNws, nw)
continue
}

// regexp match (slow path)
match, err := regexp.MatchString(name, nw.Name())
if err != nil || !match {
continue
} else {
retNws = append(retNws, nw)
}
}
return retNws, nil
}

func filterNetworkByID(nws []libnetwork.Network, id string) (retNws []libnetwork.Network, err error) {
for _, nw := range nws {
if strings.HasPrefix(nw.ID(), id) {
retNws = append(retNws, nw)
}
}
return retNws, nil
}

// filterAllNetworks filter network list according to user specified filter
// and return user chosen networks
func filterNetworks(nws []libnetwork.Network, filter filters.Args) ([]libnetwork.Network, error) {
// if filter is empty, return original network list
if filter.Len() == 0 {
return nws, nil
}

var displayNet []libnetwork.Network
for fkey, fhandler := range supportedFilters {
errFilter := filter.WalkValues(fkey, func(fval string) error {
passList, err := fhandler(nws, fval)
if err != nil {
return err
}
displayNet = append(displayNet, passList...)
return nil
})
if errFilter != nil {
return nil, errFilter
}
}
return displayNet, nil
}
34 changes: 14 additions & 20 deletions api/server/router/network/network_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"golang.org/x/net/context"

"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
Expand All @@ -28,29 +27,24 @@ func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWrit
return err
}

list := []*types.NetworkResource{}
netFilters.WalkValues("name", func(name string) error {
if nw, err := n.backend.GetNetwork(name, daemon.NetworkByName); err == nil {
list = append(list, buildNetworkResource(nw))
} else {
logrus.Errorf("failed to get network for filter=%s : %v", name, err)
if netFilters.Len() != 0 {
if err := netFilters.Validate(acceptedFilters); err != nil {
return err
}
return nil
})
}

netFilters.WalkValues("id", func(id string) error {
for _, nw := range n.backend.GetNetworksByID(id) {
list = append(list, buildNetworkResource(nw))
}
return nil
})
list := []*types.NetworkResource{}

if !netFilters.Include("name") && !netFilters.Include("id") {
nwList := n.backend.GetNetworksByID("")
for _, nw := range nwList {
list = append(list, buildNetworkResource(nw))
}
nwList := n.backend.GetAllNetworks()
displayable, err := filterNetworks(nwList, netFilters)
if err != nil {
return err
}

for _, nw := range displayable {
list = append(list, buildNetworkResource(nw))
}

return httputils.WriteJSON(w, http.StatusOK, list)
}

Expand Down
5 changes: 5 additions & 0 deletions api/types/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ type EventsOptions struct {
Filters filters.Args
}

// NetworkListOptions holds parameters to filter the list of networks with.
type NetworkListOptions struct {
Filters filters.Args
}

// HijackedResponse holds connection information for a hijacked request.
type HijackedResponse struct {
Conn net.Conn
Expand Down
13 changes: 13 additions & 0 deletions daemon/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@ func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
return list
}

// GetAllNetworks returns a list containing all networks
func (daemon *Daemon) GetAllNetworks() []libnetwork.Network {
c := daemon.netController
list := []libnetwork.Network{}
l := func(nw libnetwork.Network) bool {
list = append(list, nw)
return false
}
c.WalkNetworks(l)

return list
}

// CreateNetwork creates a network with the given name, driver and other optional parameters
func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string) (libnetwork.Network, error) {
c := daemon.netController
Expand Down
1 change: 1 addition & 0 deletions docs/reference/api/docker_remote_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ This section lists each version from latest to oldest. Each listing includes a
the push or pull completes.
* `POST /containers/create` now allows you to set a read/write rate limit for a
device (in bytes per second or IO per second).
* `GET /networks` now supports filtering by `name`, `id` and `type`.

### v1.21 API changes

Expand Down
9 changes: 5 additions & 4 deletions docs/reference/api/docker_remote_api_v1.22.md
Original file line number Diff line number Diff line change
Expand Up @@ -2728,7 +2728,7 @@ Status Codes

**Example request**:

GET /networks HTTP/1.1
GET /networks?filters={"type":{"custom":true}} HTTP/1.1

**Example response**:

Expand Down Expand Up @@ -2794,11 +2794,12 @@ Content-Type: application/json
]
```



Query Parameters:

- **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]`
- **filters** - JSON encoded network list filter. The filter value is one of:
- `name=<network-name>` Matches all or part of a network name.
- `id=<network-id>` Matches all or part of a network id.
- `type=["custom"|"builtin"]` Filters networks by type. The `custom` keyword returns all user-defined networks.

Status Codes:

Expand Down
Loading

0 comments on commit 4432a89

Please sign in to comment.