mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Move network conversions out of API router
This stuff doesn't belong here and is causing imports of libnetwork into the router, which is not what we want. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
68e25cf526
commit
c0bc14e8dd
11 changed files with 442 additions and 371 deletions
|
@ -13,7 +13,7 @@ import (
|
||||||
// to provide network specific functionality.
|
// to provide network specific functionality.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
FindNetwork(idName string) (libnetwork.Network, error)
|
FindNetwork(idName string) (libnetwork.Network, error)
|
||||||
GetNetworks() []libnetwork.Network
|
GetNetworks(filters.Args, types.NetworkListConfig) ([]types.NetworkResource, error)
|
||||||
CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
|
CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
|
||||||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||||
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
|
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
|
||||||
|
@ -24,7 +24,7 @@ type Backend interface {
|
||||||
// ClusterBackend is all the methods that need to be implemented
|
// ClusterBackend is all the methods that need to be implemented
|
||||||
// to provide cluster network specific functionality.
|
// to provide cluster network specific functionality.
|
||||||
type ClusterBackend interface {
|
type ClusterBackend interface {
|
||||||
GetNetworks() ([]types.NetworkResource, error)
|
GetNetworks(filters.Args) ([]types.NetworkResource, error)
|
||||||
GetNetwork(name string) (types.NetworkResource, error)
|
GetNetwork(name string) (types.NetworkResource, error)
|
||||||
GetNetworksByName(name string) ([]types.NetworkResource, error)
|
GetNetworksByName(name string) ([]types.NetworkResource, error)
|
||||||
CreateNetwork(nc types.NetworkCreateRequest) (string, error)
|
CreateNetwork(nc types.NetworkCreateRequest) (string, error)
|
||||||
|
|
|
@ -1,93 +1 @@
|
||||||
package network // import "github.com/docker/docker/api/server/router/network"
|
package network // import "github.com/docker/docker/api/server/router/network"
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
|
||||||
"github.com/docker/docker/runconfig"
|
|
||||||
)
|
|
||||||
|
|
||||||
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, invalidFilter(netType)
|
|
||||||
}
|
|
||||||
return retNws, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type invalidFilter string
|
|
||||||
|
|
||||||
func (e invalidFilter) Error() string {
|
|
||||||
return "Invalid filter: 'type'='" + string(e) + "'"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e invalidFilter) InvalidParameter() {}
|
|
||||||
|
|
||||||
// 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 := []types.NetworkResource{}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
displayNet = append(displayNet, nw)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,70 +15,54 @@ import (
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
netconst "github.com/docker/libnetwork/datastore"
|
netconst "github.com/docker/libnetwork/datastore"
|
||||||
"github.com/docker/libnetwork/networkdb"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// acceptedNetworkFilters is a list of acceptable filters
|
|
||||||
acceptedNetworkFilters = map[string]bool{
|
|
||||||
"driver": true,
|
|
||||||
"type": true,
|
|
||||||
"name": true,
|
|
||||||
"id": true,
|
|
||||||
"label": true,
|
|
||||||
"scope": true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := r.Form.Get("filters")
|
filter, err := filters.FromJSON(r.Form.Get("filters"))
|
||||||
netFilters, err := filters.FromJSON(filter)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := netFilters.Validate(acceptedNetworkFilters); err != nil {
|
if err := network.ValidateFilters(filter); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
list := []types.NetworkResource{}
|
var list []types.NetworkResource
|
||||||
|
nr, err := n.cluster.GetNetworks(filter)
|
||||||
if nr, err := n.cluster.GetNetworks(); err == nil {
|
if err == nil {
|
||||||
list = append(list, nr...)
|
list = nr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine the network list returned by Docker daemon if it is not already
|
// Combine the network list returned by Docker daemon if it is not already
|
||||||
// returned by the cluster manager
|
// returned by the cluster manager
|
||||||
SKIP:
|
localNetworks, err := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: versions.LessThan(httputils.VersionFromContext(ctx), "1.28")})
|
||||||
for _, nw := range n.backend.GetNetworks() {
|
|
||||||
for _, nl := range list {
|
|
||||||
if nl.ID == nw.ID() {
|
|
||||||
continue SKIP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nr *types.NetworkResource
|
|
||||||
// Versions < 1.28 fetches all the containers attached to a network
|
|
||||||
// in a network list api call. It is a heavy weight operation when
|
|
||||||
// run across all the networks. Starting API version 1.28, this detailed
|
|
||||||
// info is available for network specific GET API (equivalent to inspect)
|
|
||||||
if versions.LessThan(httputils.VersionFromContext(ctx), "1.28") {
|
|
||||||
nr = n.buildDetailedNetworkResources(nw, false)
|
|
||||||
} else {
|
|
||||||
nr = n.buildNetworkResource(nw)
|
|
||||||
}
|
|
||||||
list = append(list, *nr)
|
|
||||||
}
|
|
||||||
|
|
||||||
list, err = filterNetworks(list, netFilters)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var idx map[string]bool
|
||||||
|
if len(list) > 0 {
|
||||||
|
idx = make(map[string]bool, len(list))
|
||||||
|
for _, n := range list {
|
||||||
|
idx[n.ID] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, n := range localNetworks {
|
||||||
|
if idx[n.ID] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list = append(list, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list == nil {
|
||||||
|
list = []types.NetworkResource{}
|
||||||
|
}
|
||||||
|
|
||||||
return httputils.WriteJSON(w, http.StatusOK, list)
|
return httputils.WriteJSON(w, http.StatusOK, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,13 +105,6 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
scope := r.URL.Query().Get("scope")
|
scope := r.URL.Query().Get("scope")
|
||||||
|
|
||||||
isMatchingScope := func(scope, term string) bool {
|
|
||||||
if term != "" {
|
|
||||||
return scope == term
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case multiple networks have duplicate names, return error.
|
// In case multiple networks have duplicate names, return error.
|
||||||
// TODO (yongtang): should we wrap with version here for backward compatibility?
|
// TODO (yongtang): should we wrap with version here for backward compatibility?
|
||||||
|
|
||||||
|
@ -139,20 +116,26 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
listByFullName := map[string]types.NetworkResource{}
|
listByFullName := map[string]types.NetworkResource{}
|
||||||
listByPartialID := map[string]types.NetworkResource{}
|
listByPartialID := map[string]types.NetworkResource{}
|
||||||
|
|
||||||
nw := n.backend.GetNetworks()
|
// TODO(@cpuguy83): All this logic for figuring out which network to return does not belong here
|
||||||
|
// Instead there should be a backend function to just get one network.
|
||||||
|
filter := filters.NewArgs(filters.Arg("idOrName", term))
|
||||||
|
if scope != "" {
|
||||||
|
filter.Add("scope", scope)
|
||||||
|
}
|
||||||
|
nw, _ := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: true, Verbose: verbose})
|
||||||
for _, network := range nw {
|
for _, network := range nw {
|
||||||
if network.ID() == term && isMatchingScope(network.Info().Scope(), scope) {
|
if network.ID == term {
|
||||||
return httputils.WriteJSON(w, http.StatusOK, *n.buildDetailedNetworkResources(network, verbose))
|
return httputils.WriteJSON(w, http.StatusOK, network)
|
||||||
}
|
}
|
||||||
if network.Name() == term && isMatchingScope(network.Info().Scope(), scope) {
|
if network.Name == term {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByFullName[network.ID()] = *n.buildDetailedNetworkResources(network, verbose)
|
listByFullName[network.ID] = network
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID(), term) && isMatchingScope(network.Info().Scope(), scope) {
|
if strings.HasPrefix(network.ID, term) {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByPartialID[network.ID()] = *n.buildDetailedNetworkResources(network, verbose)
|
listByPartialID[network.ID] = network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,12 +157,12 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nr, _ := n.cluster.GetNetworks()
|
nr, _ := n.cluster.GetNetworks(filter)
|
||||||
for _, network := range nr {
|
for _, network := range nr {
|
||||||
if network.ID == term && isMatchingScope(network.Scope, scope) {
|
if network.ID == term {
|
||||||
return httputils.WriteJSON(w, http.StatusOK, network)
|
return httputils.WriteJSON(w, http.StatusOK, network)
|
||||||
}
|
}
|
||||||
if network.Name == term && isMatchingScope(network.Scope, scope) {
|
if network.Name == term {
|
||||||
// Check the ID collision as we are in swarm scope here, and
|
// Check the ID collision as we are in swarm scope here, and
|
||||||
// the map (of the listByFullName) may have already had a
|
// the map (of the listByFullName) may have already had a
|
||||||
// network with the same ID (from local scope previously)
|
// network with the same ID (from local scope previously)
|
||||||
|
@ -187,7 +170,7 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
|
||||||
listByFullName[network.ID] = network
|
listByFullName[network.ID] = network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID, term) && isMatchingScope(network.Scope, scope) {
|
if strings.HasPrefix(network.ID, term) {
|
||||||
// Check the ID collision as we are in swarm scope here, and
|
// Check the ID collision as we are in swarm scope here, and
|
||||||
// the map (of the listByPartialID) may have already had a
|
// the map (of the listByPartialID) may have already had a
|
||||||
// network with the same ID (from local scope previously)
|
// network with the same ID (from local scope previously)
|
||||||
|
@ -327,182 +310,6 @@ func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *networkRouter) buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {
|
|
||||||
r := &types.NetworkResource{}
|
|
||||||
if nw == nil {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
info := nw.Info()
|
|
||||||
r.Name = nw.Name()
|
|
||||||
r.ID = nw.ID()
|
|
||||||
r.Created = info.Created()
|
|
||||||
r.Scope = info.Scope()
|
|
||||||
r.Driver = nw.Type()
|
|
||||||
r.EnableIPv6 = info.IPv6Enabled()
|
|
||||||
r.Internal = info.Internal()
|
|
||||||
r.Attachable = info.Attachable()
|
|
||||||
r.Ingress = info.Ingress()
|
|
||||||
r.Options = info.DriverOptions()
|
|
||||||
r.Containers = make(map[string]types.EndpointResource)
|
|
||||||
buildIpamResources(r, info)
|
|
||||||
r.Labels = info.Labels()
|
|
||||||
r.ConfigOnly = info.ConfigOnly()
|
|
||||||
|
|
||||||
if cn := info.ConfigFrom(); cn != "" {
|
|
||||||
r.ConfigFrom = network.ConfigReference{Network: cn}
|
|
||||||
}
|
|
||||||
|
|
||||||
peers := info.Peers()
|
|
||||||
if len(peers) != 0 {
|
|
||||||
r.Peers = buildPeerInfoResources(peers)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *networkRouter) buildDetailedNetworkResources(nw libnetwork.Network, verbose bool) *types.NetworkResource {
|
|
||||||
if nw == nil {
|
|
||||||
return &types.NetworkResource{}
|
|
||||||
}
|
|
||||||
|
|
||||||
r := n.buildNetworkResource(nw)
|
|
||||||
epl := nw.Endpoints()
|
|
||||||
for _, e := range epl {
|
|
||||||
ei := e.Info()
|
|
||||||
if ei == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sb := ei.Sandbox()
|
|
||||||
tmpID := e.ID()
|
|
||||||
key := "ep-" + tmpID
|
|
||||||
if sb != nil {
|
|
||||||
key = sb.ContainerID()
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei)
|
|
||||||
}
|
|
||||||
if !verbose {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
services := nw.Info().Services()
|
|
||||||
r.Services = make(map[string]network.ServiceInfo)
|
|
||||||
for name, service := range services {
|
|
||||||
tasks := []network.Task{}
|
|
||||||
for _, t := range service.Tasks {
|
|
||||||
tasks = append(tasks, network.Task{
|
|
||||||
Name: t.Name,
|
|
||||||
EndpointID: t.EndpointID,
|
|
||||||
EndpointIP: t.EndpointIP,
|
|
||||||
Info: t.Info,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
r.Services[name] = network.ServiceInfo{
|
|
||||||
VIP: service.VIP,
|
|
||||||
Ports: service.Ports,
|
|
||||||
Tasks: tasks,
|
|
||||||
LocalLBIndex: service.LocalLBIndex,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildPeerInfoResources(peers []networkdb.PeerInfo) []network.PeerInfo {
|
|
||||||
peerInfo := make([]network.PeerInfo, 0, len(peers))
|
|
||||||
for _, peer := range peers {
|
|
||||||
peerInfo = append(peerInfo, network.PeerInfo{
|
|
||||||
Name: peer.Name,
|
|
||||||
IP: peer.IP,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return peerInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildIpamResources(r *types.NetworkResource, nwInfo libnetwork.NetworkInfo) {
|
|
||||||
id, opts, ipv4conf, ipv6conf := nwInfo.IpamConfig()
|
|
||||||
|
|
||||||
ipv4Info, ipv6Info := nwInfo.IpamInfo()
|
|
||||||
|
|
||||||
r.IPAM.Driver = id
|
|
||||||
|
|
||||||
r.IPAM.Options = opts
|
|
||||||
|
|
||||||
r.IPAM.Config = []network.IPAMConfig{}
|
|
||||||
for _, ip4 := range ipv4conf {
|
|
||||||
if ip4.PreferredPool == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
iData := network.IPAMConfig{}
|
|
||||||
iData.Subnet = ip4.PreferredPool
|
|
||||||
iData.IPRange = ip4.SubPool
|
|
||||||
iData.Gateway = ip4.Gateway
|
|
||||||
iData.AuxAddress = ip4.AuxAddresses
|
|
||||||
r.IPAM.Config = append(r.IPAM.Config, iData)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(r.IPAM.Config) == 0 {
|
|
||||||
for _, ip4Info := range ipv4Info {
|
|
||||||
iData := network.IPAMConfig{}
|
|
||||||
iData.Subnet = ip4Info.IPAMData.Pool.String()
|
|
||||||
if ip4Info.IPAMData.Gateway != nil {
|
|
||||||
iData.Gateway = ip4Info.IPAMData.Gateway.IP.String()
|
|
||||||
}
|
|
||||||
r.IPAM.Config = append(r.IPAM.Config, iData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hasIpv6Conf := false
|
|
||||||
for _, ip6 := range ipv6conf {
|
|
||||||
if ip6.PreferredPool == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
hasIpv6Conf = true
|
|
||||||
iData := network.IPAMConfig{}
|
|
||||||
iData.Subnet = ip6.PreferredPool
|
|
||||||
iData.IPRange = ip6.SubPool
|
|
||||||
iData.Gateway = ip6.Gateway
|
|
||||||
iData.AuxAddress = ip6.AuxAddresses
|
|
||||||
r.IPAM.Config = append(r.IPAM.Config, iData)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasIpv6Conf {
|
|
||||||
for _, ip6Info := range ipv6Info {
|
|
||||||
if ip6Info.IPAMData.Pool == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
iData := network.IPAMConfig{}
|
|
||||||
iData.Subnet = ip6Info.IPAMData.Pool.String()
|
|
||||||
iData.Gateway = ip6Info.IPAMData.Gateway.String()
|
|
||||||
r.IPAM.Config = append(r.IPAM.Config, iData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildEndpointResource(id string, name string, info libnetwork.EndpointInfo) types.EndpointResource {
|
|
||||||
er := types.EndpointResource{}
|
|
||||||
|
|
||||||
er.EndpointID = id
|
|
||||||
er.Name = name
|
|
||||||
ei := info
|
|
||||||
if ei == nil {
|
|
||||||
return er
|
|
||||||
}
|
|
||||||
|
|
||||||
if iface := ei.Iface(); iface != nil {
|
|
||||||
if mac := iface.MacAddress(); mac != nil {
|
|
||||||
er.MacAddress = mac.String()
|
|
||||||
}
|
|
||||||
if ip := iface.Address(); ip != nil && len(ip.IP) > 0 {
|
|
||||||
er.IPv4Address = ip.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 {
|
|
||||||
er.IPv6Address = ipv6.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return er
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *networkRouter) postNetworksPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func (n *networkRouter) postNetworksPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -532,25 +339,25 @@ func (n *networkRouter) findUniqueNetwork(term string) (types.NetworkResource, e
|
||||||
listByFullName := map[string]types.NetworkResource{}
|
listByFullName := map[string]types.NetworkResource{}
|
||||||
listByPartialID := map[string]types.NetworkResource{}
|
listByPartialID := map[string]types.NetworkResource{}
|
||||||
|
|
||||||
nw := n.backend.GetNetworks()
|
filter := filters.NewArgs(filters.Arg("idOrName", term))
|
||||||
|
nw, _ := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: true})
|
||||||
for _, network := range nw {
|
for _, network := range nw {
|
||||||
if network.ID() == term {
|
if network.ID == term {
|
||||||
return *n.buildDetailedNetworkResources(network, false), nil
|
return network, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
if network.Name() == term && !network.Info().Ingress() {
|
if network.Name == term && !network.Ingress {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByFullName[network.ID()] = *n.buildDetailedNetworkResources(network, false)
|
listByFullName[network.ID] = network
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(network.ID(), term) {
|
if strings.HasPrefix(network.ID, term) {
|
||||||
// No need to check the ID collision here as we are still in
|
// No need to check the ID collision here as we are still in
|
||||||
// local scope and the network ID is unique in this scope.
|
// local scope and the network ID is unique in this scope.
|
||||||
listByPartialID[network.ID()] = *n.buildDetailedNetworkResources(network, false)
|
listByPartialID[network.ID] = network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nr, _ := n.cluster.GetNetworks()
|
nr, _ := n.cluster.GetNetworks(filter)
|
||||||
for _, network := range nr {
|
for _, network := range nr {
|
||||||
if network.ID == term {
|
if network.ID == term {
|
||||||
return network, nil
|
return network, nil
|
||||||
|
|
|
@ -55,3 +55,10 @@ type PluginEnableConfig struct {
|
||||||
type PluginDisableConfig struct {
|
type PluginDisableConfig struct {
|
||||||
ForceDisable bool
|
ForceDisable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetworkListConfig stores the options available for listing networks
|
||||||
|
type NetworkListConfig struct {
|
||||||
|
// TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here
|
||||||
|
Detailed bool
|
||||||
|
Verbose bool
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
package network // import "github.com/docker/docker/api/types/network"
|
package network // import "github.com/docker/docker/api/types/network"
|
||||||
|
import (
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/errdefs"
|
||||||
|
)
|
||||||
|
|
||||||
// Address represents an IP address
|
// Address represents an IP address
|
||||||
type Address struct {
|
type Address struct {
|
||||||
|
@ -106,3 +110,17 @@ type NetworkingConfig struct {
|
||||||
type ConfigReference struct {
|
type ConfigReference struct {
|
||||||
Network string
|
Network string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var acceptedFilters = map[string]bool{
|
||||||
|
"driver": true,
|
||||||
|
"type": true,
|
||||||
|
"name": true,
|
||||||
|
"id": true,
|
||||||
|
"label": true,
|
||||||
|
"scope": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateFilters validates the list of filter args with the available filters.
|
||||||
|
func ValidateFilters(filter filters.Args) error {
|
||||||
|
return errdefs.InvalidParameter(filter.Validate(acceptedFilters))
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package daemon // import "github.com/docker/docker/daemon"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
apitypes "github.com/docker/docker/api/types"
|
apitypes "github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
lncluster "github.com/docker/libnetwork/cluster"
|
lncluster "github.com/docker/libnetwork/cluster"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,6 +22,6 @@ type ClusterStatus interface {
|
||||||
// NetworkManager provides methods to manage networks
|
// NetworkManager provides methods to manage networks
|
||||||
type NetworkManager interface {
|
type NetworkManager interface {
|
||||||
GetNetwork(input string) (apitypes.NetworkResource, error)
|
GetNetwork(input string) (apitypes.NetworkResource, error)
|
||||||
GetNetworks() ([]apitypes.NetworkResource, error)
|
GetNetworks(filters.Args) ([]apitypes.NetworkResource, error)
|
||||||
RemoveNetwork(input string) error
|
RemoveNetwork(input string) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apitypes "github.com/docker/docker/api/types"
|
apitypes "github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
types "github.com/docker/docker/api/types/swarm"
|
types "github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/daemon/cluster/convert"
|
"github.com/docker/docker/daemon/cluster/convert"
|
||||||
|
internalnetwork "github.com/docker/docker/daemon/network"
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
swarmapi "github.com/docker/swarmkit/api"
|
swarmapi "github.com/docker/swarmkit/api"
|
||||||
|
@ -16,16 +18,32 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetNetworks returns all current cluster managed networks.
|
// GetNetworks returns all current cluster managed networks.
|
||||||
func (c *Cluster) GetNetworks() ([]apitypes.NetworkResource, error) {
|
func (c *Cluster) GetNetworks(filter filters.Args) ([]apitypes.NetworkResource, error) {
|
||||||
list, err := c.getNetworks(nil)
|
var f *swarmapi.ListNetworksRequest_Filters
|
||||||
|
|
||||||
|
if filter.Len() > 0 {
|
||||||
|
f = &swarmapi.ListNetworksRequest_Filters{}
|
||||||
|
|
||||||
|
if filter.Contains("name") {
|
||||||
|
f.Names = filter.Get("name")
|
||||||
|
f.NamePrefixes = filter.Get("name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Contains("id") {
|
||||||
|
f.IDPrefixes = filter.Get("id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err := c.getNetworks(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
removePredefinedNetworks(&list)
|
filterPredefinedNetworks(&list)
|
||||||
return list, nil
|
|
||||||
|
return internalnetwork.FilterNetworks(list, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removePredefinedNetworks(networks *[]apitypes.NetworkResource) {
|
func filterPredefinedNetworks(networks *[]apitypes.NetworkResource) {
|
||||||
if networks == nil {
|
if networks == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
||||||
|
@ -26,6 +27,7 @@ import (
|
||||||
"github.com/docker/libnetwork/driverapi"
|
"github.com/docker/libnetwork/driverapi"
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/networkdb"
|
||||||
"github.com/docker/libnetwork/options"
|
"github.com/docker/libnetwork/options"
|
||||||
networktypes "github.com/docker/libnetwork/types"
|
networktypes "github.com/docker/libnetwork/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -89,7 +91,7 @@ func (daemon *Daemon) FindNetwork(term string) (libnetwork.Network, error) {
|
||||||
func (daemon *Daemon) GetNetworkByID(id string) (libnetwork.Network, error) {
|
func (daemon *Daemon) GetNetworkByID(id string) (libnetwork.Network, error) {
|
||||||
c := daemon.netController
|
c := daemon.netController
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, libnetwork.ErrNoSuchNetwork(id)
|
return nil, errors.Wrap(libnetwork.ErrNoSuchNetwork(id), "netcontroller is nil")
|
||||||
}
|
}
|
||||||
return c.NetworkByID(id)
|
return c.NetworkByID(id)
|
||||||
}
|
}
|
||||||
|
@ -507,7 +509,7 @@ func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
|
||||||
func (daemon *Daemon) DeleteNetwork(networkID string) error {
|
func (daemon *Daemon) DeleteNetwork(networkID string) error {
|
||||||
n, err := daemon.GetNetworkByID(networkID)
|
n, err := daemon.GetNetworkByID(networkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "could not find network by ID")
|
||||||
}
|
}
|
||||||
return daemon.deleteNetwork(n, false)
|
return daemon.deleteNetwork(n, false)
|
||||||
}
|
}
|
||||||
|
@ -560,7 +562,7 @@ func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := nw.Delete(); err != nil {
|
if err := nw.Delete(); err != nil {
|
||||||
return err
|
return errors.Wrap(err, "error while removing network")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is not a configuration only network, we need to
|
// If this is not a configuration only network, we need to
|
||||||
|
@ -576,8 +578,212 @@ func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNetworks returns a list of all networks
|
// GetNetworks returns a list of all networks
|
||||||
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
|
func (daemon *Daemon) GetNetworks(filter filters.Args, config types.NetworkListConfig) ([]types.NetworkResource, error) {
|
||||||
return daemon.getAllNetworks()
|
networks := daemon.getAllNetworks()
|
||||||
|
|
||||||
|
list := make([]types.NetworkResource, 0, len(networks))
|
||||||
|
var idx map[string]libnetwork.Network
|
||||||
|
if config.Detailed {
|
||||||
|
idx = make(map[string]libnetwork.Network)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range networks {
|
||||||
|
nr := buildNetworkResource(n)
|
||||||
|
list = append(list, nr)
|
||||||
|
if config.Detailed {
|
||||||
|
idx[nr.ID] = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
list, err = internalnetwork.FilterNetworks(list, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Detailed {
|
||||||
|
for i, n := range list {
|
||||||
|
np := &n
|
||||||
|
buildDetailedNetworkResources(np, idx[n.ID], config.Verbose)
|
||||||
|
list[i] = *np
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildNetworkResource(nw libnetwork.Network) types.NetworkResource {
|
||||||
|
r := types.NetworkResource{}
|
||||||
|
if nw == nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
info := nw.Info()
|
||||||
|
r.Name = nw.Name()
|
||||||
|
r.ID = nw.ID()
|
||||||
|
r.Created = info.Created()
|
||||||
|
r.Scope = info.Scope()
|
||||||
|
r.Driver = nw.Type()
|
||||||
|
r.EnableIPv6 = info.IPv6Enabled()
|
||||||
|
r.Internal = info.Internal()
|
||||||
|
r.Attachable = info.Attachable()
|
||||||
|
r.Ingress = info.Ingress()
|
||||||
|
r.Options = info.DriverOptions()
|
||||||
|
r.Containers = make(map[string]types.EndpointResource)
|
||||||
|
buildIpamResources(&r, info)
|
||||||
|
r.Labels = info.Labels()
|
||||||
|
r.ConfigOnly = info.ConfigOnly()
|
||||||
|
|
||||||
|
if cn := info.ConfigFrom(); cn != "" {
|
||||||
|
r.ConfigFrom = network.ConfigReference{Network: cn}
|
||||||
|
}
|
||||||
|
|
||||||
|
peers := info.Peers()
|
||||||
|
if len(peers) != 0 {
|
||||||
|
r.Peers = buildPeerInfoResources(peers)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildDetailedNetworkResources(r *types.NetworkResource, nw libnetwork.Network, verbose bool) {
|
||||||
|
if nw == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
epl := nw.Endpoints()
|
||||||
|
for _, e := range epl {
|
||||||
|
ei := e.Info()
|
||||||
|
if ei == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sb := ei.Sandbox()
|
||||||
|
tmpID := e.ID()
|
||||||
|
key := "ep-" + tmpID
|
||||||
|
if sb != nil {
|
||||||
|
key = sb.ContainerID()
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei)
|
||||||
|
}
|
||||||
|
if !verbose {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
services := nw.Info().Services()
|
||||||
|
r.Services = make(map[string]network.ServiceInfo)
|
||||||
|
for name, service := range services {
|
||||||
|
tasks := []network.Task{}
|
||||||
|
for _, t := range service.Tasks {
|
||||||
|
tasks = append(tasks, network.Task{
|
||||||
|
Name: t.Name,
|
||||||
|
EndpointID: t.EndpointID,
|
||||||
|
EndpointIP: t.EndpointIP,
|
||||||
|
Info: t.Info,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
r.Services[name] = network.ServiceInfo{
|
||||||
|
VIP: service.VIP,
|
||||||
|
Ports: service.Ports,
|
||||||
|
Tasks: tasks,
|
||||||
|
LocalLBIndex: service.LocalLBIndex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPeerInfoResources(peers []networkdb.PeerInfo) []network.PeerInfo {
|
||||||
|
peerInfo := make([]network.PeerInfo, 0, len(peers))
|
||||||
|
for _, peer := range peers {
|
||||||
|
peerInfo = append(peerInfo, network.PeerInfo{
|
||||||
|
Name: peer.Name,
|
||||||
|
IP: peer.IP,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return peerInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildIpamResources(r *types.NetworkResource, nwInfo libnetwork.NetworkInfo) {
|
||||||
|
id, opts, ipv4conf, ipv6conf := nwInfo.IpamConfig()
|
||||||
|
|
||||||
|
ipv4Info, ipv6Info := nwInfo.IpamInfo()
|
||||||
|
|
||||||
|
r.IPAM.Driver = id
|
||||||
|
|
||||||
|
r.IPAM.Options = opts
|
||||||
|
|
||||||
|
r.IPAM.Config = []network.IPAMConfig{}
|
||||||
|
for _, ip4 := range ipv4conf {
|
||||||
|
if ip4.PreferredPool == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
iData := network.IPAMConfig{}
|
||||||
|
iData.Subnet = ip4.PreferredPool
|
||||||
|
iData.IPRange = ip4.SubPool
|
||||||
|
iData.Gateway = ip4.Gateway
|
||||||
|
iData.AuxAddress = ip4.AuxAddresses
|
||||||
|
r.IPAM.Config = append(r.IPAM.Config, iData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r.IPAM.Config) == 0 {
|
||||||
|
for _, ip4Info := range ipv4Info {
|
||||||
|
iData := network.IPAMConfig{}
|
||||||
|
iData.Subnet = ip4Info.IPAMData.Pool.String()
|
||||||
|
if ip4Info.IPAMData.Gateway != nil {
|
||||||
|
iData.Gateway = ip4Info.IPAMData.Gateway.IP.String()
|
||||||
|
}
|
||||||
|
r.IPAM.Config = append(r.IPAM.Config, iData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hasIpv6Conf := false
|
||||||
|
for _, ip6 := range ipv6conf {
|
||||||
|
if ip6.PreferredPool == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hasIpv6Conf = true
|
||||||
|
iData := network.IPAMConfig{}
|
||||||
|
iData.Subnet = ip6.PreferredPool
|
||||||
|
iData.IPRange = ip6.SubPool
|
||||||
|
iData.Gateway = ip6.Gateway
|
||||||
|
iData.AuxAddress = ip6.AuxAddresses
|
||||||
|
r.IPAM.Config = append(r.IPAM.Config, iData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasIpv6Conf {
|
||||||
|
for _, ip6Info := range ipv6Info {
|
||||||
|
if ip6Info.IPAMData.Pool == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
iData := network.IPAMConfig{}
|
||||||
|
iData.Subnet = ip6Info.IPAMData.Pool.String()
|
||||||
|
iData.Gateway = ip6Info.IPAMData.Gateway.String()
|
||||||
|
r.IPAM.Config = append(r.IPAM.Config, iData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildEndpointResource(id string, name string, info libnetwork.EndpointInfo) types.EndpointResource {
|
||||||
|
er := types.EndpointResource{}
|
||||||
|
|
||||||
|
er.EndpointID = id
|
||||||
|
er.Name = name
|
||||||
|
ei := info
|
||||||
|
if ei == nil {
|
||||||
|
return er
|
||||||
|
}
|
||||||
|
|
||||||
|
if iface := ei.Iface(); iface != nil {
|
||||||
|
if mac := iface.MacAddress(); mac != nil {
|
||||||
|
er.MacAddress = mac.String()
|
||||||
|
}
|
||||||
|
if ip := iface.Address(); ip != nil && len(ip.IP) > 0 {
|
||||||
|
er.IPv4Address = ip.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 {
|
||||||
|
er.IPv6Address = ipv6.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return er
|
||||||
}
|
}
|
||||||
|
|
||||||
// clearAttachableNetworks removes the attachable networks
|
// clearAttachableNetworks removes the attachable networks
|
||||||
|
|
92
daemon/network/filter.go
Normal file
92
daemon/network/filter.go
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
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/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 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 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
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package network // import "github.com/docker/docker/api/server/router/network"
|
package network // import "github.com/docker/docker/daemon/network"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -75,75 +75,89 @@ func TestFilterNetworks(t *testing.T) {
|
||||||
filter filters.Args
|
filter filters.Args
|
||||||
resultCount int
|
resultCount int
|
||||||
err string
|
err string
|
||||||
|
name string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
filter: bridgeDriverFilters,
|
filter: bridgeDriverFilters,
|
||||||
resultCount: 1,
|
resultCount: 1,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "bridge driver filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: overlayDriverFilters,
|
filter: overlayDriverFilters,
|
||||||
resultCount: 1,
|
resultCount: 1,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "overlay driver filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: nonameDriverFilters,
|
filter: nonameDriverFilters,
|
||||||
resultCount: 0,
|
resultCount: 0,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "no name driver filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: customDriverFilters,
|
filter: customDriverFilters,
|
||||||
resultCount: 3,
|
resultCount: 3,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "custom driver filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: builtinDriverFilters,
|
filter: builtinDriverFilters,
|
||||||
resultCount: 3,
|
resultCount: 3,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "builtin driver filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: invalidDriverFilters,
|
filter: invalidDriverFilters,
|
||||||
resultCount: 0,
|
resultCount: 0,
|
||||||
err: "Invalid filter: 'type'='invalid'",
|
err: "invalid filter: 'type'='invalid'",
|
||||||
|
name: "invalid driver filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: localScopeFilters,
|
filter: localScopeFilters,
|
||||||
resultCount: 4,
|
resultCount: 4,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "local scope filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: swarmScopeFilters,
|
filter: swarmScopeFilters,
|
||||||
resultCount: 1,
|
resultCount: 1,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "swarm scope filters",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filter: globalScopeFilters,
|
filter: globalScopeFilters,
|
||||||
resultCount: 1,
|
resultCount: 1,
|
||||||
err: "",
|
err: "",
|
||||||
|
name: "global scope filters",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
result, err := filterNetworks(networks, testCase.filter)
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
if testCase.err != "" {
|
ls := make([]types.NetworkResource, 0, len(networks))
|
||||||
if err == nil {
|
ls = append(ls, networks...)
|
||||||
t.Fatalf("expect error '%s', got no error", testCase.err)
|
result, err := FilterNetworks(ls, testCase.filter)
|
||||||
|
if testCase.err != "" {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expect error '%s', got no error", testCase.err)
|
||||||
|
|
||||||
} else if !strings.Contains(err.Error(), testCase.err) {
|
} else if !strings.Contains(err.Error(), testCase.err) {
|
||||||
t.Fatalf("expect error '%s', got '%s'", testCase.err, err)
|
t.Fatalf("expect error '%s', got '%s'", testCase.err, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("expect no error, got error '%s'", err)
|
t.Fatalf("expect no error, got error '%s'", err)
|
||||||
}
|
}
|
||||||
// Make sure result is not nil
|
// Make sure result is not nil
|
||||||
if result == nil {
|
if result == nil {
|
||||||
t.Fatal("filterNetworks should not return nil")
|
t.Fatal("filterNetworks should not return nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(result) != testCase.resultCount {
|
if len(result) != testCase.resultCount {
|
||||||
t.Fatalf("expect '%d' networks, got '%d' networks", testCase.resultCount, len(result))
|
t.Fatalf("expect '%d' networks, got '%d' networks", testCase.resultCount, len(result))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -141,7 +141,7 @@ func (daemon *Daemon) clusterNetworksPrune(ctx context.Context, pruneFilters fil
|
||||||
return rep, nil
|
return rep, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
networks, err := cluster.GetNetworks()
|
networks, err := cluster.GetNetworks(pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rep, err
|
return rep, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue