ServiceBackend interface (#369)

* Add ServiceBackend interface

This adds a ServiceBackend interface that is shared between etcd/etcd3
(later) and kubernetes, leading to a massive reduction in code. When
returning the specific records from their backend.

Fixes #273
This commit is contained in:
Miek Gieben 2016-10-30 15:54:16 +00:00 committed by GitHub
parent 81d5baee28
commit 27d893cf33
15 changed files with 273 additions and 503 deletions

View file

@ -14,13 +14,13 @@ import (
// ServeDNS implements the middleware.Handler interface.
func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
opt := Options{}
opt := middleware.Options{}
state := request.Request{W: w, Req: r}
if state.QClass() != dns.ClassINET {
return dns.RcodeServerFailure, fmt.Errorf("can only deal with ClassINET")
}
name := state.Name()
if e.Debug {
if e.Debugging {
if debug := isDebug(name); debug != "" {
opt.Debug = r.Question[0].Name
state.Clear()
@ -58,30 +58,30 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
)
switch state.Type() {
case "A":
records, debug, err = e.A(zone, state, nil, opt)
records, debug, err = middleware.A(e, zone, state, nil, opt)
case "AAAA":
records, debug, err = e.AAAA(zone, state, nil, opt)
records, debug, err = middleware.AAAA(e, zone, state, nil, opt)
case "TXT":
records, debug, err = e.TXT(zone, state, opt)
records, debug, err = middleware.TXT(e, zone, state, opt)
case "CNAME":
records, debug, err = e.CNAME(zone, state, opt)
records, debug, err = middleware.CNAME(e, zone, state, opt)
case "PTR":
records, debug, err = e.PTR(zone, state, opt)
records, debug, err = middleware.PTR(e, zone, state, opt)
case "MX":
records, extra, debug, err = e.MX(zone, state, opt)
records, extra, debug, err = middleware.MX(e, zone, state, opt)
case "SRV":
records, extra, debug, err = e.SRV(zone, state, opt)
records, extra, debug, err = middleware.SRV(e, zone, state, opt)
case "SOA":
records, debug, err = e.SOA(zone, state, opt)
records, debug, err = middleware.SOA(e, zone, state, opt)
case "NS":
if state.Name() == zone {
records, extra, debug, err = e.NS(zone, state, opt)
records, extra, debug, err = middleware.NS(e, zone, state, opt)
break
}
fallthrough
default:
// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
_, debug, err = e.A(zone, state, nil, opt)
_, debug, err = middleware.A(e, zone, state, nil, opt)
}
if opt.Debug != "" {
@ -90,15 +90,15 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
state.Req.Question[0].Name = opt.Debug
}
if isEtcdNameError(err) {
return e.Err(zone, dns.RcodeNameError, state, debug, err, opt)
if e.IsNameError(err) {
return middleware.BackendError(e, zone, dns.RcodeNameError, state, debug, err, opt)
}
if err != nil {
return e.Err(zone, dns.RcodeServerFailure, state, debug, err, opt)
return middleware.BackendError(e, zone, dns.RcodeServerFailure, state, debug, err, opt)
}
if len(records) == 0 {
return e.Err(zone, dns.RcodeSuccess, state, debug, err, opt)
return middleware.BackendError(e, zone, dns.RcodeSuccess, state, debug, err, opt)
}
m := new(dns.Msg)
@ -107,7 +107,7 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
m.Answer = append(m.Answer, records...)
m.Extra = append(m.Extra, extra...)
if opt.Debug != "" {
m.Extra = append(m.Extra, servicesToTxt(debug)...)
m.Extra = append(m.Extra, middleware.ServicesToTxt(debug)...)
}
m = dnsutil.Dedup(m)
@ -119,22 +119,3 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
// Name implements the Handler interface.
func (e *Etcd) Name() string { return "etcd" }
// Err write an error response to the client.
func (e *Etcd) Err(zone string, rcode int, state request.Request, debug []msg.Service, err error, opt Options) (int, error) {
m := new(dns.Msg)
m.SetRcode(state.Req, rcode)
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
m.Ns, _, _ = e.SOA(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.W.WriteMsg(m)
// Return success as the rcode to signal we have written to the client.
return dns.RcodeSuccess, nil
}