agent: Support stale queries with retries

This commit is contained in:
Armon Dadgar 2014-06-08 15:49:24 -07:00
parent 248ce2d301
commit 3b3d235880
3 changed files with 32 additions and 11 deletions

View File

@ -227,8 +227,8 @@ func (c *Command) setupAgent(config *Config, logOutput io.Writer, logWriter *log
return err return err
} }
server, err := NewDNSServer(agent, logOutput, config.Domain, server, err := NewDNSServer(agent, &config.DNSConfig, logOutput,
dnsAddr.String(), config.DNSRecursor) config.Domain, dnsAddr.String(), config.DNSRecursor)
if err != nil { if err != nil {
agent.Shutdown() agent.Shutdown()
c.Ui.Error(fmt.Sprintf("Error starting dns server: %s", err)) c.Ui.Error(fmt.Sprintf("Error starting dns server: %s", err))

View File

@ -23,6 +23,7 @@ const (
// service discovery endpoints using a DNS interface. // service discovery endpoints using a DNS interface.
type DNSServer struct { type DNSServer struct {
agent *Agent agent *Agent
config *DNSConfig
dnsHandler *dns.ServeMux dnsHandler *dns.ServeMux
dnsServer *dns.Server dnsServer *dns.Server
dnsServerTCP *dns.Server dnsServerTCP *dns.Server
@ -32,7 +33,7 @@ type DNSServer struct {
} }
// NewDNSServer starts a new DNS server to provide an agent interface // NewDNSServer starts a new DNS server to provide an agent interface
func NewDNSServer(agent *Agent, logOutput io.Writer, domain, bind, recursor string) (*DNSServer, error) { func NewDNSServer(agent *Agent, config *DNSConfig, logOutput io.Writer, domain, bind, recursor string) (*DNSServer, error) {
// Make sure domain is FQDN // Make sure domain is FQDN
domain = dns.Fqdn(domain) domain = dns.Fqdn(domain)
@ -55,6 +56,7 @@ func NewDNSServer(agent *Agent, logOutput io.Writer, domain, bind, recursor stri
// Create the server // Create the server
srv := &DNSServer{ srv := &DNSServer{
agent: agent, agent: agent,
config: config,
dnsHandler: mux, dnsHandler: mux,
dnsServer: server, dnsServer: server,
dnsServerTCP: serverTCP, dnsServerTCP: serverTCP,
@ -308,14 +310,23 @@ func (d *DNSServer) nodeLookup(network, datacenter, node string, req, resp *dns.
args := structs.NodeSpecificRequest{ args := structs.NodeSpecificRequest{
Datacenter: datacenter, Datacenter: datacenter,
Node: node, Node: node,
QueryOptions: structs.QueryOptions{AllowStale: d.config.AllowStale},
} }
var out structs.IndexedNodeServices var out structs.IndexedNodeServices
RPC:
if err := d.agent.RPC("Catalog.NodeServices", &args, &out); err != nil { if err := d.agent.RPC("Catalog.NodeServices", &args, &out); err != nil {
d.logger.Printf("[ERR] dns: rpc error: %v", err) d.logger.Printf("[ERR] dns: rpc error: %v", err)
resp.SetRcode(req, dns.RcodeServerFailure) resp.SetRcode(req, dns.RcodeServerFailure)
return return
} }
// Verify that request is not too stale, redo the request
if args.AllowStale && out.LastContact > d.config.MaxStale {
args.AllowStale = false
d.logger.Printf("[WARN] dns: Query results too stale, re-requesting")
goto RPC
}
// If we have no address, return not found! // If we have no address, return not found!
if out.NodeServices == nil { if out.NodeServices == nil {
resp.SetRcode(req, dns.RcodeNameError) resp.SetRcode(req, dns.RcodeNameError)
@ -402,14 +413,23 @@ func (d *DNSServer) serviceLookup(network, datacenter, service, tag string, req,
ServiceName: service, ServiceName: service,
ServiceTag: tag, ServiceTag: tag,
TagFilter: tag != "", TagFilter: tag != "",
QueryOptions: structs.QueryOptions{AllowStale: d.config.AllowStale},
} }
var out structs.IndexedCheckServiceNodes var out structs.IndexedCheckServiceNodes
RPC:
if err := d.agent.RPC("Health.ServiceNodes", &args, &out); err != nil { if err := d.agent.RPC("Health.ServiceNodes", &args, &out); err != nil {
d.logger.Printf("[ERR] dns: rpc error: %v", err) d.logger.Printf("[ERR] dns: rpc error: %v", err)
resp.SetRcode(req, dns.RcodeServerFailure) resp.SetRcode(req, dns.RcodeServerFailure)
return return
} }
// Verify that request is not too stale, redo the request
if args.AllowStale && out.LastContact > d.config.MaxStale {
args.AllowStale = false
d.logger.Printf("[WARN] dns: Query results too stale, re-requesting")
goto RPC
}
// If we have no nodes, return not found! // If we have no nodes, return not found!
if len(out.Nodes) == 0 { if len(out.Nodes) == 0 {
resp.SetRcode(req, dns.RcodeNameError) resp.SetRcode(req, dns.RcodeNameError)

View File

@ -14,8 +14,9 @@ func makeDNSServer(t *testing.T) (string, *DNSServer) {
conf := nextConfig() conf := nextConfig()
addr, _ := conf.ClientListener(conf.Ports.DNS) addr, _ := conf.ClientListener(conf.Ports.DNS)
dir, agent := makeAgent(t, conf) dir, agent := makeAgent(t, conf)
server, err := NewDNSServer(agent, agent.logOutput, conf.Domain, config := &DNSConfig{}
addr.String(), "8.8.8.8:53") server, err := NewDNSServer(agent, config, agent.logOutput,
conf.Domain, addr.String(), "8.8.8.8:53")
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }