Merge pull request #856 from mavenugo/localalias

Support for container local alias
This commit is contained in:
Jana Radhakrishnan 2016-01-07 17:50:31 -08:00
commit b4acd1026b
9 changed files with 130 additions and 10 deletions

View file

@ -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)
}

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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 {

View file

@ -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
}

View file

@ -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 {

View file

@ -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
}

View file

@ -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() {