From 84abbcefa89a2ef7050539fed5ddeb0f006e8721 Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Wed, 25 Nov 2015 15:25:56 -0800 Subject: [PATCH] Fix a couple of edge cases in service discovery The first issue is an ordering problem where sandbox attached version of endpoint object should be pushed to the watch database first so that any other create endpoint which is in progress can make use of it immediately to update the container hosts file. And only after that the current container should try to retrieve the service records from the service data base and upate it's hosts file. With the previous order there is a small time window, when another endpoint create will find this endpoint but it doesn't have the sandbox context while the svc record population from svc db has already happened so that container will totally miss to populate the service record of the newly created endpoint. The second issue is trying to rebuild the /etc/hosts file from scratch during endpoint join and this may sometimes happen after the service record add for another endpoint has happened on the container file. Obviously this rebuilding will wipe out that service record which was just added. Removed the rebuilding of /etc/hosts file during endpoint join. The initial population of /etc/hosts file should only happen during sandbox creation time. In the endpoint join just added the backward-compatible self ip -> hostname entry as just another record. Signed-off-by: Jana Radhakrishnan --- libnetwork/endpoint.go | 6 +++--- libnetwork/sandbox.go | 37 ++++++++----------------------------- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 865f2aab70..4e475b3093 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -386,6 +386,9 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error { } }() + // Watch for service records + network.getController().watchSvcRecord(ep) + address := "" if ip := ep.getFirstInterfaceAddress(); ip != nil { address = ip.String() @@ -394,9 +397,6 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error { return err } - // Watch for service records - network.getController().watchSvcRecord(ep) - if err = sb.updateDNS(network.enableIPv6); err != nil { return err } diff --git a/libnetwork/sandbox.go b/libnetwork/sandbox.go index b29c67fdbe..d24c43a460 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -62,7 +62,6 @@ type sandbox struct { osSbox osl.Sandbox controller *controller refCnt int - hostsOnce sync.Once endpoints epHeap epPriority map[string]int joinLeaveDone chan struct{} @@ -601,41 +600,21 @@ func (sb *sandbox) buildHostsFile() error { } func (sb *sandbox) updateHostsFile(ifaceIP string, svcRecords []etchosts.Record) error { - var err error + var mhost string if sb.config.originHostsPath != "" { return nil } - max := func(a, b int) int { - if a < b { - return b - } - - return a + if sb.config.domainName != "" { + mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName, + sb.config.hostName) + } else { + mhost = sb.config.hostName } - extraContent := make([]etchosts.Record, 0, - max(len(sb.config.extraHosts), len(svcRecords))) - - sb.hostsOnce.Do(func() { - // Rebuild the hosts file accounting for the passed - // interface IP and service records - - for _, extraHost := range sb.config.extraHosts { - extraContent = append(extraContent, - etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP}) - } - - err = etchosts.Build(sb.config.hostsPath, ifaceIP, - sb.config.hostName, sb.config.domainName, extraContent) - }) - - if err != nil { - return err - } - - extraContent = extraContent[:0] + extraContent := make([]etchosts.Record, 0, len(svcRecords)+1) + extraContent = append(extraContent, etchosts.Record{Hosts: mhost, IP: ifaceIP}) for _, svc := range svcRecords { extraContent = append(extraContent, svc) }