middleware/etcd: Return json parsing errors (#158)
When coredns unmarshals a json value and it fails it will put the error in the returned message iff the query was a debug query (o-o.debug.<REST>).
This commit is contained in:
parent
d04abdf422
commit
3110306296
4 changed files with 41 additions and 8 deletions
|
@ -39,7 +39,7 @@ etcd [zones...] {
|
||||||
pointing to external names. If you want CoreDNS to act as a proxy for clients you'll need to add
|
pointing to external names. If you want CoreDNS to act as a proxy for clients you'll need to add
|
||||||
the proxy middleware.
|
the proxy middleware.
|
||||||
* `tls` followed the cert, key and the CA's cert filenames.
|
* `tls` followed the cert, key and the CA's cert filenames.
|
||||||
* `debug` allow debug queries. Prefix the name with `o-o.debug.` to reveive extra information in the
|
* `debug` allow debug queries. Prefix the name with `o-o.debug.` to retrieve extra information in the
|
||||||
additional section of the reply in the form of text records:
|
additional section of the reply in the form of text records:
|
||||||
|
|
||||||
skydns.test.skydns.dom.a. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"
|
skydns.test.skydns.dom.a. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"
|
||||||
|
@ -47,6 +47,13 @@ etcd [zones...] {
|
||||||
This shows the complete key as the owername, the rdata of the TXT record has:
|
This shows the complete key as the owername, the rdata of the TXT record has:
|
||||||
`host:port(priority,weight,txt content,mail)[targetstrip,group]`.
|
`host:port(priority,weight,txt content,mail)[targetstrip,group]`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
This is the default SkyDNS setup, with everying specified in full:
|
This is the default SkyDNS setup, with everying specified in full:
|
||||||
|
|
|
@ -36,3 +36,21 @@ func servicesToTxt(debug []msg.Service) []dns.RR {
|
||||||
}
|
}
|
||||||
return rr
|
return 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
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package etcd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ Nodes:
|
||||||
}
|
}
|
||||||
serv := new(msg.Service)
|
serv := new(msg.Service)
|
||||||
if err := json.Unmarshal([]byte(n.Value), serv); err != nil {
|
if err := json.Unmarshal([]byte(n.Value), serv); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("%s: %s", n.Key, err.Error())
|
||||||
}
|
}
|
||||||
b := msg.Service{Host: serv.Host, Port: serv.Port, Priority: serv.Priority, Weight: serv.Weight, Text: serv.Text, Key: n.Key}
|
b := msg.Service{Host: serv.Host, Port: serv.Port, Priority: serv.Priority, Weight: serv.Weight, Text: serv.Text, Key: n.Key}
|
||||||
if _, ok := bx[b]; ok {
|
if _, ok := bx[b]; ok {
|
||||||
|
|
|
@ -82,14 +82,14 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
if isEtcdNameError(err) {
|
if isEtcdNameError(err) {
|
||||||
return e.Err(zone, dns.RcodeNameError, state, debug)
|
return e.Err(zone, dns.RcodeNameError, state, debug, err)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dns.RcodeServerFailure, err
|
return e.Err(zone, dns.RcodeServerFailure, state, debug, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return e.Err(zone, dns.RcodeSuccess, state, debug)
|
return e.Err(zone, dns.RcodeSuccess, state, debug, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
|
@ -109,15 +109,22 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err write an error response to the client.
|
// Err write an error response to the client.
|
||||||
func (e Etcd) Err(zone string, rcode int, state middleware.State, debug []msg.Service) (int, error) {
|
func (e Etcd) Err(zone string, rcode int, state middleware.State, debug []msg.Service, err error) (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, _, _ = e.SOA(zone, state)
|
m.Ns, _, _ = e.SOA(zone, state)
|
||||||
|
if e.debug != "" {
|
||||||
m.Extra = servicesToTxt(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 rcode, nil
|
// Return success as the rcode to signal we have written to the client.
|
||||||
|
return dns.RcodeSuccess, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func dedup(m *dns.Msg) *dns.Msg {
|
func dedup(m *dns.Msg) *dns.Msg {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue