Corrects two issues with DNS prepared query failover

When DNS prepared query fails over to another datacenter and the datacenter
returns some nodes, the DNS result does not translate WAN addresses even when
translation is enabled for SRV and A queries, and returns the wrong datacenter
(the one that failed over) for SRV queries.
This commit is contained in:
Max Timchenko 2016-07-27 18:11:42 -04:00 committed by James Phillips
parent b6c1543da8
commit 3b08db47dc
No known key found for this signature in database
GPG Key ID: 77183E682AC5FC11
2 changed files with 126 additions and 3 deletions

View File

@ -744,10 +744,10 @@ RPC:
// Add various responses depending on the request.
qType := req.Question[0].Qtype
if qType == dns.TypeSRV {
d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl)
if qType == dns.TypeSRV {
d.serviceSRVRecords(out.Datacenter, out.Nodes, req, resp, ttl)
} else {
d.serviceNodeRecords(datacenter, out.Nodes, req, resp, ttl)
d.serviceNodeRecords(out.Datacenter, out.Nodes, req, resp, ttl)
}
// If the network is not TCP, restrict the number of responses.

View File

@ -2737,6 +2737,129 @@ func TestDNS_PreparedQuery_TTL(t *testing.T) {
}
}
func TestDNS_PreparedQuery_Failover(t *testing.T) {
dir1, srv1 := makeDNSServerConfig(t, func(c *Config) {
c.Datacenter = "dc1"
c.TranslateWanAddrs = true
}, nil)
defer os.RemoveAll(dir1)
defer srv1.Shutdown()
dir2, srv2 := makeDNSServerConfig(t, func(c *Config) {
c.Datacenter = "dc2"
c.TranslateWanAddrs = true
}, nil)
defer os.RemoveAll(dir2)
defer srv2.Shutdown()
testutil.WaitForLeader(t, srv1.agent.RPC, "dc1")
testutil.WaitForLeader(t, srv2.agent.RPC, "dc2")
// Join WAN cluster
addr := fmt.Sprintf("127.0.0.1:%d",
srv1.agent.config.Ports.SerfWan)
if _, err := srv2.agent.JoinWAN([]string{addr}); err != nil {
t.Fatalf("err: %v", err)
}
testutil.WaitForResult(
func() (bool, error) {
return len(srv1.agent.WANMembers()) > 1, nil
},
func(err error) {
t.Fatalf("Failed waiting for WAN join: %v", err)
})
// Register a remote node with a service.
{
args := &structs.RegisterRequest{
Datacenter: "dc2",
Node: "foo",
Address: "127.0.0.1",
TaggedAddresses: map[string]string{
"wan": "127.0.0.2",
},
Service: &structs.NodeService{
Service: "db",
},
}
var out struct{}
if err := srv2.agent.RPC("Catalog.Register", args, &out); err != nil {
t.Fatalf("err: %v", err)
}
}
// Register an equivalent prepared query in both DCs.
var id_dc1 string
{
args := &structs.PreparedQueryRequest{
Datacenter: "dc1",
Op: structs.PreparedQueryCreate,
Query: &structs.PreparedQuery{
Name: "my-query",
Service: structs.ServiceQuery{
Service: "db",
Failover: structs.QueryDatacenterOptions{
NearestN: 1,
Datacenters: []string{"dc2"},
},
},
},
}
if err := srv1.agent.RPC("PreparedQuery.Apply", args, &id_dc1); err != nil {
t.Fatalf("err: %v", err)
}
}
var id_dc2 string
{
args := &structs.PreparedQueryRequest{
Datacenter: "dc2",
Op: structs.PreparedQueryCreate,
Query: &structs.PreparedQuery{
Name: "my-query",
Service: structs.ServiceQuery{
Service: "db",
Failover: structs.QueryDatacenterOptions{
NearestN: 1,
Datacenters: []string{"dc1"},
},
},
},
}
if err := srv2.agent.RPC("PreparedQuery.Apply", args, &id_dc2); err != nil {
t.Fatalf("err: %v", err)
}
}
// Look up the SRV record via the query
m := new(dns.Msg)
m.SetQuestion("my-query.query.consul.", dns.TypeSRV)
c := new(dns.Client)
cl_addr, _ := srv1.agent.config.ClientListener("", srv1.agent.config.Ports.DNS)
in, _, err := c.Exchange(m, cl_addr.String())
if err != nil {
t.Fatalf("err: %v", err)
}
if len(in.Answer) != 1 {
t.Fatalf("Bad: %#v", in)
}
aRec, ok := in.Extra[0].(*dns.A)
if !ok {
t.Fatalf("Bad: %#v", in.Extra[0])
}
if aRec.Hdr.Name != "foo.node.dc2.consul." {
t.Fatalf("Bad: %#v", in.Extra[0])
}
if aRec.A.String() != "127.0.0.2" {
t.Fatalf("Bad: %#v", in.Extra[0])
}
}
func TestDNS_ServiceLookup_SRV_RFC(t *testing.T) {
dir, srv := makeDNSServer(t)
defer os.RemoveAll(dir)