From 4850c5f1e68456dc360fd6837f67f7ea332f8335 Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Fri, 23 Oct 2015 10:09:00 -0700 Subject: [PATCH] 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 --- libnetwork/endpoint.go | 30 +++++++++++++++--------------- libnetwork/network.go | 29 ++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index b9933953a5..e40b85cbcd 100644 --- a/libnetwork/endpoint.go +++ b/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,17 +498,6 @@ func (ep *endpoint) Delete() error { } ep.Unlock() - if err = n.getEpCnt().DecEndpointCnt(); 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) - } - } - }() - if err = n.getController().deleteFromStore(ep); err != nil { return err } @@ -524,6 +510,20 @@ func (ep *endpoint) Delete() error { } }() + if err = n.getEpCnt().DecEndpointCnt(); 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) + } + } + }() + + // unwatch for service records + n.getController().unWatchSvcRecord(ep) + if err = ep.deleteEndpoint(); err != nil { return err } diff --git a/libnetwork/network.go b/libnetwork/network.go index 69b0e755a7..2584602849 100644 --- a/libnetwork/network.go +++ b/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(),