diff --git a/nameserver/dns.go b/nameserver/dns.go index 9db9de20..461cdfed 100644 --- a/nameserver/dns.go +++ b/nameserver/dns.go @@ -216,7 +216,7 @@ func (h *handler) handleRecursive(w dns.ResponseWriter, req *dns.Msg) { reqCopy := req.Copy() reqCopy.Id = dns.Id() response, _, err := h.client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, h.upstream.Port)) - if err != nil || response == nil { + if (err != nil && err != dns.ErrTruncated) || response == nil { h.ns.debugf("error trying %s: %v", server, err) continue } diff --git a/nameserver/dns_test.go b/nameserver/dns_test.go index 74187f27..a1fad802 100644 --- a/nameserver/dns_test.go +++ b/nameserver/dns_test.go @@ -42,17 +42,17 @@ func TestTruncation(t *testing.T) { nameserver.AddEntry("foo.weave.local.", "", router.UnknownPeerName, i) } - doRequest := func(client *dns.Client, request *dns.Msg, port int) *dns.Msg { + doRequest := func(client *dns.Client, request *dns.Msg, port int, expectedErr error) *dns.Msg { request.SetQuestion("foo.weave.local.", dns.TypeA) response, _, err := client.Exchange(request, fmt.Sprintf("127.0.0.1:%d", port)) - require.Nil(t, err) + require.Equal(t, expectedErr, err) return response } // do a udp query, ensure we get a truncated response { udpClient := dns.Client{Net: "udp", UDPSize: minUDPSize} - response := doRequest(&udpClient, &dns.Msg{}, udpPort) + response := doRequest(&udpClient, &dns.Msg{}, udpPort, dns.ErrTruncated) require.True(t, response.MsgHdr.Truncated) require.True(t, len(response.Answer) < 100) } @@ -62,7 +62,7 @@ func TestTruncation(t *testing.T) { udpClient := dns.Client{Net: "udp", UDPSize: 65535} request := &dns.Msg{} request.SetEdns0(65535, false) - response := doRequest(&udpClient, request, udpPort) + response := doRequest(&udpClient, request, udpPort, nil) require.False(t, response.MsgHdr.Truncated) require.Equal(t, len(response.Answer), 100) } @@ -70,7 +70,7 @@ func TestTruncation(t *testing.T) { // do a tcp query, ensure we don't get a truncated response { tcpClient := dns.Client{Net: "tcp"} - response := doRequest(&tcpClient, &dns.Msg{}, tcpPort) + response := doRequest(&tcpClient, &dns.Msg{}, tcpPort, nil) require.False(t, response.MsgHdr.Truncated) require.Equal(t, len(response.Answer), 100) } diff --git a/proxy/inspect_container_interceptor.go b/proxy/inspect_container_interceptor.go index 7916ea9a..590649d4 100644 --- a/proxy/inspect_container_interceptor.go +++ b/proxy/inspect_container_interceptor.go @@ -22,30 +22,9 @@ func (i *inspectContainerInterceptor) InterceptResponse(r *http.Response) error return err } - if err := updateContainerNetworkSettings(container); err != nil { + if err := i.proxy.updateContainerNetworkSettings(container); err != nil { Log.Warningf("Inspecting container %s failed: %s", container["Id"], err) } return marshalResponseBody(r, container) } - -func updateContainerNetworkSettings(container jsonObject) error { - containerID, err := container.String("Id") - if err != nil { - return err - } - - mac, ips, nets, err := weaveContainerIPs(containerID) - if err != nil || len(ips) == 0 { - return err - } - - networkSettings, err := container.Object("NetworkSettings") - if err != nil { - return err - } - networkSettings["MacAddress"] = mac - networkSettings["IPAddress"] = ips[0].String() - networkSettings["IPPrefixLen"], _ = nets[0].Mask.Size() - return nil -} diff --git a/proxy/inspect_exec_interceptor.go b/proxy/inspect_exec_interceptor.go index 970c3142..32e70940 100644 --- a/proxy/inspect_exec_interceptor.go +++ b/proxy/inspect_exec_interceptor.go @@ -27,7 +27,7 @@ func (i *inspectExecInterceptor) InterceptResponse(r *http.Response) error { return err } - if err := updateContainerNetworkSettings(container); err != nil { + if err := i.proxy.updateContainerNetworkSettings(container); err != nil { Log.Warningf("Inspecting exec %s failed: %s", exec["Id"], err) } diff --git a/proxy/proxy.go b/proxy/proxy.go index f087d769..e90c7f57 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -358,6 +358,24 @@ func (proxy *Proxy) waitForStart(r *http.Request) error { return nil } +// If some other operation is waiting for a container to start, join in the wait +func (proxy *Proxy) waitForStartByIdent(ident string) error { + var ch chan error + proxy.Lock() + for _, wait := range proxy.waiters { + if ident == wait.ident && !wait.done { + ch = wait.ch + break + } + } + proxy.Unlock() + if ch != nil { + Log.Debugf("Wait for start of container %s", ident) + return <-ch + } + return nil +} + func (proxy *Proxy) ContainerDied(ident string) { } @@ -495,3 +513,27 @@ func (proxy *Proxy) getDNSDomain() (domain string) { return string(b) } + +func (proxy *Proxy) updateContainerNetworkSettings(container jsonObject) error { + containerID, err := container.String("Id") + if err != nil { + return err + } + + if err := proxy.waitForStartByIdent(containerID); err != nil { + return err + } + mac, ips, nets, err := weaveContainerIPs(containerID) + if err != nil || len(ips) == 0 { + return err + } + + networkSettings, err := container.Object("NetworkSettings") + if err != nil { + return err + } + networkSettings["MacAddress"] = mac + networkSettings["IPAddress"] = ips[0].String() + networkSettings["IPPrefixLen"], _ = nets[0].Mask.Size() + return nil +}