Remove debug queries (#1058)
* Remove debug from interface and methods * remove debug queries from etcd * remove debug queries from k8s - they were not used * And remove from mw/proxy-google as well * Remove debug query test
This commit is contained in:
parent
c2105a4f41
commit
3e252deabb
17 changed files with 99 additions and 462 deletions
|
@ -11,27 +11,22 @@ import (
|
||||||
type ServiceBackend interface {
|
type ServiceBackend interface {
|
||||||
// Services communicates with the backend to retrieve the service definition. Exact indicates
|
// Services communicates with the backend to retrieve the service definition. Exact indicates
|
||||||
// on exact much are that we are allowed to recurs.
|
// on exact much are that we are allowed to recurs.
|
||||||
Services(state request.Request, exact bool, opt Options) ([]msg.Service, []msg.Service, error)
|
Services(state request.Request, exact bool, opt Options) ([]msg.Service, error)
|
||||||
|
|
||||||
// Reverse communicates with the backend to retrieve service definition based on a IP address
|
// Reverse communicates with the backend to retrieve service definition based on a IP address
|
||||||
// instead of a name. I.e. a reverse DNS lookup.
|
// instead of a name. I.e. a reverse DNS lookup.
|
||||||
Reverse(state request.Request, exact bool, opt Options) ([]msg.Service, []msg.Service, error)
|
Reverse(state request.Request, exact bool, opt Options) ([]msg.Service, error)
|
||||||
|
|
||||||
// Lookup is used to find records else where.
|
// Lookup is used to find records else where.
|
||||||
Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error)
|
Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error)
|
||||||
|
|
||||||
// IsNameError return true if err indicated a record not found condition
|
|
||||||
IsNameError(err error) bool
|
|
||||||
|
|
||||||
// Debug returns a string used when returning debug services.
|
|
||||||
Debug() string
|
|
||||||
|
|
||||||
// Returns _all_ services that matches a certain name.
|
// Returns _all_ services that matches a certain name.
|
||||||
// Note: it does not implement a specific service.
|
// Note: it does not implement a specific service.
|
||||||
Records(state request.Request, exact bool) ([]msg.Service, error)
|
Records(state request.Request, exact bool) ([]msg.Service, error)
|
||||||
|
|
||||||
|
// IsNameError return true if err indicated a record not found condition
|
||||||
|
IsNameError(err error) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options are extra options that can be specified for a lookup.
|
// Options are extra options that can be specified for a lookup.
|
||||||
type Options struct {
|
type Options struct{}
|
||||||
Debug string // This is a debug query. A query prefixed with debug.o-o
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,10 +14,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// A returns A records from Backend or an error.
|
// A returns A records from Backend or an error.
|
||||||
func A(b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, debug []msg.Service, err error) {
|
func A(b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) {
|
||||||
services, debug, err := b.Services(state, false, opt)
|
services, err := b.Services(state, false, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, debug, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, serv := range services {
|
for _, serv := range services {
|
||||||
|
@ -41,14 +41,13 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d
|
||||||
}
|
}
|
||||||
|
|
||||||
state1 := state.NewWithQuestion(serv.Host, state.QType())
|
state1 := state.NewWithQuestion(serv.Host, state.QType())
|
||||||
nextRecords, nextDebug, err := A(b, zone, state1, append(previousRecords, newRecord), opt)
|
nextRecords, err := A(b, zone, state1, append(previousRecords, newRecord), opt)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Not only have we found something we should add the CNAME and the IP addresses.
|
// Not only have we found something we should add the CNAME and the IP addresses.
|
||||||
if len(nextRecords) > 0 {
|
if len(nextRecords) > 0 {
|
||||||
records = append(records, newRecord)
|
records = append(records, newRecord)
|
||||||
records = append(records, nextRecords...)
|
records = append(records, nextRecords...)
|
||||||
debug = append(debug, nextDebug...)
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -61,8 +60,6 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d
|
||||||
// Lookup
|
// Lookup
|
||||||
m1, e1 := b.Lookup(state, target, state.QType())
|
m1, e1 := b.Lookup(state, target, state.QType())
|
||||||
if e1 != nil {
|
if e1 != nil {
|
||||||
debugMsg := msg.Service{Key: msg.Path(target, b.Debug()), Host: target, Text: " IN " + state.Type() + ": " + e1.Error()}
|
|
||||||
debug = append(debug, debugMsg)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Len(m1.Answer) > 0 here is well?
|
// Len(m1.Answer) > 0 here is well?
|
||||||
|
@ -77,14 +74,14 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d
|
||||||
// nodata?
|
// nodata?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, debug, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AAAA returns AAAA records from Backend or an error.
|
// AAAA returns AAAA records from Backend or an error.
|
||||||
func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, debug []msg.Service, err error) {
|
func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) {
|
||||||
services, debug, err := b.Services(state, false, opt)
|
services, err := b.Services(state, false, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, debug, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, serv := range services {
|
for _, serv := range services {
|
||||||
|
@ -109,14 +106,13 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords
|
||||||
}
|
}
|
||||||
|
|
||||||
state1 := state.NewWithQuestion(serv.Host, state.QType())
|
state1 := state.NewWithQuestion(serv.Host, state.QType())
|
||||||
nextRecords, nextDebug, err := AAAA(b, zone, state1, append(previousRecords, newRecord), opt)
|
nextRecords, err := AAAA(b, zone, state1, append(previousRecords, newRecord), opt)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Not only have we found something we should add the CNAME and the IP addresses.
|
// Not only have we found something we should add the CNAME and the IP addresses.
|
||||||
if len(nextRecords) > 0 {
|
if len(nextRecords) > 0 {
|
||||||
records = append(records, newRecord)
|
records = append(records, newRecord)
|
||||||
records = append(records, nextRecords...)
|
records = append(records, nextRecords...)
|
||||||
debug = append(debug, nextDebug...)
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -128,8 +124,6 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords
|
||||||
}
|
}
|
||||||
m1, e1 := b.Lookup(state, target, state.QType())
|
m1, e1 := b.Lookup(state, target, state.QType())
|
||||||
if e1 != nil {
|
if e1 != nil {
|
||||||
debugMsg := msg.Service{Key: msg.Path(target, b.Debug()), Host: target, Text: " IN " + state.Type() + ": " + e1.Error()}
|
|
||||||
debug = append(debug, debugMsg)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Len(m1.Answer) > 0 here is well?
|
// Len(m1.Answer) > 0 here is well?
|
||||||
|
@ -145,15 +139,15 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords
|
||||||
records = append(records, serv.NewAAAA(state.QName(), ip))
|
records = append(records, serv.NewAAAA(state.QName(), ip))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, debug, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRV returns SRV records from the Backend.
|
// SRV returns SRV records from the Backend.
|
||||||
// If the Target is not a name but an IP address, a name is created on the fly.
|
// If the Target is not a name but an IP address, a name is created on the fly.
|
||||||
func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, debug []msg.Service, err error) {
|
func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) {
|
||||||
services, debug, err := b.Services(state, false, opt)
|
services, err := b.Services(state, false, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Looping twice to get the right weight vs priority
|
// Looping twice to get the right weight vs priority
|
||||||
|
@ -196,9 +190,6 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec
|
||||||
m1, e1 := b.Lookup(state, srv.Target, dns.TypeA)
|
m1, e1 := b.Lookup(state, srv.Target, dns.TypeA)
|
||||||
if e1 == nil {
|
if e1 == nil {
|
||||||
extra = append(extra, m1.Answer...)
|
extra = append(extra, m1.Answer...)
|
||||||
} else {
|
|
||||||
debugMsg := msg.Service{Key: msg.Path(srv.Target, b.Debug()), Host: srv.Target, Text: " IN A: " + e1.Error()}
|
|
||||||
debug = append(debug, debugMsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m1, e1 = b.Lookup(state, srv.Target, dns.TypeAAAA)
|
m1, e1 = b.Lookup(state, srv.Target, dns.TypeAAAA)
|
||||||
|
@ -209,19 +200,15 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec
|
||||||
extra = append(extra, a)
|
extra = append(extra, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
debugMsg := msg.Service{Key: msg.Path(srv.Target, b.Debug()), Host: srv.Target, Text: " IN AAAA: " + e1.Error()}
|
|
||||||
debug = append(debug, debugMsg)
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Internal name, we should have some info on them, either v4 or v6
|
// Internal name, we should have some info on them, either v4 or v6
|
||||||
// Clients expect a complete answer, because we are a recursor in their view.
|
// Clients expect a complete answer, because we are a recursor in their view.
|
||||||
state1 := state.NewWithQuestion(srv.Target, dns.TypeA)
|
state1 := state.NewWithQuestion(srv.Target, dns.TypeA)
|
||||||
addr, debugAddr, e1 := A(b, zone, state1, nil, opt)
|
addr, e1 := A(b, zone, state1, nil, opt)
|
||||||
if e1 == nil {
|
if e1 == nil {
|
||||||
extra = append(extra, addr...)
|
extra = append(extra, addr...)
|
||||||
debug = append(debug, debugAddr...)
|
|
||||||
}
|
}
|
||||||
// IPv6 lookups here as well? AAAA(zone, state1, nil).
|
// IPv6 lookups here as well? AAAA(zone, state1, nil).
|
||||||
|
|
||||||
|
@ -233,14 +220,14 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec
|
||||||
extra = append(extra, newAddress(serv, srv.Target, ip, what))
|
extra = append(extra, newAddress(serv, srv.Target, ip, what))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, extra, debug, nil
|
return records, extra, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MX returns MX records from the Backend. If the Target is not a name but an IP address, a name is created on the fly.
|
// MX returns MX records from the Backend. If the Target is not a name but an IP address, a name is created on the fly.
|
||||||
func MX(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, debug []msg.Service, err error) {
|
func MX(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) {
|
||||||
services, debug, err := b.Services(state, false, opt)
|
services, err := b.Services(state, false, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, debug, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup := make(map[string]bool)
|
lookup := make(map[string]bool)
|
||||||
|
@ -263,10 +250,8 @@ func MX(b ServiceBackend, zone string, state request.Request, opt Options) (reco
|
||||||
m1, e1 := b.Lookup(state, mx.Mx, dns.TypeA)
|
m1, e1 := b.Lookup(state, mx.Mx, dns.TypeA)
|
||||||
if e1 == nil {
|
if e1 == nil {
|
||||||
extra = append(extra, m1.Answer...)
|
extra = append(extra, m1.Answer...)
|
||||||
} else {
|
|
||||||
debugMsg := msg.Service{Key: msg.Path(mx.Mx, b.Debug()), Host: mx.Mx, Text: " IN A: " + e1.Error()}
|
|
||||||
debug = append(debug, debugMsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m1, e1 = b.Lookup(state, mx.Mx, dns.TypeAAAA)
|
m1, e1 = b.Lookup(state, mx.Mx, dns.TypeAAAA)
|
||||||
if e1 == nil {
|
if e1 == nil {
|
||||||
// If we have seen CNAME's we *assume* that they are already added.
|
// If we have seen CNAME's we *assume* that they are already added.
|
||||||
|
@ -275,18 +260,14 @@ func MX(b ServiceBackend, zone string, state request.Request, opt Options) (reco
|
||||||
extra = append(extra, a)
|
extra = append(extra, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
debugMsg := msg.Service{Key: msg.Path(mx.Mx, b.Debug()), Host: mx.Mx, Text: " IN AAAA: " + e1.Error()}
|
|
||||||
debug = append(debug, debugMsg)
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Internal name
|
// Internal name
|
||||||
state1 := state.NewWithQuestion(mx.Mx, dns.TypeA)
|
state1 := state.NewWithQuestion(mx.Mx, dns.TypeA)
|
||||||
addr, debugAddr, e1 := A(b, zone, state1, nil, opt)
|
addr, e1 := A(b, zone, state1, nil, opt)
|
||||||
if e1 == nil {
|
if e1 == nil {
|
||||||
extra = append(extra, addr...)
|
extra = append(extra, addr...)
|
||||||
debug = append(debug, debugAddr...)
|
|
||||||
}
|
}
|
||||||
// e.AAAA as well
|
// e.AAAA as well
|
||||||
|
|
||||||
|
@ -296,14 +277,14 @@ func MX(b ServiceBackend, zone string, state request.Request, opt Options) (reco
|
||||||
extra = append(extra, newAddress(serv, serv.Host, ip, what))
|
extra = append(extra, newAddress(serv, serv.Host, ip, what))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, extra, debug, nil
|
return records, extra, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CNAME returns CNAME records from the backend or an error.
|
// CNAME returns CNAME records from the backend or an error.
|
||||||
func CNAME(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, debug []msg.Service, err error) {
|
func CNAME(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) {
|
||||||
services, debug, err := b.Services(state, true, opt)
|
services, err := b.Services(state, true, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, debug, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(services) > 0 {
|
if len(services) > 0 {
|
||||||
|
@ -312,14 +293,14 @@ func CNAME(b ServiceBackend, zone string, state request.Request, opt Options) (r
|
||||||
records = append(records, serv.NewCNAME(state.QName(), serv.Host))
|
records = append(records, serv.NewCNAME(state.QName(), serv.Host))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, debug, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TXT returns TXT records from Backend or an error.
|
// TXT returns TXT records from Backend or an error.
|
||||||
func TXT(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, debug []msg.Service, err error) {
|
func TXT(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) {
|
||||||
services, debug, err := b.Services(state, false, opt)
|
services, err := b.Services(state, false, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, debug, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, serv := range services {
|
for _, serv := range services {
|
||||||
|
@ -328,14 +309,14 @@ func TXT(b ServiceBackend, zone string, state request.Request, opt Options) (rec
|
||||||
}
|
}
|
||||||
records = append(records, serv.NewTXT(state.QName()))
|
records = append(records, serv.NewTXT(state.QName()))
|
||||||
}
|
}
|
||||||
return records, debug, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PTR returns the PTR records from the backend, only services that have a domain name as host are included.
|
// PTR returns the PTR records from the backend, only services that have a domain name as host are included.
|
||||||
func PTR(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, debug []msg.Service, err error) {
|
func PTR(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) {
|
||||||
services, debug, err := b.Reverse(state, true, opt)
|
services, err := b.Reverse(state, true, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, debug, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, serv := range services {
|
for _, serv := range services {
|
||||||
|
@ -343,20 +324,20 @@ func PTR(b ServiceBackend, zone string, state request.Request, opt Options) (rec
|
||||||
records = append(records, serv.NewPTR(state.QName(), serv.Host))
|
records = append(records, serv.NewPTR(state.QName(), serv.Host))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, debug, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NS returns NS records from the backend
|
// NS returns NS records from the backend
|
||||||
func NS(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, debug []msg.Service, err error) {
|
func NS(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) {
|
||||||
// NS record for this zone live in a special place, ns.dns.<zone>. Fake our lookup.
|
// NS record for this zone live in a special place, ns.dns.<zone>. Fake our lookup.
|
||||||
// only a tad bit fishy...
|
// only a tad bit fishy...
|
||||||
old := state.QName()
|
old := state.QName()
|
||||||
|
|
||||||
state.Clear()
|
state.Clear()
|
||||||
state.Req.Question[0].Name = "ns.dns." + zone
|
state.Req.Question[0].Name = "ns.dns." + zone
|
||||||
services, debug, err := b.Services(state, false, opt)
|
services, err := b.Services(state, false, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, debug, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
// ... and reset
|
// ... and reset
|
||||||
state.Req.Question[0].Name = old
|
state.Req.Question[0].Name = old
|
||||||
|
@ -365,7 +346,7 @@ func NS(b ServiceBackend, zone string, state request.Request, opt Options) (reco
|
||||||
what, ip := serv.HostType()
|
what, ip := serv.HostType()
|
||||||
switch what {
|
switch what {
|
||||||
case dns.TypeCNAME:
|
case dns.TypeCNAME:
|
||||||
return nil, nil, debug, fmt.Errorf("NS record must be an IP address: %s", serv.Host)
|
return nil, nil, fmt.Errorf("NS record must be an IP address: %s", serv.Host)
|
||||||
|
|
||||||
case dns.TypeA, dns.TypeAAAA:
|
case dns.TypeA, dns.TypeAAAA:
|
||||||
serv.Host = msg.Domain(serv.Key)
|
serv.Host = msg.Domain(serv.Key)
|
||||||
|
@ -373,11 +354,11 @@ func NS(b ServiceBackend, zone string, state request.Request, opt Options) (reco
|
||||||
extra = append(extra, newAddress(serv, serv.Host, ip, what))
|
extra = append(extra, newAddress(serv, serv.Host, ip, what))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return records, extra, debug, nil
|
return records, extra, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SOA returns a SOA record from the backend.
|
// SOA returns a SOA record from the backend.
|
||||||
func SOA(b ServiceBackend, zone string, state request.Request, opt Options) ([]dns.RR, []msg.Service, error) {
|
func SOA(b ServiceBackend, zone string, state request.Request, opt Options) ([]dns.RR, error) {
|
||||||
header := dns.RR_Header{Name: zone, Rrtype: dns.TypeSOA, Ttl: 300, Class: dns.ClassINET}
|
header := dns.RR_Header{Name: zone, Rrtype: dns.TypeSOA, Ttl: 300, Class: dns.ClassINET}
|
||||||
|
|
||||||
Mbox := hostmaster + "."
|
Mbox := hostmaster + "."
|
||||||
|
@ -396,60 +377,22 @@ func SOA(b ServiceBackend, zone string, state request.Request, opt Options) ([]d
|
||||||
Expire: 86400,
|
Expire: 86400,
|
||||||
Minttl: minTTL,
|
Minttl: minTTL,
|
||||||
}
|
}
|
||||||
return []dns.RR{soa}, nil, nil
|
return []dns.RR{soa}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackendError writes an error response to the client.
|
// BackendError writes an error response to the client.
|
||||||
func BackendError(b ServiceBackend, zone string, rcode int, state request.Request, debug []msg.Service, err error, opt Options) (int, error) {
|
func BackendError(b ServiceBackend, zone string, rcode int, state request.Request, err error, opt Options) (int, error) {
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetRcode(state.Req, rcode)
|
m.SetRcode(state.Req, rcode)
|
||||||
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
|
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
|
||||||
m.Ns, _, _ = SOA(b, zone, state, opt)
|
m.Ns, _ = SOA(b, zone, state, opt)
|
||||||
if opt.Debug != "" {
|
|
||||||
m.Extra = ServicesToTxt(debug)
|
|
||||||
txt := ErrorToTxt(err)
|
|
||||||
if txt != nil {
|
|
||||||
m.Extra = append(m.Extra, ErrorToTxt(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.SizeAndDo(m)
|
state.SizeAndDo(m)
|
||||||
state.W.WriteMsg(m)
|
state.W.WriteMsg(m)
|
||||||
// Return success as the rcode to signal we have written to the client.
|
// Return success as the rcode to signal we have written to the client.
|
||||||
return dns.RcodeSuccess, err
|
return dns.RcodeSuccess, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServicesToTxt puts debug in TXT RRs.
|
|
||||||
func ServicesToTxt(debug []msg.Service) []dns.RR {
|
|
||||||
if debug == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := make([]dns.RR, len(debug))
|
|
||||||
for i, d := range debug {
|
|
||||||
rr[i] = d.RR()
|
|
||||||
}
|
|
||||||
return rr
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorToTxt puts in error's text into an TXT RR.
|
|
||||||
func ErrorToTxt(err error) dns.RR {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
msg := err.Error()
|
|
||||||
if len(msg) > 255 {
|
|
||||||
msg = msg[:255]
|
|
||||||
}
|
|
||||||
t := new(dns.TXT)
|
|
||||||
t.Hdr.Class = dns.ClassCHAOS
|
|
||||||
t.Hdr.Ttl = 0
|
|
||||||
t.Hdr.Rrtype = dns.TypeTXT
|
|
||||||
t.Hdr.Name = "."
|
|
||||||
|
|
||||||
t.Txt = []string{msg}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func newAddress(s msg.Service, name string, ip net.IP, what uint16) dns.RR {
|
func newAddress(s msg.Service, name string, ip net.IP, what uint16) dns.RR {
|
||||||
|
|
||||||
hdr := dns.RR_Header{Name: name, Rrtype: what, Class: dns.ClassINET, Ttl: s.TTL}
|
hdr := dns.RR_Header{Name: name, Rrtype: what, Class: dns.ClassINET, Ttl: s.TTL}
|
||||||
|
|
|
@ -28,7 +28,6 @@ etcd [ZONES...] {
|
||||||
endpoint ENDPOINT...
|
endpoint ENDPOINT...
|
||||||
upstream ADDRESS...
|
upstream ADDRESS...
|
||||||
tls CERT KEY CACERT
|
tls CERT KEY CACERT
|
||||||
debug
|
|
||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
@ -46,8 +45,6 @@ etcd [ZONES...] {
|
||||||
* a single argument that is the CA PEM file, if the server cert is not signed by a system CA and no client cert is needed
|
* a single argument that is the CA PEM file, if the server cert is not signed by a system CA and no client cert is needed
|
||||||
* two arguments - path to cert PEM file, the path to private key PEM file - if the server certificate is signed by a system-installed CA and a client certificate is needed
|
* two arguments - path to cert PEM file, the path to private key PEM file - if the server certificate is signed by a system-installed CA and a client certificate is needed
|
||||||
* three arguments - path to cert PEM file, path to client private key PEM file, path to CA PEM file - if the server certificate is not signed by a system-installed CA and client certificate is needed
|
* three arguments - path to cert PEM file, path to client private key PEM file, path to CA PEM file - if the server certificate is not signed by a system-installed CA and client certificate is needed
|
||||||
* `debug` allows for debug queries. Prefix the name with `o-o.debug.` to retrieve extra information in the
|
|
||||||
additional section of the reply in the form of TXT records.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -110,44 +107,3 @@ Querying with dig:
|
||||||
% dig @localhost -x 10.0.0.127 +short
|
% dig @localhost -x 10.0.0.127 +short
|
||||||
reverse.atoom.net.
|
reverse.atoom.net.
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Or with *debug* queries enabled:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
% dig @localhost -p 1053 o-o.debug.127.0.0.10.in-addr.arpa. PTR
|
|
||||||
|
|
||||||
;; OPT PSEUDOSECTION:
|
|
||||||
; EDNS: version: 0, flags:; udp: 4096
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;o-o.debug.127.0.0.10.in-addr.arpa. IN PTR
|
|
||||||
|
|
||||||
;; ANSWER SECTION:
|
|
||||||
127.0.0.10.in-addr.arpa. 300 IN PTR reverse.atoom.net.
|
|
||||||
|
|
||||||
;; ADDITIONAL SECTION:
|
|
||||||
127.0.0.10.in-addr.arpa. 300 CH TXT "reverse.atoom.net.:0(10,0,,false)[0,]"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Debug queries
|
|
||||||
|
|
||||||
When debug queries are enabled CoreDNS will return errors and etcd records encountered during the resolution
|
|
||||||
process in the response. The general form looks like this:
|
|
||||||
|
|
||||||
skydns.test.skydns.dom.a. 0 CH TXT "127.0.0.1:0(10,0,,false)[0,]"
|
|
||||||
|
|
||||||
This shows the complete key as the owername, the rdata of the TXT record has:
|
|
||||||
`host:port(priority,weight,txt content,mail)[targetstrip,group]`.
|
|
||||||
|
|
||||||
Errors when communicating with an upstream will be returned as: `host:0(0,0,error message,false)[0,]`.
|
|
||||||
|
|
||||||
An example:
|
|
||||||
|
|
||||||
www.example.org. 0 CH TXT "www.example.org.:0(0,0, IN A: unreachable backend,false)[0,]"
|
|
||||||
|
|
||||||
Signalling that an A record for www.example.org. was sought, but it failed with that error.
|
|
||||||
|
|
||||||
Any errors seen doing parsing will show up like this:
|
|
||||||
|
|
||||||
. 0 CH TXT "/skydns/local/skydns/r/a: invalid character '.' after object key:value pair"
|
|
||||||
|
|
||||||
which shows `a.r.skydns.local.` has a json encoding problem.
|
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
// +build etcd
|
|
||||||
|
|
||||||
package etcd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/middleware/etcd/msg"
|
|
||||||
"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
|
|
||||||
"github.com/coredns/coredns/middleware/test"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDebugLookup(t *testing.T) {
|
|
||||||
etc := newEtcdMiddleware()
|
|
||||||
etc.Debugging = true
|
|
||||||
|
|
||||||
for _, serv := range servicesDebug {
|
|
||||||
set(t, etc, serv.Key, 0, serv)
|
|
||||||
defer delete(t, etc, serv.Key)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range dnsTestCasesDebug {
|
|
||||||
m := tc.Msg()
|
|
||||||
|
|
||||||
rec := dnsrecorder.New(&test.ResponseWriter{})
|
|
||||||
etc.ServeDNS(ctxt, rec, m)
|
|
||||||
|
|
||||||
resp := rec.Msg
|
|
||||||
test.SortAndCheck(t, resp, tc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDebugLookupFalse(t *testing.T) {
|
|
||||||
etc := newEtcdMiddleware()
|
|
||||||
|
|
||||||
for _, serv := range servicesDebug {
|
|
||||||
set(t, etc, serv.Key, 0, serv)
|
|
||||||
defer delete(t, etc, serv.Key)
|
|
||||||
}
|
|
||||||
for _, tc := range dnsTestCasesDebugFalse {
|
|
||||||
m := tc.Msg()
|
|
||||||
|
|
||||||
rec := dnsrecorder.New(&test.ResponseWriter{})
|
|
||||||
etc.ServeDNS(ctxt, rec, m)
|
|
||||||
|
|
||||||
resp := rec.Msg
|
|
||||||
test.SortAndCheck(t, resp, tc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var servicesDebug = []*msg.Service{
|
|
||||||
{Host: "127.0.0.1", Key: "a.dom.skydns.test."},
|
|
||||||
{Host: "127.0.0.2", Key: "b.sub.dom.skydns.test."},
|
|
||||||
}
|
|
||||||
|
|
||||||
var dnsTestCasesDebug = []test.Case{
|
|
||||||
{
|
|
||||||
Qname: "o-o.debug.dom.skydns.test.", Qtype: dns.TypeA,
|
|
||||||
Answer: []dns.RR{
|
|
||||||
test.A("dom.skydns.test. 300 IN A 127.0.0.1"),
|
|
||||||
test.A("dom.skydns.test. 300 IN A 127.0.0.2"),
|
|
||||||
},
|
|
||||||
Extra: []dns.RR{
|
|
||||||
test.TXT(`a.dom.skydns.test. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
|
|
||||||
test.TXT(`b.sub.dom.skydns.test. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Qname: "o-o.debug.dom.skydns.test.", Qtype: dns.TypeTXT,
|
|
||||||
Ns: []dns.RR{
|
|
||||||
test.SOA("skydns.test. 300 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1463943291 7200 1800 86400 60"),
|
|
||||||
},
|
|
||||||
Extra: []dns.RR{
|
|
||||||
test.TXT(`a.dom.skydns.test. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`),
|
|
||||||
test.TXT(`b.sub.dom.skydns.test. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var dnsTestCasesDebugFalse = []test.Case{
|
|
||||||
{
|
|
||||||
Qname: "o-o.debug.dom.skydns.test.", Qtype: dns.TypeA,
|
|
||||||
Rcode: dns.RcodeNameError,
|
|
||||||
Ns: []dns.RR{
|
|
||||||
test.SOA("skydns.test. 300 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1463943291 7200 1800 86400 60"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Qname: "o-o.debug.dom.skydns.test.", Qtype: dns.TypeTXT,
|
|
||||||
Rcode: dns.RcodeNameError,
|
|
||||||
Ns: []dns.RR{
|
|
||||||
test.SOA("skydns.test. 300 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1463943291 7200 1800 86400 60"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -30,26 +30,23 @@ type Etcd struct {
|
||||||
Ctx context.Context
|
Ctx context.Context
|
||||||
Inflight *singleflight.Group
|
Inflight *singleflight.Group
|
||||||
Stubmap *map[string]proxy.Proxy // list of proxies for stub resolving.
|
Stubmap *map[string]proxy.Proxy // list of proxies for stub resolving.
|
||||||
Debugging bool // Do we allow debug queries.
|
|
||||||
|
|
||||||
endpoints []string // Stored here as well, to aid in testing.
|
endpoints []string // Stored here as well, to aid in testing.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Services implements the ServiceBackend interface.
|
// Services implements the ServiceBackend interface.
|
||||||
func (e *Etcd) Services(state request.Request, exact bool, opt middleware.Options) (services, debug []msg.Service, err error) {
|
func (e *Etcd) Services(state request.Request, exact bool, opt middleware.Options) (services []msg.Service, err error) {
|
||||||
services, err = e.Records(state, exact)
|
services, err = e.Records(state, exact)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if opt.Debug != "" {
|
|
||||||
debug = services
|
|
||||||
}
|
|
||||||
services = msg.Group(services)
|
services = msg.Group(services)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse implements the ServiceBackend interface.
|
// Reverse implements the ServiceBackend interface.
|
||||||
func (e *Etcd) Reverse(state request.Request, exact bool, opt middleware.Options) (services, debug []msg.Service, err error) {
|
func (e *Etcd) Reverse(state request.Request, exact bool, opt middleware.Options) (services []msg.Service, err error) {
|
||||||
return e.Services(state, exact, opt)
|
return e.Services(state, exact, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,11 +63,6 @@ func (e *Etcd) IsNameError(err error) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug implements the ServiceBackend interface.
|
|
||||||
func (e *Etcd) Debug() string {
|
|
||||||
return e.PathPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// Records looks up records in etcd. If exact is true, it will lookup just this
|
// Records looks up records in etcd. If exact is true, it will lookup just this
|
||||||
// name. This is used when find matches when completing SRV lookups for instance.
|
// name. This is used when find matches when completing SRV lookups for instance.
|
||||||
func (e *Etcd) Records(state request.Request, exact bool) ([]msg.Service, error) {
|
func (e *Etcd) Records(state request.Request, exact bool) ([]msg.Service, error) {
|
||||||
|
|
|
@ -2,8 +2,6 @@ package etcd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/coredns/coredns/middleware"
|
"github.com/coredns/coredns/middleware"
|
||||||
"github.com/coredns/coredns/middleware/etcd/msg"
|
|
||||||
"github.com/coredns/coredns/middleware/pkg/debug"
|
|
||||||
"github.com/coredns/coredns/middleware/pkg/dnsutil"
|
"github.com/coredns/coredns/middleware/pkg/dnsutil"
|
||||||
"github.com/coredns/coredns/request"
|
"github.com/coredns/coredns/request"
|
||||||
|
|
||||||
|
@ -17,13 +15,6 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
state := request.Request{W: w, Req: r}
|
state := request.Request{W: w, Req: r}
|
||||||
|
|
||||||
name := state.Name()
|
name := state.Name()
|
||||||
if e.Debugging {
|
|
||||||
if bug := debug.IsDebug(name); bug != "" {
|
|
||||||
opt.Debug = r.Question[0].Name
|
|
||||||
state.Clear()
|
|
||||||
state.Req.Question[0].Name = bug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to check stubzones first, because we may get a request for a zone we
|
// We need to check stubzones first, because we may get a request for a zone we
|
||||||
// are not auth. for *but* do have a stubzone forward for. If we do the stubzone
|
// are not auth. for *but* do have a stubzone forward for. If we do the stubzone
|
||||||
|
@ -39,49 +30,39 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
|
|
||||||
zone := middleware.Zones(e.Zones).Matches(state.Name())
|
zone := middleware.Zones(e.Zones).Matches(state.Name())
|
||||||
if zone == "" {
|
if zone == "" {
|
||||||
if opt.Debug != "" {
|
|
||||||
r.Question[0].Name = opt.Debug
|
|
||||||
}
|
|
||||||
return middleware.NextOrFailure(e.Name(), e.Next, ctx, w, r)
|
return middleware.NextOrFailure(e.Name(), e.Next, ctx, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
records, extra []dns.RR
|
records, extra []dns.RR
|
||||||
debug []msg.Service
|
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
switch state.Type() {
|
switch state.Type() {
|
||||||
case "A":
|
case "A":
|
||||||
records, debug, err = middleware.A(e, zone, state, nil, opt)
|
records, err = middleware.A(e, zone, state, nil, opt)
|
||||||
case "AAAA":
|
case "AAAA":
|
||||||
records, debug, err = middleware.AAAA(e, zone, state, nil, opt)
|
records, err = middleware.AAAA(e, zone, state, nil, opt)
|
||||||
case "TXT":
|
case "TXT":
|
||||||
records, debug, err = middleware.TXT(e, zone, state, opt)
|
records, err = middleware.TXT(e, zone, state, opt)
|
||||||
case "CNAME":
|
case "CNAME":
|
||||||
records, debug, err = middleware.CNAME(e, zone, state, opt)
|
records, err = middleware.CNAME(e, zone, state, opt)
|
||||||
case "PTR":
|
case "PTR":
|
||||||
records, debug, err = middleware.PTR(e, zone, state, opt)
|
records, err = middleware.PTR(e, zone, state, opt)
|
||||||
case "MX":
|
case "MX":
|
||||||
records, extra, debug, err = middleware.MX(e, zone, state, opt)
|
records, extra, err = middleware.MX(e, zone, state, opt)
|
||||||
case "SRV":
|
case "SRV":
|
||||||
records, extra, debug, err = middleware.SRV(e, zone, state, opt)
|
records, extra, err = middleware.SRV(e, zone, state, opt)
|
||||||
case "SOA":
|
case "SOA":
|
||||||
records, debug, err = middleware.SOA(e, zone, state, opt)
|
records, err = middleware.SOA(e, zone, state, opt)
|
||||||
case "NS":
|
case "NS":
|
||||||
if state.Name() == zone {
|
if state.Name() == zone {
|
||||||
records, extra, debug, err = middleware.NS(e, zone, state, opt)
|
records, extra, err = middleware.NS(e, zone, state, opt)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
|
// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
|
||||||
_, debug, err = middleware.A(e, zone, state, nil, opt)
|
_, err = middleware.A(e, zone, state, nil, opt)
|
||||||
}
|
|
||||||
|
|
||||||
if opt.Debug != "" {
|
|
||||||
// Substitute this name with the original when we return the request.
|
|
||||||
state.Clear()
|
|
||||||
state.Req.Question[0].Name = opt.Debug
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.IsNameError(err) {
|
if e.IsNameError(err) {
|
||||||
|
@ -89,14 +70,14 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
return middleware.NextOrFailure(e.Name(), e.Next, ctx, w, r)
|
return middleware.NextOrFailure(e.Name(), e.Next, ctx, w, r)
|
||||||
}
|
}
|
||||||
// Make err nil when returning here, so we don't log spam for NXDOMAIN.
|
// Make err nil when returning here, so we don't log spam for NXDOMAIN.
|
||||||
return middleware.BackendError(e, zone, dns.RcodeNameError, state, debug, nil /* err */, opt)
|
return middleware.BackendError(e, zone, dns.RcodeNameError, state, nil /* err */, opt)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return middleware.BackendError(e, zone, dns.RcodeServerFailure, state, debug, err, opt)
|
return middleware.BackendError(e, zone, dns.RcodeServerFailure, state, err, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return middleware.BackendError(e, zone, dns.RcodeSuccess, state, debug, err, opt)
|
return middleware.BackendError(e, zone, dns.RcodeSuccess, state, err, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
|
@ -104,9 +85,6 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
|
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
|
||||||
m.Answer = append(m.Answer, records...)
|
m.Answer = append(m.Answer, records...)
|
||||||
m.Extra = append(m.Extra, extra...)
|
m.Extra = append(m.Extra, extra...)
|
||||||
if opt.Debug != "" {
|
|
||||||
m.Extra = append(m.Extra, middleware.ServicesToTxt(debug)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
m = dnsutil.Dedup(m)
|
m = dnsutil.Dedup(m)
|
||||||
state.SizeAndDo(m)
|
state.SizeAndDo(m)
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
// +build etcd
|
|
||||||
|
|
||||||
package etcd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/middleware/etcd/msg"
|
|
||||||
"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
|
|
||||||
"github.com/coredns/coredns/middleware/proxy"
|
|
||||||
"github.com/coredns/coredns/middleware/test"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestProxyLookupFailDebug(t *testing.T) {
|
|
||||||
etc := newEtcdMiddleware()
|
|
||||||
etc.Proxy = proxy.NewLookup([]string{"127.0.0.1:154"})
|
|
||||||
etc.Debugging = true
|
|
||||||
|
|
||||||
for _, serv := range servicesProxy {
|
|
||||||
set(t, etc, serv.Key, 0, serv)
|
|
||||||
defer delete(t, etc, serv.Key)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range dnsTestCasesProxy {
|
|
||||||
m := tc.Msg()
|
|
||||||
|
|
||||||
rec := dnsrecorder.New(&test.ResponseWriter{})
|
|
||||||
_, err := etc.ServeDNS(ctxt, rec, m)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("expected no error, got %v\n", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := rec.Msg
|
|
||||||
test.SortAndCheck(t, resp, tc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var servicesProxy = []*msg.Service{
|
|
||||||
{Host: "www.example.org", Key: "a.dom.skydns.test."},
|
|
||||||
}
|
|
||||||
|
|
||||||
var dnsTestCasesProxy = []test.Case{
|
|
||||||
{
|
|
||||||
Qname: "o-o.debug.dom.skydns.test.", Qtype: dns.TypeSRV,
|
|
||||||
Answer: []dns.RR{
|
|
||||||
test.SRV("dom.skydns.test. 300 IN SRV 10 100 0 www.example.org."),
|
|
||||||
},
|
|
||||||
Extra: []dns.RR{
|
|
||||||
test.TXT("a.dom.skydns.test. 300 CH TXT \"www.example.org:0(10,0,,false)[0,]\""),
|
|
||||||
test.TXT("www.example.org. 0 CH TXT \"www.example.org.:0(0,0, IN A: unreachable backend: no upstream host,false)[0,]\""),
|
|
||||||
test.TXT("www.example.org. 0 CH TXT \"www.example.org.:0(0,0, IN AAAA: unreachable backend: no upstream host,false)[0,]\""),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -77,7 +77,7 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
|
||||||
case "fallthrough":
|
case "fallthrough":
|
||||||
etc.Fallthrough = true
|
etc.Fallthrough = true
|
||||||
case "debug":
|
case "debug":
|
||||||
etc.Debugging = true
|
/* it is a noop now */
|
||||||
case "path":
|
case "path":
|
||||||
if !c.NextArg() {
|
if !c.NextArg() {
|
||||||
return &Etcd{}, false, c.ArgErr()
|
return &Etcd{}, false, c.ArgErr()
|
||||||
|
|
|
@ -32,44 +32,44 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M
|
||||||
|
|
||||||
switch state.Type() {
|
switch state.Type() {
|
||||||
case "A":
|
case "A":
|
||||||
records, _, err = middleware.A(&k, zone, state, nil, middleware.Options{})
|
records, err = middleware.A(&k, zone, state, nil, middleware.Options{})
|
||||||
case "AAAA":
|
case "AAAA":
|
||||||
records, _, err = middleware.AAAA(&k, zone, state, nil, middleware.Options{})
|
records, err = middleware.AAAA(&k, zone, state, nil, middleware.Options{})
|
||||||
case "TXT":
|
case "TXT":
|
||||||
records, _, err = middleware.TXT(&k, zone, state, middleware.Options{})
|
records, err = middleware.TXT(&k, zone, state, middleware.Options{})
|
||||||
case "CNAME":
|
case "CNAME":
|
||||||
records, _, err = middleware.CNAME(&k, zone, state, middleware.Options{})
|
records, err = middleware.CNAME(&k, zone, state, middleware.Options{})
|
||||||
case "PTR":
|
case "PTR":
|
||||||
records, _, err = middleware.PTR(&k, zone, state, middleware.Options{})
|
records, err = middleware.PTR(&k, zone, state, middleware.Options{})
|
||||||
case "MX":
|
case "MX":
|
||||||
records, extra, _, err = middleware.MX(&k, zone, state, middleware.Options{})
|
records, extra, err = middleware.MX(&k, zone, state, middleware.Options{})
|
||||||
case "SRV":
|
case "SRV":
|
||||||
records, extra, _, err = middleware.SRV(&k, zone, state, middleware.Options{})
|
records, extra, err = middleware.SRV(&k, zone, state, middleware.Options{})
|
||||||
case "SOA":
|
case "SOA":
|
||||||
records, _, err = middleware.SOA(&k, zone, state, middleware.Options{})
|
records, err = middleware.SOA(&k, zone, state, middleware.Options{})
|
||||||
case "NS":
|
case "NS":
|
||||||
if state.Name() == zone {
|
if state.Name() == zone {
|
||||||
records, extra, _, err = middleware.NS(&k, zone, state, middleware.Options{})
|
records, extra, err = middleware.NS(&k, zone, state, middleware.Options{})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
|
// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
|
||||||
_, _, err = middleware.A(&k, zone, state, nil, middleware.Options{})
|
_, err = middleware.A(&k, zone, state, nil, middleware.Options{})
|
||||||
}
|
}
|
||||||
|
|
||||||
if k.IsNameError(err) {
|
if k.IsNameError(err) {
|
||||||
if k.Fallthrough {
|
if k.Fallthrough {
|
||||||
return middleware.NextOrFailure(k.Name(), k.Next, ctx, w, r)
|
return middleware.NextOrFailure(k.Name(), k.Next, ctx, w, r)
|
||||||
}
|
}
|
||||||
return middleware.BackendError(&k, zone, dns.RcodeNameError, state, nil /*debug*/, nil /* err */, middleware.Options{})
|
return middleware.BackendError(&k, zone, dns.RcodeNameError, state, nil /* err */, middleware.Options{})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dns.RcodeServerFailure, err
|
return dns.RcodeServerFailure, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return middleware.BackendError(&k, zone, dns.RcodeSuccess, state, nil /*debug*/, nil, middleware.Options{})
|
return middleware.BackendError(&k, zone, dns.RcodeSuccess, state, nil, middleware.Options{})
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Answer = append(m.Answer, records...)
|
m.Answer = append(m.Answer, records...)
|
||||||
|
|
|
@ -81,7 +81,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Services implements the ServiceBackend interface.
|
// Services implements the ServiceBackend interface.
|
||||||
func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.Options) (svcs []msg.Service, debug []msg.Service, err error) {
|
func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.Options) (svcs []msg.Service, err error) {
|
||||||
|
|
||||||
// We're looking again at types, which we've already done in ServeDNS, but there are some types k8s just can't answer.
|
// We're looking again at types, which we've already done in ServeDNS, but there are some types k8s just can't answer.
|
||||||
switch state.QType() {
|
switch state.QType() {
|
||||||
|
@ -92,19 +92,19 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
|
|
||||||
segs := dns.SplitDomainName(t)
|
segs := dns.SplitDomainName(t)
|
||||||
if len(segs) != 1 {
|
if len(segs) != 1 {
|
||||||
return nil, nil, fmt.Errorf("kubernetes: TXT query can only be for dns-version: %s", state.QName())
|
return nil, fmt.Errorf("kubernetes: TXT query can only be for dns-version: %s", state.QName())
|
||||||
}
|
}
|
||||||
if segs[0] != "dns-version" {
|
if segs[0] != "dns-version" {
|
||||||
return nil, nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
svc := msg.Service{Text: DNSSchemaVersion, TTL: 28800, Key: msg.Path(state.QName(), "coredns")}
|
svc := msg.Service{Text: DNSSchemaVersion, TTL: 28800, Key: msg.Path(state.QName(), "coredns")}
|
||||||
return []msg.Service{svc}, nil, nil
|
return []msg.Service{svc}, nil
|
||||||
|
|
||||||
case dns.TypeNS:
|
case dns.TypeNS:
|
||||||
// We can only get here if the qname equal the zone, see ServeDNS in handler.go.
|
// We can only get here if the qname equal the zone, see ServeDNS in handler.go.
|
||||||
ns := k.nsAddr()
|
ns := k.nsAddr()
|
||||||
svc := msg.Service{Host: ns.A.String(), Key: msg.Path(state.QName(), "coredns")}
|
svc := msg.Service{Host: ns.A.String(), Key: msg.Path(state.QName(), "coredns")}
|
||||||
return []msg.Service{svc}, nil, nil
|
return []msg.Service{svc}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.QType() == dns.TypeA && isDefaultNS(state.Name(), state.Zone) {
|
if state.QType() == dns.TypeA && isDefaultNS(state.Name(), state.Zone) {
|
||||||
|
@ -112,7 +112,7 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
// SOA records always use this hardcoded name
|
// SOA records always use this hardcoded name
|
||||||
ns := k.nsAddr()
|
ns := k.nsAddr()
|
||||||
svc := msg.Service{Host: ns.A.String(), Key: msg.Path(state.QName(), "coredns")}
|
svc := msg.Service{Host: ns.A.String(), Key: msg.Path(state.QName(), "coredns")}
|
||||||
return []msg.Service{svc}, nil, nil
|
return []msg.Service{svc}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s, e := k.Records(state, false)
|
s, e := k.Records(state, false)
|
||||||
|
@ -120,7 +120,7 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
// SRV for external services is not yet implemented, so remove those records.
|
// SRV for external services is not yet implemented, so remove those records.
|
||||||
|
|
||||||
if state.QType() != dns.TypeSRV {
|
if state.QType() != dns.TypeSRV {
|
||||||
return s, nil, e
|
return s, e
|
||||||
}
|
}
|
||||||
|
|
||||||
internal := []msg.Service{}
|
internal := []msg.Service{}
|
||||||
|
@ -130,13 +130,11 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return internal, nil, e
|
return internal, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// primaryZone will return the first non-reverse zone being handled by this middleware
|
// primaryZone will return the first non-reverse zone being handled by this middleware
|
||||||
func (k *Kubernetes) primaryZone() string {
|
func (k *Kubernetes) primaryZone() string { return k.Zones[k.primaryZoneIndex] }
|
||||||
return k.Zones[k.primaryZoneIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup implements the ServiceBackend interface.
|
// Lookup implements the ServiceBackend interface.
|
||||||
func (k *Kubernetes) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) {
|
func (k *Kubernetes) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) {
|
||||||
|
@ -148,9 +146,6 @@ func (k *Kubernetes) IsNameError(err error) bool {
|
||||||
return err == errNoItems || err == errNsNotExposed || err == errInvalidRequest
|
return err == errNoItems || err == errNsNotExposed || err == errInvalidRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug implements the ServiceBackend interface.
|
|
||||||
func (k *Kubernetes) Debug() string { return "debug" }
|
|
||||||
|
|
||||||
func (k *Kubernetes) getClientConfig() (*rest.Config, error) {
|
func (k *Kubernetes) getClientConfig() (*rest.Config, error) {
|
||||||
loadingRules := &clientcmd.ClientConfigLoadingRules{}
|
loadingRules := &clientcmd.ClientConfigLoadingRules{}
|
||||||
overrides := &clientcmd.ConfigOverrides{}
|
overrides := &clientcmd.ConfigOverrides{}
|
||||||
|
|
|
@ -222,7 +222,7 @@ func TestServices(t *testing.T) {
|
||||||
Req: &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
|
Req: &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
|
||||||
Zone: "interwebs.test.", // must match from k.Zones[0]
|
Zone: "interwebs.test.", // must match from k.Zones[0]
|
||||||
}
|
}
|
||||||
svcs, _, e := k.Services(state, false, middleware.Options{})
|
svcs, e := k.Services(state, false, middleware.Options{})
|
||||||
if e != nil {
|
if e != nil {
|
||||||
t.Errorf("Test %d: got error '%v'", i, e)
|
t.Errorf("Test %d: got error '%v'", i, e)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -10,15 +10,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reverse implements the ServiceBackend interface.
|
// Reverse implements the ServiceBackend interface.
|
||||||
func (k *Kubernetes) Reverse(state request.Request, exact bool, opt middleware.Options) ([]msg.Service, []msg.Service, error) {
|
func (k *Kubernetes) Reverse(state request.Request, exact bool, opt middleware.Options) ([]msg.Service, error) {
|
||||||
|
|
||||||
ip := dnsutil.ExtractAddressFromReverse(state.Name())
|
ip := dnsutil.ExtractAddressFromReverse(state.Name())
|
||||||
if ip == "" {
|
if ip == "" {
|
||||||
return nil, nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
records := k.serviceRecordForIP(ip, state.Name())
|
records := k.serviceRecordForIP(ip, state.Name())
|
||||||
return records, nil, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// serviceRecordForIP gets a service record with a cluster ip matching the ip argument
|
// serviceRecordForIP gets a service record with a cluster ip matching the ip argument
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package debug
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Name is the domain prefix we check for when it is a debug query.
|
|
||||||
const Name = "o-o.debug."
|
|
||||||
|
|
||||||
// IsDebug checks if name is a debugging name, i.e. starts with o-o.debug.
|
|
||||||
// it returns the empty string if it is not a debug message, otherwise it will return the
|
|
||||||
// name with o-o.debug. stripped off. Name will be lowercased before comparing.
|
|
||||||
func IsDebug(name string) string {
|
|
||||||
if len(name) == len(Name) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
name = strings.ToLower(name)
|
|
||||||
debug := strings.HasPrefix(name, Name)
|
|
||||||
if !debug {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return name[len(Name):]
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package debug
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIsDebug(t *testing.T) {
|
|
||||||
if ok := IsDebug("o-o.debug.miek.nl."); ok != "miek.nl." {
|
|
||||||
t.Errorf("expected o-o.debug.miek.nl. to be debug")
|
|
||||||
}
|
|
||||||
if ok := IsDebug(strings.ToLower("o-o.Debug.miek.nl.")); ok != "miek.nl." {
|
|
||||||
t.Errorf("expected o-o.Debug.miek.nl. to be debug")
|
|
||||||
}
|
|
||||||
if ok := IsDebug("i-o.debug.miek.nl."); ok != "" {
|
|
||||||
t.Errorf("expected i-o.Debug.miek.nl. to be non-debug")
|
|
||||||
}
|
|
||||||
if ok := IsDebug(strings.ToLower("i-o.Debug.")); ok != "" {
|
|
||||||
t.Errorf("expected o-o.Debug. to be non-debug")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coredns/coredns/middleware/pkg/debug"
|
|
||||||
"github.com/coredns/coredns/middleware/pkg/healthcheck"
|
"github.com/coredns/coredns/middleware/pkg/healthcheck"
|
||||||
"github.com/coredns/coredns/request"
|
"github.com/coredns/coredns/request"
|
||||||
|
|
||||||
|
@ -50,12 +49,6 @@ func (g *google) Exchange(ctx context.Context, addr string, state request.Reques
|
||||||
v.Set("name", state.Name())
|
v.Set("name", state.Name())
|
||||||
v.Set("type", fmt.Sprintf("%d", state.QType()))
|
v.Set("type", fmt.Sprintf("%d", state.QType()))
|
||||||
|
|
||||||
optDebug := false
|
|
||||||
if bug := debug.IsDebug(state.Name()); bug != "" {
|
|
||||||
optDebug = true
|
|
||||||
v.Set("name", bug)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, backendErr := g.exchangeJSON(addr, v.Encode())
|
buf, backendErr := g.exchangeJSON(addr, v.Encode())
|
||||||
|
|
||||||
if backendErr == nil {
|
if backendErr == nil {
|
||||||
|
@ -64,19 +57,11 @@ func (g *google) Exchange(ctx context.Context, addr string, state request.Reques
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m, debug, err := toMsg(gm)
|
m, err := toMsg(gm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if optDebug {
|
|
||||||
// reset question
|
|
||||||
m.Question[0].Name = state.QName()
|
|
||||||
// prepend debug RR to the additional section
|
|
||||||
m.Extra = append([]dns.RR{debug}, m.Extra...)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Id = state.Req.Id
|
m.Id = state.Req.Id
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// toMsg converts a googleMsg into the dns message. The returned RR is the comment disquised as a TXT record.
|
// toMsg converts a googleMsg into the dns message.
|
||||||
func toMsg(g *googleMsg) (*dns.Msg, dns.RR, error) {
|
func toMsg(g *googleMsg) (*dns.Msg, error) {
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.Response = true
|
m.Response = true
|
||||||
m.Rcode = g.Status
|
m.Rcode = g.Status
|
||||||
|
@ -28,24 +28,23 @@ func toMsg(g *googleMsg) (*dns.Msg, dns.RR, error) {
|
||||||
for i := 0; i < len(m.Answer); i++ {
|
for i := 0; i < len(m.Answer); i++ {
|
||||||
m.Answer[i], err = toRR(g.Answer[i])
|
m.Answer[i], err = toRR(g.Answer[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(m.Ns); i++ {
|
for i := 0; i < len(m.Ns); i++ {
|
||||||
m.Ns[i], err = toRR(g.Authority[i])
|
m.Ns[i], err = toRR(g.Authority[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(m.Extra); i++ {
|
for i := 0; i < len(m.Extra); i++ {
|
||||||
m.Extra[i], err = toRR(g.Additional[i])
|
m.Extra[i], err = toRR(g.Additional[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
txt, _ := dns.NewRR(". 0 CH TXT " + g.Comment)
|
return m, nil
|
||||||
return m, txt, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// toRR transforms a "google" RR to a dns.RR.
|
// toRR transforms a "google" RR to a dns.RR.
|
||||||
|
|
|
@ -18,11 +18,10 @@ import (
|
||||||
|
|
||||||
// uses some stuff from etcd_tests.go
|
// uses some stuff from etcd_tests.go
|
||||||
|
|
||||||
func TestEtcdCacheAndDebug(t *testing.T) {
|
func TestEtcdCache(t *testing.T) {
|
||||||
corefile := `.:0 {
|
corefile := `.:0 {
|
||||||
etcd skydns.test {
|
etcd skydns.test {
|
||||||
path /skydns
|
path /skydns
|
||||||
debug
|
|
||||||
}
|
}
|
||||||
cache skydns.test
|
cache skydns.test
|
||||||
}`
|
}`
|
||||||
|
@ -51,15 +50,6 @@ func TestEtcdCacheAndDebug(t *testing.T) {
|
||||||
}
|
}
|
||||||
checkResponse(t, resp)
|
checkResponse(t, resp)
|
||||||
|
|
||||||
resp, err = p.Lookup(state, "o-o.debug.b.example.skydns.test.", dns.TypeA)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Expected to receive reply, but didn't: %s", err)
|
|
||||||
}
|
|
||||||
checkResponse(t, resp)
|
|
||||||
if len(resp.Extra) != 1 {
|
|
||||||
t.Errorf("Expected one RR in additional section, got: %d", len(resp.Extra))
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err = p.Lookup(state, "b.example.skydns.test.", dns.TypeA)
|
resp, err = p.Lookup(state, "b.example.skydns.test.", dns.TypeA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Expected to receive reply, but didn't: %s", err)
|
t.Errorf("Expected to receive reply, but didn't: %s", err)
|
Loading…
Add table
Reference in a new issue