mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Global alias support
Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
parent
be981267c0
commit
2db863e5d7
9 changed files with 141 additions and 29 deletions
|
@ -379,6 +379,10 @@ func procCreateEndpoint(c libnetwork.NetworkController, vars map[string]string,
|
||||||
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(ec.PortMapping))
|
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(ec.PortMapping))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, str := range ec.MyAliases {
|
||||||
|
setFctList = append(setFctList, libnetwork.CreateOptionMyAlias(str))
|
||||||
|
}
|
||||||
|
|
||||||
ep, err := n.CreateEndpoint(ec.Name, setFctList...)
|
ep, err := n.CreateEndpoint(ec.Name, setFctList...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", convertNetworkError(err)
|
return "", convertNetworkError(err)
|
||||||
|
@ -624,6 +628,10 @@ func procPublishService(c libnetwork.NetworkController, vars map[string]string,
|
||||||
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(sp.PortMapping))
|
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(sp.PortMapping))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, str := range sp.MyAliases {
|
||||||
|
setFctList = append(setFctList, libnetwork.CreateOptionMyAlias(str))
|
||||||
|
}
|
||||||
|
|
||||||
ep, err := n.CreateEndpoint(sp.Name, setFctList...)
|
ep, err := n.CreateEndpoint(sp.Name, setFctList...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", endpointToService(convertNetworkError(err))
|
return "", endpointToService(convertNetworkError(err))
|
||||||
|
|
|
@ -43,6 +43,7 @@ type networkCreate struct {
|
||||||
// endpointCreate represents the body of the "create endpoint" http request message
|
// endpointCreate represents the body of the "create endpoint" http request message
|
||||||
type endpointCreate struct {
|
type endpointCreate struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
MyAliases []string `json:"my_aliases"`
|
||||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,7 @@ type endpointJoin struct {
|
||||||
// servicePublish represents the body of the "publish service" http request message
|
// servicePublish represents the body of the "publish service" http request message
|
||||||
type servicePublish struct {
|
type servicePublish struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
MyAliases []string `json:"my_aliases"`
|
||||||
Network string `json:"network_name"`
|
Network string `json:"network_name"`
|
||||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||||
|
|
|
@ -163,6 +163,8 @@ func parseServiceName(name string) (string, string) {
|
||||||
// CmdServicePublish handles service create UI
|
// CmdServicePublish handles service create UI
|
||||||
func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error {
|
func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error {
|
||||||
cmd := cli.Subcmd(chain, "publish", "SERVICE[.NETWORK]", "Publish a new service on a network", false)
|
cmd := cli.Subcmd(chain, "publish", "SERVICE[.NETWORK]", "Publish a new service on a network", false)
|
||||||
|
flAlias := opts.NewListOpts(netutils.ValidateAlias)
|
||||||
|
cmd.Var(&flAlias, []string{"-alias"}, "Add alias to self")
|
||||||
cmd.Require(flag.Exact, 1)
|
cmd.Require(flag.Exact, 1)
|
||||||
err := cmd.ParseFlags(args, true)
|
err := cmd.ParseFlags(args, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +172,7 @@ func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
sn, nn := parseServiceName(cmd.Arg(0))
|
sn, nn := parseServiceName(cmd.Arg(0))
|
||||||
sc := serviceCreate{Name: sn, Network: nn}
|
sc := serviceCreate{Name: sn, Network: nn, MyAliases: flAlias.GetAll()}
|
||||||
obj, _, err := readBody(cli.call("POST", "/services", sc, nil))
|
obj, _, err := readBody(cli.call("POST", "/services", sc, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -43,6 +43,7 @@ type networkCreate struct {
|
||||||
// serviceCreate represents the body of the "publish service" http request message
|
// serviceCreate represents the body of the "publish service" http request message
|
||||||
type serviceCreate struct {
|
type serviceCreate struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
MyAliases []string `json:"my_aliases"`
|
||||||
Network string `json:"network_name"`
|
Network string `json:"network_name"`
|
||||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||||
|
|
|
@ -65,6 +65,7 @@ type endpoint struct {
|
||||||
prefAddressV6 net.IP
|
prefAddressV6 net.IP
|
||||||
ipamOptions map[string]string
|
ipamOptions map[string]string
|
||||||
aliases map[string]string
|
aliases map[string]string
|
||||||
|
myAliases []string
|
||||||
dbIndex uint64
|
dbIndex uint64
|
||||||
dbExists bool
|
dbExists bool
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
@ -85,6 +86,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
||||||
epMap["sandbox"] = ep.sandboxID
|
epMap["sandbox"] = ep.sandboxID
|
||||||
epMap["anonymous"] = ep.anonymous
|
epMap["anonymous"] = ep.anonymous
|
||||||
epMap["disableResolution"] = ep.disableResolution
|
epMap["disableResolution"] = ep.disableResolution
|
||||||
|
epMap["myAliases"] = ep.myAliases
|
||||||
return json.Marshal(epMap)
|
return json.Marshal(epMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +167,10 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
|
||||||
if v, ok := epMap["disableResolution"]; ok {
|
if v, ok := epMap["disableResolution"]; ok {
|
||||||
ep.disableResolution = v.(bool)
|
ep.disableResolution = v.(bool)
|
||||||
}
|
}
|
||||||
|
ma, _ := json.Marshal(epMap["myAliases"])
|
||||||
|
var myAliases []string
|
||||||
|
json.Unmarshal(ma, &myAliases)
|
||||||
|
ep.myAliases = myAliases
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +199,9 @@ func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
||||||
dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
|
dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
|
||||||
copy(dstEp.exposedPorts, ep.exposedPorts)
|
copy(dstEp.exposedPorts, ep.exposedPorts)
|
||||||
|
|
||||||
|
dstEp.myAliases = make([]string, len(ep.myAliases))
|
||||||
|
copy(dstEp.myAliases, ep.myAliases)
|
||||||
|
|
||||||
dstEp.generic = options.Generic{}
|
dstEp.generic = options.Generic{}
|
||||||
for k, v := range ep.generic {
|
for k, v := range ep.generic {
|
||||||
dstEp.generic[k] = v
|
dstEp.generic[k] = v
|
||||||
|
@ -215,6 +224,13 @@ func (ep *endpoint) Name() string {
|
||||||
return ep.name
|
return ep.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ep *endpoint) MyAliases() []string {
|
||||||
|
ep.Lock()
|
||||||
|
defer ep.Unlock()
|
||||||
|
|
||||||
|
return ep.myAliases
|
||||||
|
}
|
||||||
|
|
||||||
func (ep *endpoint) Network() string {
|
func (ep *endpoint) Network() string {
|
||||||
if ep.network == nil {
|
if ep.network == nil {
|
||||||
return ""
|
return ""
|
||||||
|
@ -759,6 +775,13 @@ func CreateOptionAlias(name string, alias string) EndpointOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//CreateOptionMyAlias function returns an option setter for setting endpoint's self alias
|
||||||
|
func CreateOptionMyAlias(alias string) EndpointOption {
|
||||||
|
return func(ep *endpoint) {
|
||||||
|
ep.myAliases = append(ep.myAliases, alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// JoinOptionPriority function returns an option setter for priority option to
|
// JoinOptionPriority function returns an option setter for priority option to
|
||||||
// be passed to the endpoint.Join() method.
|
// be passed to the endpoint.Join() method.
|
||||||
func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
|
func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
|
||||||
|
|
|
@ -70,7 +70,7 @@ type NetworkInfo interface {
|
||||||
type EndpointWalker func(ep Endpoint) bool
|
type EndpointWalker func(ep Endpoint) bool
|
||||||
|
|
||||||
type svcInfo struct {
|
type svcInfo struct {
|
||||||
svcMap map[string]net.IP
|
svcMap map[string][]net.IP
|
||||||
ipMap map[string]string
|
ipMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,36 +831,77 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
epName := ep.Name()
|
||||||
|
if iface := ep.Iface(); iface.Address() != nil {
|
||||||
|
myAliases := ep.MyAliases()
|
||||||
|
if isAdd {
|
||||||
|
n.addSvcRecords(epName, iface.Address().IP, true)
|
||||||
|
for _, alias := range myAliases {
|
||||||
|
n.addSvcRecords(alias, iface.Address().IP, false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n.deleteSvcRecords(epName, iface.Address().IP, true)
|
||||||
|
for _, alias := range myAliases {
|
||||||
|
n.deleteSvcRecords(alias, iface.Address().IP, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *network) addSvcRecords(name string, epIP net.IP, ipMapUpdate bool) {
|
||||||
c := n.getController()
|
c := n.getController()
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
sr, ok := c.svcDb[n.ID()]
|
sr, ok := c.svcDb[n.ID()]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.svcDb[n.ID()] = svcInfo{
|
sr = svcInfo{
|
||||||
svcMap: make(map[string]net.IP),
|
svcMap: make(map[string][]net.IP),
|
||||||
ipMap: make(map[string]string),
|
ipMap: make(map[string]string),
|
||||||
}
|
}
|
||||||
sr = c.svcDb[n.ID()]
|
c.svcDb[n.ID()] = sr
|
||||||
}
|
}
|
||||||
|
|
||||||
epName := ep.Name()
|
if ipMapUpdate {
|
||||||
n.Lock()
|
reverseIP := netutils.ReverseIP(epIP.String())
|
||||||
if iface := ep.Iface(); iface.Address() != nil {
|
if _, ok := sr.ipMap[reverseIP]; !ok {
|
||||||
|
sr.ipMap[reverseIP] = name
|
||||||
reverseIP := netutils.ReverseIP(iface.Address().IP.String())
|
|
||||||
if isAdd {
|
|
||||||
// If we already have this endpoint in service db just return
|
|
||||||
if _, ok := sr.svcMap[epName]; ok {
|
|
||||||
n.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sr.svcMap[epName] = iface.Address().IP
|
|
||||||
sr.ipMap[reverseIP] = epName
|
|
||||||
} else {
|
|
||||||
delete(sr.svcMap, epName)
|
|
||||||
delete(sr.ipMap, reverseIP)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n.Unlock()
|
|
||||||
|
ipList := sr.svcMap[name]
|
||||||
|
for _, ip := range ipList {
|
||||||
|
if ip.Equal(epIP) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sr.svcMap[name] = append(sr.svcMap[name], epIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *network) deleteSvcRecords(name string, epIP net.IP, ipMapUpdate bool) {
|
||||||
|
c := n.getController()
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
sr, ok := c.svcDb[n.ID()]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipMapUpdate {
|
||||||
|
delete(sr.ipMap, netutils.ReverseIP(epIP.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
ipList := sr.svcMap[name]
|
||||||
|
for i, ip := range ipList {
|
||||||
|
if ip.Equal(epIP) {
|
||||||
|
ipList = append(ipList[:i], ipList[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sr.svcMap[name] = ipList
|
||||||
|
|
||||||
|
if len(ipList) == 0 {
|
||||||
|
delete(sr.svcMap, name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
|
func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
|
||||||
|
@ -877,7 +918,7 @@ func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
|
||||||
|
|
||||||
recs = append(recs, etchosts.Record{
|
recs = append(recs, etchosts.Record{
|
||||||
Hosts: h,
|
Hosts: h,
|
||||||
IP: ip.String(),
|
IP: ip[0].String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -481,7 +481,7 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
|
||||||
ip, ok := sr.svcMap[name]
|
ip, ok := sr.svcMap[name]
|
||||||
n.Unlock()
|
n.Unlock()
|
||||||
if ok {
|
if ok {
|
||||||
return ip
|
return ip[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -249,3 +249,33 @@ function test_single_network_connectivity() {
|
||||||
dnet_cmd $(inst_id2port 1) container rm container_2
|
dnet_cmd $(inst_id2port 1) container rm container_2
|
||||||
dnet_cmd $(inst_id2port 1) network rm br1
|
dnet_cmd $(inst_id2port 1) network rm br1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "Test bridge network global alias support" {
|
||||||
|
skip_for_circleci
|
||||||
|
dnet_cmd $(inst_id2port 1) network create -d bridge br1
|
||||||
|
dnet_cmd $(inst_id2port 1) network create -d bridge br2
|
||||||
|
dnet_cmd $(inst_id2port 1) container create container_1
|
||||||
|
net_connect 1 container_1 br1 : c1
|
||||||
|
dnet_cmd $(inst_id2port 1) container create container_2
|
||||||
|
net_connect 1 container_2 br1 : shared
|
||||||
|
dnet_cmd $(inst_id2port 1) container create container_3
|
||||||
|
net_connect 1 container_3 br1 : shared
|
||||||
|
|
||||||
|
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_2) "ping -c 1 container_1"
|
||||||
|
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_2) "ping -c 1 c1"
|
||||||
|
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 container_2"
|
||||||
|
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 shared"
|
||||||
|
|
||||||
|
net_disconnect 1 container_2 br1
|
||||||
|
dnet_cmd $(inst_id2port 1) container rm container_2
|
||||||
|
|
||||||
|
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 container_3"
|
||||||
|
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 shared"
|
||||||
|
|
||||||
|
net_disconnect 1 container_1 br1
|
||||||
|
dnet_cmd $(inst_id2port 1) container rm container_1
|
||||||
|
net_disconnect 1 container_3 br1
|
||||||
|
dnet_cmd $(inst_id2port 1) container rm container_3
|
||||||
|
|
||||||
|
dnet_cmd $(inst_id2port 1) network rm br1
|
||||||
|
}
|
||||||
|
|
|
@ -18,12 +18,17 @@ function get_sbox_id() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function net_connect() {
|
function net_connect() {
|
||||||
local al
|
local al gl
|
||||||
if [ -n "$4" ]; then
|
if [ -n "$4" ]; then
|
||||||
al="--alias=${4}"
|
if [ "${4}" != ":" ]; then
|
||||||
|
al="--alias=${4}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
dnet_cmd $(inst_id2port ${1}) service publish ${2}.${3}
|
if [ -n "$5" ]; then
|
||||||
dnet_cmd $(inst_id2port ${1}) service attach $al ${2} ${2}.${3}
|
gl="--alias=${5}"
|
||||||
|
fi
|
||||||
|
dnet_cmd $(inst_id2port ${1}) service publish $gl ${2}.${3}
|
||||||
|
dnet_cmd $(inst_id2port ${1}) service attach $al ${2} ${2}.${3}
|
||||||
}
|
}
|
||||||
|
|
||||||
function net_disconnect() {
|
function net_disconnect() {
|
||||||
|
|
Loading…
Reference in a new issue