diff --git a/middleware/etcd/debug_test.go b/middleware/etcd/debug_test.go index 9e50b6930..cf1a65129 100644 --- a/middleware/etcd/debug_test.go +++ b/middleware/etcd/debug_test.go @@ -113,8 +113,8 @@ var dnsTestCasesDebug = []test.Case{ test.A("dom.skydns.test. 300 IN A 127.0.0.2"), }, Extra: []dns.RR{ - test.TXT(`skydns.test.skydns.dom.a. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`), - test.TXT(`skydns.test.skydns.dom.sub.b. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`), + 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,]"`), }, }, { @@ -123,8 +123,8 @@ var dnsTestCasesDebug = []test.Case{ test.SOA("skydns.test. 300 IN SOA ns.dns.skydns.test. hostmaster.skydns.test. 1463943291 7200 1800 86400 60"), }, Extra: []dns.RR{ - test.TXT(`skydns.test.skydns.dom.a. 300 CH TXT "127.0.0.1:0(10,0,,false)[0,]"`), - test.TXT(`skydns.test.skydns.dom.sub.b. 300 CH TXT "127.0.0.2:0(10,0,,false)[0,]"`), + 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,]"`), }, }, } diff --git a/middleware/etcd/etcd.go b/middleware/etcd/etcd.go index eb0eb5c43..4176f1cb8 100644 --- a/middleware/etcd/etcd.go +++ b/middleware/etcd/etcd.go @@ -32,12 +32,12 @@ type Etcd struct { // this name. This is used when find matches when completing SRV lookups // for instance. func (g Etcd) Records(name string, exact bool) ([]msg.Service, error) { - path, star := g.PathWithWildcard(name) + path, star := msg.PathWithWildcard(name, g.PathPrefix) r, err := g.Get(path, true) if err != nil { return nil, err } - segments := strings.Split(g.Path(name), "/") + segments := strings.Split(msg.Path(name, g.PathPrefix), "/") switch { case exact && r.Node.Dir: return nil, nil diff --git a/middleware/etcd/handler.go b/middleware/etcd/handler.go index ac0f701dd..bf87afcd6 100644 --- a/middleware/etcd/handler.go +++ b/middleware/etcd/handler.go @@ -76,7 +76,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i } if e.debug != "" { - // substitute this name with the original when we return the request. + // Substitute this name with the original when we return the request. state.Clear() state.Req.Question[0].Name = e.debug } @@ -112,6 +112,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i func (e Etcd) Err(zone string, rcode int, state middleware.State, debug []msg.Service) (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) m.Extra = servicesToTxt(debug) state.SizeAndDo(m) diff --git a/middleware/etcd/lookup.go b/middleware/etcd/lookup.go index 15b6afe19..1223f85a4 100644 --- a/middleware/etcd/lookup.go +++ b/middleware/etcd/lookup.go @@ -213,13 +213,13 @@ func (e Etcd) SRV(zone string, state middleware.State) (records, extra []dns.RR, } // e.AAA(zone, state1, nil) as well...? case ip.To4() != nil: - serv.Host = e.Domain(serv.Key) + serv.Host = msg.Domain(serv.Key) srv := serv.NewSRV(state.QName(), weight) records = append(records, srv) extra = append(extra, serv.NewA(srv.Target, ip.To4())) case ip.To4() == nil: - serv.Host = e.Domain(serv.Key) + serv.Host = msg.Domain(serv.Key) srv := serv.NewSRV(state.QName(), weight) records = append(records, srv) @@ -278,11 +278,11 @@ func (e Etcd) MX(zone string, state middleware.State) (records, extra []dns.RR, } // e.AAAA as well case ip.To4() != nil: - serv.Host = e.Domain(serv.Key) + serv.Host = msg.Domain(serv.Key) records = append(records, serv.NewMX(state.QName())) extra = append(extra, serv.NewA(serv.Host, ip.To4())) case ip.To4() == nil: - serv.Host = e.Domain(serv.Key) + serv.Host = msg.Domain(serv.Key) records = append(records, serv.NewMX(state.QName())) extra = append(extra, serv.NewAAAA(serv.Host, ip.To16())) } @@ -340,11 +340,11 @@ func (e Etcd) NS(zone string, state middleware.State) (records, extra []dns.RR, case ip == nil: return nil, nil, debug, fmt.Errorf("NS record must be an IP address: %s", serv.Host) case ip.To4() != nil: - serv.Host = e.Domain(serv.Key) + serv.Host = msg.Domain(serv.Key) records = append(records, serv.NewNS(state.QName())) extra = append(extra, serv.NewA(serv.Host, ip.To4())) case ip.To4() == nil: - serv.Host = e.Domain(serv.Key) + serv.Host = msg.Domain(serv.Key) records = append(records, serv.NewNS(state.QName())) extra = append(extra, serv.NewAAAA(serv.Host, ip.To16())) } diff --git a/middleware/etcd/path.go b/middleware/etcd/msg/path.go similarity index 74% rename from middleware/etcd/path.go rename to middleware/etcd/msg/path.go index 2cd87ac86..16c1bbd60 100644 --- a/middleware/etcd/path.go +++ b/middleware/etcd/msg/path.go @@ -1,4 +1,4 @@ -package etcd +package msg import ( "path" @@ -9,16 +9,16 @@ import ( // Path converts a domainname to an etcd path. If s looks like service.staging.skydns.local., // the resulting key will be /skydns/local/skydns/staging/service . -func (e Etcd) Path(s string) string { +func Path(s, prefix string) string { l := dns.SplitDomainName(s) for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 { l[i], l[j] = l[j], l[i] } - return path.Join(append([]string{"/" + e.PathPrefix + "/"}, l...)...) + return path.Join(append([]string{"/" + prefix + "/"}, l...)...) } // Domain is the opposite of Path. -func (e Etcd) Domain(s string) string { +func Domain(s string) string { l := strings.Split(s, "/") // start with 1, to strip /skydns for i, j := 1, len(l)-1; i < j; i, j = i+1, j-1 { @@ -32,15 +32,15 @@ func (e Etcd) Domain(s string) string { // later find the matching names. So service.*.skydns.local, will look for all // services under skydns.local and will later check for names that match // service.*.skydns.local. If a wildcard is found the returned bool is true. -func (e Etcd) PathWithWildcard(s string) (string, bool) { +func PathWithWildcard(s, prefix string) (string, bool) { l := dns.SplitDomainName(s) for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 { l[i], l[j] = l[j], l[i] } for i, k := range l { if k == "*" || k == "any" { - return path.Join(append([]string{"/" + e.PathPrefix + "/"}, l[:i]...)...), true + return path.Join(append([]string{"/" + prefix + "/"}, l[:i]...)...), true } } - return path.Join(append([]string{"/" + e.PathPrefix + "/"}, l...)...), false + return path.Join(append([]string{"/" + prefix + "/"}, l...)...), false } diff --git a/middleware/etcd/path_test.go b/middleware/etcd/msg/path_test.go similarity index 71% rename from middleware/etcd/path_test.go rename to middleware/etcd/msg/path_test.go index feebb4210..a9ec59713 100644 --- a/middleware/etcd/path_test.go +++ b/middleware/etcd/msg/path_test.go @@ -1,11 +1,10 @@ -package etcd +package msg import "testing" func TestPath(t *testing.T) { for _, path := range []string{"mydns", "skydns"} { - e := Etcd{PathPrefix: path} - result := e.Path("service.staging.skydns.local.") + result := Path("service.staging.skydns.local.", path) if result != "/"+path+"/local/skydns/staging/service" { t.Errorf("Failure to get domain's path with prefix: %s", result) } diff --git a/middleware/etcd/msg/service.go b/middleware/etcd/msg/service.go index e851df978..76d74a463 100644 --- a/middleware/etcd/msg/service.go +++ b/middleware/etcd/msg/service.go @@ -39,13 +39,13 @@ type Service struct { // RR returns an RR representation of s. It is in a condensed form to minimize space // when this is returned in a DNS message. // The RR will look like: -// skydns.local.skydns.east.production.rails.1. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]" -// etcd Key Ttl Host:Port < see below > +// 1.rails.production.east.skydns.local. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]" +// etcd Key Ttl Host:Port < see below > // between parens: (Priority, Weight, Text (only first 200 bytes!), Mail) // between blockquotes: [TargetStrip,Group] // If the record is synthesised by CoreDNS (i.e. no lookup in etcd happened): // -// skydns.local.skydns.east.production.rails.1. 300 CH TXT "service1.example.com:8080(10,0,,false)[0,]" +// TODO(miek): what to put here? // func (s *Service) RR() *dns.TXT { l := len(s.Text) @@ -56,8 +56,7 @@ func (s *Service) RR() *dns.TXT { t.Hdr.Class = dns.ClassCHAOS t.Hdr.Ttl = s.Ttl t.Hdr.Rrtype = dns.TypeTXT - // TODO(miek): key guaranteerd to be > 1? - t.Hdr.Name = strings.Replace(s.Key[1:], "/", ".", -1) + "." // TODO(miek): slightly more like etcd.Domain() + t.Hdr.Name = Domain(s.Key) t.Txt = make([]string, 1) t.Txt[0] = fmt.Sprintf("%s:%d(%d,%d,%s,%t)[%d,%s]", diff --git a/middleware/etcd/setup_test.go b/middleware/etcd/setup_test.go index a695d43ce..1810e8e70 100644 --- a/middleware/etcd/setup_test.go +++ b/middleware/etcd/setup_test.go @@ -47,12 +47,12 @@ func set(t *testing.T, e Etcd, k string, ttl time.Duration, m *msg.Service) { if err != nil { t.Fatal(err) } - path, _ := e.PathWithWildcard(k) + path, _ := msg.PathWithWildcard(k, e.PathPrefix) e.Client.Set(ctx, path, string(b), &etcdc.SetOptions{TTL: ttl}) } func delete(t *testing.T, e Etcd, k string) { - path, _ := e.PathWithWildcard(k) + path, _ := msg.PathWithWildcard(k, e.PathPrefix) e.Client.Delete(ctx, path, &etcdc.DeleteOptions{Recursive: false}) } diff --git a/middleware/etcd/stub.go b/middleware/etcd/stub.go index 83611b896..2d4c14c24 100644 --- a/middleware/etcd/stub.go +++ b/middleware/etcd/stub.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/proxy" "github.com/miekg/dns" @@ -46,7 +47,7 @@ func (e *Etcd) updateStubZones() { continue } - domain := e.Domain(serv.Key) + domain := msg.Domain(serv.Key) labels := dns.SplitDomainName(domain) // If the remaining name equals any of the zones we have, we ignore it.