zettio/weave#362 - improve the unit tests for the TCP server by checking if we get all the responses with TCP when a previous UDP query resulted in a truncated response.
This commit is contained in:
1 parent
bf88ed8d96
commit
9c7ffd9b81
3 files changed
+96
-45
No files matched your search
+18
-22
@@ -21,34 +21,31 @@ func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
|
||||
}
|
||||
|
||||
type DNSServer struct {
|
||||
config *dns.ClientConfig
|
||||
zone Zone
|
||||
iface *net.Interface
|
||||
udpPort int
|
||||
udpSrv *dns.Server
|
||||
tcpPort int
|
||||
tcpSrv *dns.Server
|
||||
config *dns.ClientConfig
|
||||
zone Zone
|
||||
iface *net.Interface
|
||||
port int
|
||||
udpSrv *dns.Server
|
||||
tcpSrv *dns.Server
|
||||
}
|
||||
|
||||
// Creates a new DNS server with a given config
|
||||
func NewDNSServerWithConfig(config *dns.ClientConfig, zone Zone, iface *net.Interface, udpPort int, tcpPort int) (*DNSServer, error) {
|
||||
func NewDNSServerWithConfig(config *dns.ClientConfig, zone Zone, iface *net.Interface, port int) (*DNSServer, error) {
|
||||
return &DNSServer{
|
||||
config: config,
|
||||
zone: zone,
|
||||
iface: iface,
|
||||
udpPort: udpPort,
|
||||
tcpPort: tcpPort,
|
||||
config: config,
|
||||
zone: zone,
|
||||
iface: iface,
|
||||
port: port,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Creates a new DNS server
|
||||
func NewDNSServer(zone Zone, iface *net.Interface, udpPort int, tcpPort int) (*DNSServer, error) {
|
||||
func NewDNSServer(zone Zone, iface *net.Interface, port int) (*DNSServer, error) {
|
||||
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewDNSServerWithConfig(config, zone, iface, udpPort, tcpPort)
|
||||
return NewDNSServerWithConfig(config, zone, iface, port)
|
||||
}
|
||||
|
||||
// Start the DNS server
|
||||
@@ -75,19 +72,18 @@ func (s *DNSServer) Start() error {
|
||||
err = mdnsServer.Start(s.iface)
|
||||
checkFatal(err)
|
||||
|
||||
udpAddress := fmt.Sprintf(":%d", s.udpPort)
|
||||
s.udpSrv = &dns.Server{Addr: udpAddress, Net: "udp", Handler: LocalServeMux}
|
||||
tcpAddress := fmt.Sprintf(":%d", s.tcpPort)
|
||||
s.tcpSrv = &dns.Server{Addr: tcpAddress, Net: "tcp", Handler: LocalServeMux}
|
||||
address := fmt.Sprintf(":%d", s.port)
|
||||
s.udpSrv = &dns.Server{Addr: address, Net: "udp", Handler: LocalServeMux}
|
||||
s.tcpSrv = &dns.Server{Addr: address, Net: "tcp", Handler: LocalServeMux}
|
||||
|
||||
go func() {
|
||||
Info.Printf("Listening for DNS on %s (UDP)", udpAddress)
|
||||
Info.Printf("Listening for DNS on %s (UDP)", address)
|
||||
err = s.udpSrv.ListenAndServe()
|
||||
checkFatal(err)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
Info.Printf("Listening for DNS on %s (TCP)", tcpAddress)
|
||||
Info.Printf("Listening for DNS on %s (TCP)", address)
|
||||
err = s.tcpSrv.ListenAndServe()
|
||||
checkFatal(err)
|
||||
}()
|
||||
|
||||
+75
-18
@@ -3,7 +3,7 @@ package nameserver
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/zettio/weave/common"
|
||||
. "github.com/zettio/weave/common"
|
||||
wt "github.com/zettio/weave/testing"
|
||||
"net"
|
||||
"testing"
|
||||
@@ -16,7 +16,7 @@ const (
|
||||
testRDNSnonlocal = "8.8.8.8.in-addr.arpa."
|
||||
)
|
||||
|
||||
func TestDNSServer(t *testing.T) {
|
||||
func TestUDPDNSServer(t *testing.T) {
|
||||
const (
|
||||
port = 17625
|
||||
successTestName = "test1.weave.local."
|
||||
@@ -27,7 +27,7 @@ func TestDNSServer(t *testing.T) {
|
||||
dnsAddr := fmt.Sprintf("localhost:%d", port)
|
||||
testCIDR1 := testAddr1 + "/24"
|
||||
|
||||
common.InitDefaultLogging(true)
|
||||
InitDefaultLogging(true)
|
||||
var zone = new(ZoneDb)
|
||||
ip, _, _ := net.ParseCIDR(testCIDR1)
|
||||
zone.AddRecord(containerID, successTestName, ip)
|
||||
@@ -41,17 +41,14 @@ func TestDNSServer(t *testing.T) {
|
||||
wt.AssertNoErr(t, err)
|
||||
|
||||
config := &dns.ClientConfig{Servers: []string{"127.0.0.1"}, Port: fallbackPort}
|
||||
srv, err := NewDNSServerWithConfig(config, zone, nil, port, port)
|
||||
srv, err := NewDNSServerWithConfig(config, zone, nil, port)
|
||||
wt.AssertNoErr(t, err)
|
||||
defer srv.Stop()
|
||||
go srv.Start()
|
||||
time.Sleep(100 * time.Millisecond) // Allow sever goroutine to start
|
||||
|
||||
// Create a regular UDP client and a TCP client
|
||||
c := new(dns.Client)
|
||||
c.UDPSize = UDPBufSize
|
||||
tc := new(dns.Client)
|
||||
tc.Net = "tcp"
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(successTestName, dns.TypeA)
|
||||
m.RecursionDesired = true
|
||||
@@ -63,16 +60,6 @@ func TestDNSServer(t *testing.T) {
|
||||
wt.AssertType(t, r.Answer[0], (*dns.A)(nil), "DNS record")
|
||||
wt.AssertEqualString(t, r.Answer[0].(*dns.A).A.String(), testAddr1, "IP address")
|
||||
|
||||
// Retry the query with the TCP client
|
||||
tr, _, err := tc.Exchange(m, dnsAddr)
|
||||
wt.AssertNoErr(t, err)
|
||||
wt.AssertStatus(t, tr.Rcode, dns.RcodeSuccess, "DNS response code (TCP)")
|
||||
wt.AssertEqualInt(t, len(tr.Answer), 1, "Number of answers (TCP)")
|
||||
wt.AssertType(t, tr.Answer[0], (*dns.A)(nil), "DNS record (TCP)")
|
||||
wt.AssertEqualString(t, tr.Answer[0].(*dns.A).A.String(), testAddr1, "IP address (TCP)")
|
||||
// TODO: look for some way of testing the TCP fallback for truncated responses: it seems there is
|
||||
// TODO: no client lib in Go that can do that...
|
||||
|
||||
m.SetQuestion(failTestName, dns.TypeA)
|
||||
r, _, err = c.Exchange(m, dnsAddr)
|
||||
wt.AssertNoErr(t, err)
|
||||
@@ -129,6 +116,76 @@ func TestDNSServer(t *testing.T) {
|
||||
// needs two servers, each listening on its own address
|
||||
}
|
||||
|
||||
func TestTCPDNSServer(t *testing.T) {
|
||||
const (
|
||||
port = 17625
|
||||
localTestName = "test1.weave.local."
|
||||
testAddr1 = "10.0.2.1"
|
||||
)
|
||||
dnsAddr := fmt.Sprintf("localhost:%d", port)
|
||||
|
||||
InitDefaultLogging(true)
|
||||
var zone = new(ZoneDb)
|
||||
|
||||
// Insert a bunch of IPs for the same name
|
||||
ansCount := 0
|
||||
for i := 0; i < 255; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
ip := net.ParseIP(fmt.Sprintf("10.0.%d.%d", i, j))
|
||||
ansCount += 1
|
||||
err := zone.AddRecord(containerID, localTestName, ip)
|
||||
wt.AssertNoErr(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Run another DNS server for fallback
|
||||
s, fallbackAddr, err := RunLocalUDPServer("127.0.0.1:0")
|
||||
wt.AssertNoErr(t, err)
|
||||
defer s.Shutdown()
|
||||
|
||||
_, fallbackPort, err := net.SplitHostPort(fallbackAddr)
|
||||
wt.AssertNoErr(t, err)
|
||||
|
||||
config := &dns.ClientConfig{Servers: []string{"127.0.0.1"}, Port: fallbackPort}
|
||||
srv, err := NewDNSServerWithConfig(config, zone, nil, port)
|
||||
wt.AssertNoErr(t, err)
|
||||
defer srv.Stop()
|
||||
go srv.Start()
|
||||
time.Sleep(100 * time.Millisecond) // Allow sever goroutine to start
|
||||
|
||||
// Create a regular UDP client and a TCP client
|
||||
uc := new(dns.Client)
|
||||
uc.UDPSize = UDPBufSize
|
||||
tc := new(dns.Client)
|
||||
tc.Net = "tcp"
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(localTestName, dns.TypeA)
|
||||
m.RecursionDesired = false
|
||||
|
||||
Debug.Printf("Using UDP for quering about %s", localTestName)
|
||||
r, _, err := uc.Exchange(m, dnsAddr)
|
||||
wt.AssertNoErr(t, err)
|
||||
if len(r.Answer) > 1 { // TODO: remove this when we have proper support for multiple responses (zettio/weave#338)
|
||||
wt.AssertStatus(t, r.Rcode, dns.RcodeBadTrunc, "DNS response code")
|
||||
if len(r.Answer) == ansCount {
|
||||
wt.Fatalf(t, "%d answers received, but we expected less than that", len(r.Answer))
|
||||
}
|
||||
} else {
|
||||
Debug.Println("... multiple reponses not supported (yet)")
|
||||
wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS response code")
|
||||
}
|
||||
|
||||
Debug.Println("Using TCP for the same query")
|
||||
tr, _, err := tc.Exchange(m, dnsAddr)
|
||||
wt.AssertNoErr(t, err)
|
||||
wt.AssertStatus(t, tr.Rcode, dns.RcodeSuccess, "DNS response code (TCP)")
|
||||
if len(r.Answer) > 1 { // TODO: remove this when we have proper support for multiple responses (zettio/weave#338)
|
||||
wt.AssertEqualInt(t, len(tr.Answer), ansCount, "Number of answers (TCP)")
|
||||
}
|
||||
wt.AssertType(t, tr.Answer[0], (*dns.A)(nil), "DNS record (TCP)") // assume they are all the same...
|
||||
}
|
||||
|
||||
func fallbackHandler(w dns.ResponseWriter, req *dns.Msg) {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(req)
|
||||
|
||||
+3
-5
@@ -18,8 +18,7 @@ func main() {
|
||||
justVersion bool
|
||||
ifaceName string
|
||||
apiPath string
|
||||
udpPort int
|
||||
tcpPort int
|
||||
dnsPort int
|
||||
httpPort int
|
||||
wait int
|
||||
watch bool
|
||||
@@ -30,8 +29,7 @@ func main() {
|
||||
flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast")
|
||||
flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "Path to Docker API socket")
|
||||
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up")
|
||||
flag.IntVar(&udpPort, "udpport", 53, "UDP port to listen to DNS requests")
|
||||
flag.IntVar(&tcpPort, "tcpport", 53, "TCP port to listen to DNS requests")
|
||||
flag.IntVar(&dnsPort, "dnsport", 53, "port to listen to DNS requests")
|
||||
flag.IntVar(&httpPort, "httpport", 6785, "port to listen to HTTP requests")
|
||||
flag.BoolVar(&watch, "watch", true, "watch the docker socket for container events")
|
||||
flag.BoolVar(&debug, "debug", false, "output debugging info to stderr")
|
||||
@@ -66,7 +64,7 @@ func main() {
|
||||
}
|
||||
|
||||
go weavedns.ListenHttp(weavedns.LOCAL_DOMAIN, zone, httpPort)
|
||||
srv, err := weavedns.NewDNSServer(zone, iface, udpPort, tcpPort)
|
||||
srv, err := weavedns.NewDNSServer(zone, iface, dnsPort)
|
||||
if err != nil {
|
||||
Error.Fatal("Failed to start server", err)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user