فهرست منبع

Merge pull request #856 from mavenugo/localalias

Support for container local alias
Jana Radhakrishnan 9 سال پیش
والد
کامیت
b4acd1026b

+ 21 - 2
libnetwork/api/api.go

@@ -9,6 +9,7 @@ import (
 
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/types"
 	"github.com/gorilla/mux"
 )
@@ -459,6 +460,7 @@ func procDeleteNetwork(c libnetwork.NetworkController, vars map[string]string, b
 *******************/
 func procJoinEndpoint(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
 	var ej endpointJoin
+	var setFctList []libnetwork.EndpointOption
 	err := json.Unmarshal(body, &ej)
 	if err != nil {
 		return nil, &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
@@ -477,7 +479,15 @@ func procJoinEndpoint(c libnetwork.NetworkController, vars map[string]string, bo
 		return nil, errRsp
 	}
 
-	err = ep.Join(sb)
+	for _, str := range ej.Aliases {
+		name, alias, err := netutils.ParseAlias(str)
+		if err != nil {
+			return "", convertNetworkError(err)
+		}
+		setFctList = append(setFctList, libnetwork.CreateOptionAlias(name, alias))
+	}
+
+	err = ep.Join(sb, setFctList...)
 	if err != nil {
 		return nil, convertNetworkError(err)
 	}
@@ -637,6 +647,7 @@ func procUnpublishService(c libnetwork.NetworkController, vars map[string]string
 
 func procAttachBackend(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
 	var bk endpointJoin
+	var setFctList []libnetwork.EndpointOption
 	err := json.Unmarshal(body, &bk)
 	if err != nil {
 		return nil, &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
@@ -653,7 +664,15 @@ func procAttachBackend(c libnetwork.NetworkController, vars map[string]string, b
 		return nil, errRsp
 	}
 
-	err = sv.Join(sb)
+	for _, str := range bk.Aliases {
+		name, alias, err := netutils.ParseAlias(str)
+		if err != nil {
+			return "", convertNetworkError(err)
+		}
+		setFctList = append(setFctList, libnetwork.CreateOptionAlias(name, alias))
+	}
+
+	err = sv.Join(sb, setFctList...)
 	if err != nil {
 		return nil, convertNetworkError(err)
 	}

+ 2 - 1
libnetwork/api/types.go

@@ -62,7 +62,8 @@ type sandboxCreate struct {
 
 // endpointJoin represents the expected body of the "join endpoint" or "leave endpoint" http request messages
 type endpointJoin struct {
-	SandboxID string `json:"sandbox_id"`
+	SandboxID string   `json:"sandbox_id"`
+	Aliases   []string `json:"aliases"`
 }
 
 // servicePublish represents the body of the "publish service" http request message

+ 5 - 1
libnetwork/client/service.go

@@ -8,8 +8,10 @@ import (
 	"strings"
 	"text/tabwriter"
 
+	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/libnetwork/netutils"
 )
 
 var (
@@ -319,6 +321,8 @@ func (cli *NetworkCli) CmdServiceInfo(chain string, args ...string) error {
 // CmdServiceAttach handles service attach UI
 func (cli *NetworkCli) CmdServiceAttach(chain string, args ...string) error {
 	cmd := cli.Subcmd(chain, "attach", "CONTAINER SERVICE[.NETWORK]", "Sets a container as a service backend", false)
+	flAlias := opts.NewListOpts(netutils.ValidateAlias)
+	cmd.Var(&flAlias, []string{"-alias"}, "Add alias for another container")
 	cmd.Require(flag.Min, 2)
 	err := cmd.ParseFlags(args, true)
 	if err != nil {
@@ -341,7 +345,7 @@ func (cli *NetworkCli) CmdServiceAttach(chain string, args ...string) error {
 		return err
 	}
 
-	nc := serviceAttach{SandboxID: sandboxID}
+	nc := serviceAttach{SandboxID: sandboxID, Aliases: flAlias.GetAll()}
 
 	_, _, err = readBody(cli.call("POST", "/services/"+serviceID+"/backend", nc, nil))
 

+ 2 - 1
libnetwork/client/types.go

@@ -50,7 +50,8 @@ type serviceCreate struct {
 
 // serviceAttach represents the expected body of the "attach/detach sandbox to/from service" http request messages
 type serviceAttach struct {
-	SandboxID string `json:"sandbox_id"`
+	SandboxID string   `json:"sandbox_id"`
+	Aliases   []string `json:"aliases"`
 }
 
 // SandboxCreate is the body of the "post /sandboxes" http request message

+ 11 - 0
libnetwork/endpoint.go

@@ -64,6 +64,7 @@ type endpoint struct {
 	prefAddress       net.IP
 	prefAddressV6     net.IP
 	ipamOptions       map[string]string
+	aliases           map[string]string
 	dbIndex           uint64
 	dbExists          bool
 	sync.Mutex
@@ -748,6 +749,16 @@ func CreateOptionDisableResolution() EndpointOption {
 	}
 }
 
+//CreateOptionAlias function returns an option setter for setting endpoint alias
+func CreateOptionAlias(name string, alias string) EndpointOption {
+	return func(ep *endpoint) {
+		if ep.aliases == nil {
+			ep.aliases = make(map[string]string)
+		}
+		ep.aliases[alias] = name
+	}
+}
+
 // JoinOptionPriority function returns an option setter for priority option to
 // be passed to the endpoint.Join() method.
 func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {

+ 23 - 0
libnetwork/netutils/utils.go

@@ -169,3 +169,26 @@ func ReverseIP(IP string) string {
 
 	return strings.Join(reverseIP, ".")
 }
+
+// ParseAlias parses and validates the specified string as a alias format (name:alias)
+func ParseAlias(val string) (string, string, error) {
+	if val == "" {
+		return "", "", fmt.Errorf("empty string specified for alias")
+	}
+	arr := strings.Split(val, ":")
+	if len(arr) > 2 {
+		return "", "", fmt.Errorf("bad format for alias: %s", val)
+	}
+	if len(arr) == 1 {
+		return val, val, nil
+	}
+	return arr[0], arr[1], nil
+}
+
+// ValidateAlias validates that the specified string has a valid alias format (containerName:alias).
+func ValidateAlias(val string) (string, error) {
+	if _, _, err := ParseAlias(val); err != nil {
+		return val, err
+	}
+	return val, nil
+}

+ 45 - 4
libnetwork/sandbox.go

@@ -424,26 +424,67 @@ func (sb *sandbox) ResolveName(name string) net.IP {
 	parts := strings.Split(name, ".")
 	log.Debugf("To resolve %v", parts)
 
-	for _, ep := range sb.getConnectedEndpoints() {
+	reqName := parts[0]
+	networkName := ""
+	if len(parts) > 1 {
+		networkName = parts[1]
+	}
+	epList := sb.getConnectedEndpoints()
+	// First check for local container alias
+	ip = sb.resolveName(reqName, networkName, epList, true)
+	if ip != nil {
+		return ip
+	}
+
+	// Resolve the actual container name
+	return sb.resolveName(reqName, networkName, epList, false)
+}
+
+func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool) net.IP {
+	for _, ep := range epList {
+		name := req
 		n := ep.getNetwork()
 
-		if len(parts) > 1 && parts[1] != "" && parts[1] != n.Name() {
+		if networkName != "" && networkName != n.Name() {
 			continue
 		}
 
+		if alias {
+			if ep.aliases == nil {
+				continue
+			}
+
+			var ok bool
+			ep.Lock()
+			name, ok = ep.aliases[req]
+			ep.Unlock()
+			if !ok {
+				continue
+			}
+		} else {
+			// If it is a regular lookup and if the requested name is an alias
+			// dont perform a svc lookup for this endpoint.
+			ep.Lock()
+			if _, ok := ep.aliases[req]; ok {
+				ep.Unlock()
+				continue
+			}
+			ep.Unlock()
+		}
+
 		sr, ok := n.getController().svcDb[n.ID()]
 		if !ok {
 			continue
 		}
 
 		n.Lock()
-		ip, ok = sr.svcMap[parts[0]]
+		ip, ok := sr.svcMap[name]
 		n.Unlock()
 		if ok {
 			return ip
 		}
 	}
-	return ip
+	return nil
 }
 
 func (sb *sandbox) SetKey(basePath string) error {

+ 16 - 0
libnetwork/test/integration/dnet/bridge.bats

@@ -233,3 +233,19 @@ function test_single_network_connectivity() {
     done
 
 }
+
+@test "Test bridge network alias support" {
+    skip_for_circleci
+    dnet_cmd $(inst_id2port 1) network create -d bridge br1
+    dnet_cmd $(inst_id2port 1) container create container_1
+    net_connect 1 container_1 br1 container_2:c2 
+    dnet_cmd $(inst_id2port 1) container create container_2
+    net_connect 1 container_2 br1
+    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 c2"
+    net_disconnect 1 container_1 br1
+    net_disconnect 1 container_2 br1
+    dnet_cmd $(inst_id2port 1) container rm container_1
+    dnet_cmd $(inst_id2port 1) container rm container_2
+    dnet_cmd $(inst_id2port 1) network rm br1
+}

+ 5 - 1
libnetwork/test/integration/dnet/helpers.bash

@@ -18,8 +18,12 @@ function get_sbox_id() {
 }
 
 function net_connect() {
+        local al
+        if [ -n "$4" ]; then
+            al="--alias=${4}"
+        fi
 	dnet_cmd $(inst_id2port ${1}) service publish ${2}.${3}
-	dnet_cmd $(inst_id2port ${1}) service attach ${2} ${2}.${3}
+	dnet_cmd $(inst_id2port ${1}) service attach $al ${2} ${2}.${3}
 }
 
 function net_disconnect() {