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))
|
||||
}
|
||||
|
||||
for _, str := range ec.MyAliases {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionMyAlias(str))
|
||||
}
|
||||
|
||||
ep, err := n.CreateEndpoint(ec.Name, setFctList...)
|
||||
if err != nil {
|
||||
return "", convertNetworkError(err)
|
||||
|
@ -624,6 +628,10 @@ func procPublishService(c libnetwork.NetworkController, vars map[string]string,
|
|||
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...)
|
||||
if err != nil {
|
||||
return "", endpointToService(convertNetworkError(err))
|
||||
|
|
|
@ -43,6 +43,7 @@ type networkCreate struct {
|
|||
// endpointCreate represents the body of the "create endpoint" http request message
|
||||
type endpointCreate struct {
|
||||
Name string `json:"name"`
|
||||
MyAliases []string `json:"my_aliases"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
}
|
||||
|
@ -69,6 +70,7 @@ type endpointJoin struct {
|
|||
// servicePublish represents the body of the "publish service" http request message
|
||||
type servicePublish struct {
|
||||
Name string `json:"name"`
|
||||
MyAliases []string `json:"my_aliases"`
|
||||
Network string `json:"network_name"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
|
|
|
@ -163,6 +163,8 @@ func parseServiceName(name string) (string, string) {
|
|||
// CmdServicePublish handles service create UI
|
||||
func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error {
|
||||
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)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
|
@ -170,7 +172,7 @@ func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error {
|
|||
}
|
||||
|
||||
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))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -43,6 +43,7 @@ type networkCreate struct {
|
|||
// serviceCreate represents the body of the "publish service" http request message
|
||||
type serviceCreate struct {
|
||||
Name string `json:"name"`
|
||||
MyAliases []string `json:"my_aliases"`
|
||||
Network string `json:"network_name"`
|
||||
ExposedPorts []types.TransportPort `json:"exposed_ports"`
|
||||
PortMapping []types.PortBinding `json:"port_mapping"`
|
||||
|
|
|
@ -65,6 +65,7 @@ type endpoint struct {
|
|||
prefAddressV6 net.IP
|
||||
ipamOptions map[string]string
|
||||
aliases map[string]string
|
||||
myAliases []string
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
sync.Mutex
|
||||
|
@ -85,6 +86,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
|||
epMap["sandbox"] = ep.sandboxID
|
||||
epMap["anonymous"] = ep.anonymous
|
||||
epMap["disableResolution"] = ep.disableResolution
|
||||
epMap["myAliases"] = ep.myAliases
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
|
@ -165,6 +167,10 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
|
|||
if v, ok := epMap["disableResolution"]; ok {
|
||||
ep.disableResolution = v.(bool)
|
||||
}
|
||||
ma, _ := json.Marshal(epMap["myAliases"])
|
||||
var myAliases []string
|
||||
json.Unmarshal(ma, &myAliases)
|
||||
ep.myAliases = myAliases
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -193,6 +199,9 @@ func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
|||
dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
|
||||
copy(dstEp.exposedPorts, ep.exposedPorts)
|
||||
|
||||
dstEp.myAliases = make([]string, len(ep.myAliases))
|
||||
copy(dstEp.myAliases, ep.myAliases)
|
||||
|
||||
dstEp.generic = options.Generic{}
|
||||
for k, v := range ep.generic {
|
||||
dstEp.generic[k] = v
|
||||
|
@ -215,6 +224,13 @@ func (ep *endpoint) Name() string {
|
|||
return ep.name
|
||||
}
|
||||
|
||||
func (ep *endpoint) MyAliases() []string {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
return ep.myAliases
|
||||
}
|
||||
|
||||
func (ep *endpoint) Network() string {
|
||||
if ep.network == nil {
|
||||
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
|
||||
// be passed to the endpoint.Join() method.
|
||||
func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
|
||||
|
|
|
@ -70,7 +70,7 @@ type NetworkInfo interface {
|
|||
type EndpointWalker func(ep Endpoint) bool
|
||||
|
||||
type svcInfo struct {
|
||||
svcMap map[string]net.IP
|
||||
svcMap map[string][]net.IP
|
||||
ipMap map[string]string
|
||||
}
|
||||
|
||||
|
@ -831,36 +831,77 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
|
|||
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.Lock()
|
||||
defer c.Unlock()
|
||||
sr, ok := c.svcDb[n.ID()]
|
||||
if !ok {
|
||||
c.svcDb[n.ID()] = svcInfo{
|
||||
svcMap: make(map[string]net.IP),
|
||||
sr = svcInfo{
|
||||
svcMap: make(map[string][]net.IP),
|
||||
ipMap: make(map[string]string),
|
||||
}
|
||||
sr = c.svcDb[n.ID()]
|
||||
c.svcDb[n.ID()] = sr
|
||||
}
|
||||
|
||||
epName := ep.Name()
|
||||
n.Lock()
|
||||
if iface := ep.Iface(); iface.Address() != nil {
|
||||
|
||||
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)
|
||||
if ipMapUpdate {
|
||||
reverseIP := netutils.ReverseIP(epIP.String())
|
||||
if _, ok := sr.ipMap[reverseIP]; !ok {
|
||||
sr.ipMap[reverseIP] = name
|
||||
}
|
||||
}
|
||||
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 {
|
||||
|
@ -877,7 +918,7 @@ func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
|
|||
|
||||
recs = append(recs, etchosts.Record{
|
||||
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]
|
||||
n.Unlock()
|
||||
if ok {
|
||||
return ip
|
||||
return ip[0]
|
||||
}
|
||||
}
|
||||
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) 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() {
|
||||
local al
|
||||
local al gl
|
||||
if [ -n "$4" ]; then
|
||||
al="--alias=${4}"
|
||||
if [ "${4}" != ":" ]; then
|
||||
al="--alias=${4}"
|
||||
fi
|
||||
fi
|
||||
dnet_cmd $(inst_id2port ${1}) service publish ${2}.${3}
|
||||
dnet_cmd $(inst_id2port ${1}) service attach $al ${2} ${2}.${3}
|
||||
if [ -n "$5" ]; then
|
||||
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() {
|
||||
|
|
Loading…
Reference in a new issue