docs/cluster/network.go

164 lines
4.1 KiB
Go

package cluster
import (
"strings"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/engine-api/types"
)
// Network is exported
type Network struct {
types.NetworkResource
Engine *Engine
}
func (network *Network) isPreDefined() bool {
return (network.Name == "none" || network.Name == "host" || network.Name == "bridge")
}
// Networks represents an array of networks
type Networks []*Network
// Uniq returns all uniq networks
func (networks Networks) Uniq() Networks {
tmp := make(map[string]*Network)
for _, network := range networks {
if _, ok := tmp[network.ID]; ok {
for id, endpoint := range network.Containers {
tmp[network.ID].Containers[id] = endpoint
}
} else {
netCopy := *network
netCopy.Containers = make(map[string]types.EndpointResource)
for key, value := range network.Containers {
netCopy.Containers[key] = value
}
tmp[network.ID] = &netCopy
}
}
uniq := Networks{}
for _, network := range tmp {
uniq = append(uniq, network)
}
return uniq
}
// Filter returns networks filtered by names or ids
func (networks Networks) Filter(names []string, ids []string, types []string) Networks {
typeFilter := func(network *Network) bool {
if len(types) > 0 {
for _, typ := range types {
if typ == "custom" && !network.isPreDefined() {
return true
}
if typ == "builtin" && network.isPreDefined() {
return true
}
}
} else {
return true
}
return false
}
out := Networks{}
if len(names) == 0 && len(ids) == 0 {
for _, network := range networks.Uniq() {
if typeFilter(network) {
out = append(out, network)
}
}
} else {
for _, idOrName := range append(names, ids...) {
if network := networks.Get(idOrName); network != nil {
if typeFilter(network) {
out = append(out, network)
}
}
}
}
return out
}
// RemoveDuplicateEndpoints returns a copy of input network
// where duplicate container endpoints in the network are removed.
// See https://github.com/docker/swarm/issues/1969
// This function should be disabled when the bug is fixed in Docker network
func (network *Network) RemoveDuplicateEndpoints() *Network {
// build a map from endpointID -> endpointIndex
endpointMap := make(map[string]string)
// traverse the endpoints to find the correct endpointIndex for each endpointID
for endpointIndex, endpointResource := range network.NetworkResource.Containers {
endpointID := endpointResource.EndpointID
// if this endpointID doesn't exist yet, add it
// if this endpointID exists, but endpointIndex is not a duplicate, use
// this endpointIndex
if _, ok := endpointMap[endpointID]; !ok || !strings.Contains(endpointIndex, endpointID) {
endpointMap[endpointID] = endpointIndex
}
}
// Make a copy of the network
netCopy := *network
// clean up existing endpoints
netCopy.Containers = make(map[string]types.EndpointResource)
// add the endpoint index from endpointMap
for _, index := range endpointMap {
netCopy.Containers[index] = network.Containers[index]
}
return &netCopy
}
// Get returns a network using its ID or Name
func (networks Networks) Get(IDOrName string) *Network {
// Abort immediately if the name is empty.
if len(IDOrName) == 0 {
return nil
}
// Match exact or short Network ID.
for _, network := range networks {
if network.ID == IDOrName || stringid.TruncateID(network.ID) == IDOrName {
return network
}
}
candidates := Networks{}
// Match name or engine/name.
for _, network := range networks {
if network.Name == IDOrName || network.Engine.ID+"/"+network.Name == IDOrName || network.Engine.Name+"/"+network.Name == IDOrName {
candidates = append(candidates, network)
}
}
// Return if we found a unique match.
if size := len(candidates.Uniq()); size == 1 {
return candidates[0]
} else if size > 1 {
return nil
}
// Match /name and return as soon as we find one.
for _, network := range networks {
if network.Name == "/"+IDOrName {
return network
}
}
// Match Network ID prefix.
for _, network := range networks {
if strings.HasPrefix(network.ID, IDOrName) {
candidates = append(candidates, network)
}
}
if len(candidates.Uniq()) == 1 {
return candidates[0]
}
return nil
}