Browse Source

Avoid duplicate entries in /etc/hosts

Currently the local containers of a global scope
network will get it's service records updated
from both a local update and global update. There
is no way to check if this is a local endpoint when
a remote update comes in via watch because we add
the endpoint to local endpoint list during join, while
the remote update happens during createendpoint.

The right thing to do is update the local endpoint list
and start watching during createndpoint and remove the watch
during delete endpoint. But this might result in the container
getting it's own record in it's /etc/hosts. So added a filtering
logic to filter out self records when updating the container's
/etc/hosts

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 9 years ago
parent
commit
4850c5f1e6
2 changed files with 37 additions and 14 deletions
  1. 11 11
      libnetwork/endpoint.go
  2. 26 3
      libnetwork/network.go

+ 11 - 11
libnetwork/endpoint.go

@@ -345,7 +345,7 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
 	if ip := ep.getFirstInterfaceAddress(); ip != nil {
 		address = ip.String()
 	}
-	if err = sb.updateHostsFile(address, network.getSvcRecords()); err != nil {
+	if err = sb.updateHostsFile(address, network.getSvcRecords(ep)); err != nil {
 		return err
 	}
 
@@ -467,9 +467,6 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
 		return err
 	}
 
-	// unwatch for service records
-	n.getController().unWatchSvcRecord(ep)
-
 	if sb.needDefaultGW() {
 		ep := sb.getEPwithoutGateway()
 		if ep == nil {
@@ -501,29 +498,32 @@ func (ep *endpoint) Delete() error {
 	}
 	ep.Unlock()
 
-	if err = n.getEpCnt().DecEndpointCnt(); err != nil {
+	if err = n.getController().deleteFromStore(ep); err != nil {
 		return err
 	}
 	defer func() {
 		if err != nil {
-			if e := n.getEpCnt().IncEndpointCnt(); e != nil {
-				log.Warnf("failed to update network %s : %v", n.name, e)
+			ep.dbExists = false
+			if e := n.getController().updateToStore(ep); e != nil {
+				log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
 			}
 		}
 	}()
 
-	if err = n.getController().deleteFromStore(ep); err != nil {
+	if err = n.getEpCnt().DecEndpointCnt(); err != nil {
 		return err
 	}
 	defer func() {
 		if err != nil {
-			ep.dbExists = false
-			if e := n.getController().updateToStore(ep); e != nil {
-				log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
+			if e := n.getEpCnt().IncEndpointCnt(); e != nil {
+				log.Warnf("failed to update network %s : %v", n.name, e)
 			}
 		}
 	}()
 
+	// unwatch for service records
+	n.getController().unWatchSvcRecord(ep)
+
 	if err = ep.deleteEndpoint(); err != nil {
 		return err
 	}

+ 26 - 3
libnetwork/network.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"net"
 	"strconv"
+	"strings"
 	"sync"
 
 	log "github.com/Sirupsen/logrus"
@@ -685,6 +686,14 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
 		}
 	}()
 
+	// Watch for service records
+	n.getController().watchSvcRecord(ep)
+	defer func() {
+		if err != nil {
+			n.getController().unWatchSvcRecord(ep)
+		}
+	}()
+
 	// Increment endpoint count to indicate completion of endpoint addition
 	if err = n.getEpCnt().IncEndpointCnt(); err != nil {
 		return nil, err
@@ -768,6 +777,12 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
 	var recs []etchosts.Record
 	if iface := ep.Iface(); iface.Address() != nil {
 		if isAdd {
+			// If we already have this endpoint in service db just return
+			if _, ok := sr[ep.Name()]; ok {
+				n.Unlock()
+				return
+			}
+
 			sr[ep.Name()] = iface.Address().IP
 			sr[ep.Name()+"."+n.name] = iface.Address().IP
 		} else {
@@ -793,8 +808,12 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
 	}
 
 	var sbList []*sandbox
-	for _, ep := range localEps {
-		if sb, hasSandbox := ep.getSandbox(); hasSandbox {
+	for _, lEp := range localEps {
+		if ep.ID() == lEp.ID() {
+			continue
+		}
+
+		if sb, hasSandbox := lEp.getSandbox(); hasSandbox {
 			sbList = append(sbList, sb)
 		}
 	}
@@ -808,7 +827,7 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
 	}
 }
 
-func (n *network) getSvcRecords() []etchosts.Record {
+func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
 	n.Lock()
 	defer n.Unlock()
 
@@ -816,6 +835,10 @@ func (n *network) getSvcRecords() []etchosts.Record {
 	sr, _ := n.ctrlr.svcDb[n.id]
 
 	for h, ip := range sr {
+		if ep != nil && strings.Split(h, ".")[0] == ep.Name() {
+			continue
+		}
+
 		recs = append(recs, etchosts.Record{
 			Hosts: h,
 			IP:    ip.String(),