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.
 | 
			
		||||
type Backend interface {
 | 
			
		||||
	FindNetwork(idName string) (libnetwork.Network, error)
 | 
			
		||||
	GetNetworks() []libnetwork.Network
 | 
			
		||||
	GetNetworks(filters.Args, types.NetworkListConfig) ([]types.NetworkResource, error)
 | 
			
		||||
	CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
 | 
			
		||||
	ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) 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
 | 
			
		||||
// to provide cluster network specific functionality.
 | 
			
		||||
type ClusterBackend interface {
 | 
			
		||||
	GetNetworks() ([]types.NetworkResource, error)
 | 
			
		||||
	GetNetworks(filters.Args) ([]types.NetworkResource, error)
 | 
			
		||||
	GetNetwork(name string) (types.NetworkResource, error)
 | 
			
		||||
	GetNetworksByName(name string) ([]types.NetworkResource, error)
 | 
			
		||||
	CreateNetwork(nc types.NetworkCreateRequest) (string, error)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,93 +1 @@
 | 
			
		|||
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/libnetwork"
 | 
			
		||||
	netconst "github.com/docker/libnetwork/datastore"
 | 
			
		||||
	"github.com/docker/libnetwork/networkdb"
 | 
			
		||||
	"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 {
 | 
			
		||||
	if err := httputils.ParseForm(r); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	filter := r.Form.Get("filters")
 | 
			
		||||
	netFilters, err := filters.FromJSON(filter)
 | 
			
		||||
	filter, err := filters.FromJSON(r.Form.Get("filters"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := netFilters.Validate(acceptedNetworkFilters); err != nil {
 | 
			
		||||
	if err := network.ValidateFilters(filter); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list := []types.NetworkResource{}
 | 
			
		||||
 | 
			
		||||
	if nr, err := n.cluster.GetNetworks(); err == nil {
 | 
			
		||||
		list = append(list, nr...)
 | 
			
		||||
	var list []types.NetworkResource
 | 
			
		||||
	nr, err := n.cluster.GetNetworks(filter)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		list = nr
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Combine the network list returned by Docker daemon if it is not already
 | 
			
		||||
	// returned by the cluster manager
 | 
			
		||||
SKIP:
 | 
			
		||||
	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)
 | 
			
		||||
	localNetworks, err := n.backend.GetNetworks(filter, types.NetworkListConfig{Detailed: versions.LessThan(httputils.VersionFromContext(ctx), "1.28")})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,13 +105,6 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r
 | 
			
		|||
	}
 | 
			
		||||
	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.
 | 
			
		||||
	// 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{}
 | 
			
		||||
	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 {
 | 
			
		||||
		if network.ID() == term && isMatchingScope(network.Info().Scope(), scope) {
 | 
			
		||||
			return httputils.WriteJSON(w, http.StatusOK, *n.buildDetailedNetworkResources(network, verbose))
 | 
			
		||||
		if network.ID == term {
 | 
			
		||||
			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
 | 
			
		||||
			// 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
 | 
			
		||||
			// 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 {
 | 
			
		||||
		if network.ID == term && isMatchingScope(network.Scope, scope) {
 | 
			
		||||
		if network.ID == term {
 | 
			
		||||
			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
 | 
			
		||||
			// the map (of the listByFullName) may have already had a
 | 
			
		||||
			// 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
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		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
 | 
			
		||||
			// the map (of the listByPartialID) may have already had a
 | 
			
		||||
			// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
	if err := httputils.ParseForm(r); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -532,25 +339,25 @@ func (n *networkRouter) findUniqueNetwork(term string) (types.NetworkResource, e
 | 
			
		|||
	listByFullName := 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 {
 | 
			
		||||
		if network.ID() == term {
 | 
			
		||||
			return *n.buildDetailedNetworkResources(network, false), nil
 | 
			
		||||
 | 
			
		||||
		if network.ID == term {
 | 
			
		||||
			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
 | 
			
		||||
			// 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
 | 
			
		||||
			// 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 {
 | 
			
		||||
		if network.ID == term {
 | 
			
		||||
			return network, nil
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,3 +55,10 @@ type PluginEnableConfig struct {
 | 
			
		|||
type PluginDisableConfig struct {
 | 
			
		||||
	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"
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/errdefs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Address represents an IP address
 | 
			
		||||
type Address struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -106,3 +110,17 @@ type NetworkingConfig struct {
 | 
			
		|||
type ConfigReference struct {
 | 
			
		||||
	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 (
 | 
			
		||||
	apitypes "github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	lncluster "github.com/docker/libnetwork/cluster"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +22,6 @@ type ClusterStatus interface {
 | 
			
		|||
// NetworkManager provides methods to manage networks
 | 
			
		||||
type NetworkManager interface {
 | 
			
		||||
	GetNetwork(input string) (apitypes.NetworkResource, error)
 | 
			
		||||
	GetNetworks() ([]apitypes.NetworkResource, error)
 | 
			
		||||
	GetNetworks(filters.Args) ([]apitypes.NetworkResource, error)
 | 
			
		||||
	RemoveNetwork(input string) error
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,11 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	apitypes "github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/api/types/network"
 | 
			
		||||
	types "github.com/docker/docker/api/types/swarm"
 | 
			
		||||
	"github.com/docker/docker/daemon/cluster/convert"
 | 
			
		||||
	internalnetwork "github.com/docker/docker/daemon/network"
 | 
			
		||||
	"github.com/docker/docker/errdefs"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	swarmapi "github.com/docker/swarmkit/api"
 | 
			
		||||
| 
						 | 
				
			
			@ -16,16 +18,32 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
// GetNetworks returns all current cluster managed networks.
 | 
			
		||||
func (c *Cluster) GetNetworks() ([]apitypes.NetworkResource, error) {
 | 
			
		||||
	list, err := c.getNetworks(nil)
 | 
			
		||||
func (c *Cluster) GetNetworks(filter filters.Args) ([]apitypes.NetworkResource, error) {
 | 
			
		||||
	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 {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	removePredefinedNetworks(&list)
 | 
			
		||||
	return list, nil
 | 
			
		||||
	filterPredefinedNetworks(&list)
 | 
			
		||||
 | 
			
		||||
	return internalnetwork.FilterNetworks(list, filter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func removePredefinedNetworks(networks *[]apitypes.NetworkResource) {
 | 
			
		||||
func filterPredefinedNetworks(networks *[]apitypes.NetworkResource) {
 | 
			
		||||
	if networks == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	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/container"
 | 
			
		||||
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +27,7 @@ import (
 | 
			
		|||
	"github.com/docker/libnetwork/driverapi"
 | 
			
		||||
	"github.com/docker/libnetwork/ipamapi"
 | 
			
		||||
	"github.com/docker/libnetwork/netlabel"
 | 
			
		||||
	"github.com/docker/libnetwork/networkdb"
 | 
			
		||||
	"github.com/docker/libnetwork/options"
 | 
			
		||||
	networktypes "github.com/docker/libnetwork/types"
 | 
			
		||||
	"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) {
 | 
			
		||||
	c := daemon.netController
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		return nil, libnetwork.ErrNoSuchNetwork(id)
 | 
			
		||||
		return nil, errors.Wrap(libnetwork.ErrNoSuchNetwork(id), "netcontroller is nil")
 | 
			
		||||
	}
 | 
			
		||||
	return c.NetworkByID(id)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -507,7 +509,7 @@ func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
 | 
			
		|||
func (daemon *Daemon) DeleteNetwork(networkID string) error {
 | 
			
		||||
	n, err := daemon.GetNetworkByID(networkID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
		return errors.Wrap(err, "could not find network by ID")
 | 
			
		||||
	}
 | 
			
		||||
	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 {
 | 
			
		||||
		return err
 | 
			
		||||
		return errors.Wrap(err, "error while removing network")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
 | 
			
		||||
	return daemon.getAllNetworks()
 | 
			
		||||
func (daemon *Daemon) GetNetworks(filter filters.Args, config types.NetworkListConfig) ([]types.NetworkResource, error) {
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
package network // import "github.com/docker/docker/api/server/router/network"
 | 
			
		||||
package network // import "github.com/docker/docker/daemon/network"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
| 
						 | 
				
			
			@ -75,75 +75,89 @@ func TestFilterNetworks(t *testing.T) {
 | 
			
		|||
		filter      filters.Args
 | 
			
		||||
		resultCount int
 | 
			
		||||
		err         string
 | 
			
		||||
		name        string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			filter:      bridgeDriverFilters,
 | 
			
		||||
			resultCount: 1,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "bridge driver filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      overlayDriverFilters,
 | 
			
		||||
			resultCount: 1,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "overlay driver filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      nonameDriverFilters,
 | 
			
		||||
			resultCount: 0,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "no name driver filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      customDriverFilters,
 | 
			
		||||
			resultCount: 3,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "custom driver filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      builtinDriverFilters,
 | 
			
		||||
			resultCount: 3,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "builtin driver filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      invalidDriverFilters,
 | 
			
		||||
			resultCount: 0,
 | 
			
		||||
			err:         "Invalid filter: 'type'='invalid'",
 | 
			
		||||
			err:         "invalid filter: 'type'='invalid'",
 | 
			
		||||
			name:        "invalid driver filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      localScopeFilters,
 | 
			
		||||
			resultCount: 4,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "local scope filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      swarmScopeFilters,
 | 
			
		||||
			resultCount: 1,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "swarm scope filters",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			filter:      globalScopeFilters,
 | 
			
		||||
			resultCount: 1,
 | 
			
		||||
			err:         "",
 | 
			
		||||
			name:        "global scope filters",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, testCase := range testCases {
 | 
			
		||||
		result, err := filterNetworks(networks, testCase.filter)
 | 
			
		||||
		if testCase.err != "" {
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				t.Fatalf("expect error '%s', got no error", testCase.err)
 | 
			
		||||
		t.Run(testCase.name, func(t *testing.T) {
 | 
			
		||||
			ls := make([]types.NetworkResource, 0, len(networks))
 | 
			
		||||
			ls = append(ls, networks...)
 | 
			
		||||
			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) {
 | 
			
		||||
				t.Fatalf("expect error '%s', got '%s'", testCase.err, err)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("expect no error, got error '%s'", err)
 | 
			
		||||
			}
 | 
			
		||||
			// Make sure result is not nil
 | 
			
		||||
			if result == nil {
 | 
			
		||||
				t.Fatal("filterNetworks should not return nil")
 | 
			
		||||
			}
 | 
			
		||||
				} else if !strings.Contains(err.Error(), testCase.err) {
 | 
			
		||||
					t.Fatalf("expect error '%s', got '%s'", testCase.err, err)
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatalf("expect no error, got error '%s'", err)
 | 
			
		||||
				}
 | 
			
		||||
				// Make sure result is not nil
 | 
			
		||||
				if result == nil {
 | 
			
		||||
					t.Fatal("filterNetworks should not return nil")
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			if len(result) != testCase.resultCount {
 | 
			
		||||
				t.Fatalf("expect '%d' networks, got '%d' networks", testCase.resultCount, len(result))
 | 
			
		||||
				if len(result) != testCase.resultCount {
 | 
			
		||||
					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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	networks, err := cluster.GetNetworks()
 | 
			
		||||
	networks, err := cluster.GetNetworks(pruneFilters)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return rep, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue