diff --git a/middleware/backend.go b/middleware/backend.go index 73f9b016d..645c859d3 100644 --- a/middleware/backend.go +++ b/middleware/backend.go @@ -9,10 +9,14 @@ import ( // ServiceBackend defines a (dynamic) backend that returns a slice of service definitions. type ServiceBackend interface { - // Services communitates with the backend to retrieve the service defintion. Exact indicates + // Services communicates with the backend to retrieve the service defintion. Exact indicates // on exact much are that we are allowed to recurs. Services(state request.Request, exact bool, opt Options) ([]msg.Service, []msg.Service, error) + // Reverse communicates with the backend to retrieve service definition based on a IP address + // instead of a name. I.e. a reverse DNS lookup. + Reverse(state request.Request, exact bool, opt Options) ([]msg.Service, []msg.Service, error) + // Lookup is used to find records else where. Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) diff --git a/middleware/backend_lookup.go b/middleware/backend_lookup.go index a9a5e03fd..c52bb2881 100644 --- a/middleware/backend_lookup.go +++ b/middleware/backend_lookup.go @@ -330,9 +330,8 @@ func TXT(b ServiceBackend, zone string, state request.Request, opt Options) (rec } // PTR returns the PTR records from the backend, only services that have a domain name as host are included. -// TODO(miek|infoblox): move k8s to this as well. func PTR(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, debug []msg.Service, err error) { - services, debug, err := b.Services(state, true, opt) + services, debug, err := b.Reverse(state, true, opt) if err != nil { return nil, debug, err } diff --git a/middleware/etcd/etcd.go b/middleware/etcd/etcd.go index 133f10c40..f2f53895f 100644 --- a/middleware/etcd/etcd.go +++ b/middleware/etcd/etcd.go @@ -46,6 +46,11 @@ func (e *Etcd) Services(state request.Request, exact bool, opt middleware.Option return } +// Reverse implements the ServiceBackend interface. +func (e *Etcd) Reverse(state request.Request, exact bool, opt middleware.Options) (services, debug []msg.Service, err error) { + return e.Services(state, exact, opt) +} + // Lookup implements the ServiceBackend interface. func (e *Etcd) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) { return e.Proxy.Lookup(state, name, typ) diff --git a/middleware/kubernetes/controller.go b/middleware/kubernetes/controller.go index de6b98274..4110dc6bb 100644 --- a/middleware/kubernetes/controller.go +++ b/middleware/kubernetes/controller.go @@ -5,13 +5,13 @@ import ( "sync" "time" + "k8s.io/client-go/1.5/kubernetes" "k8s.io/client-go/1.5/pkg/api" "k8s.io/client-go/1.5/pkg/api/v1" - "k8s.io/client-go/1.5/tools/cache" - "k8s.io/client-go/1.5/kubernetes" "k8s.io/client-go/1.5/pkg/labels" "k8s.io/client-go/1.5/pkg/runtime" "k8s.io/client-go/1.5/pkg/watch" + "k8s.io/client-go/1.5/tools/cache" ) var ( @@ -36,11 +36,11 @@ type dnsController struct { selector *labels.Selector - svcController *cache.Controller - nsController *cache.Controller + svcController *cache.Controller + nsController *cache.Controller - svcLister cache.StoreToServiceLister - nsLister storeToNamespaceLister + svcLister cache.StoreToServiceLister + nsLister storeToNamespaceLister // stopLock is used to enforce only a single call to Stop is active. // Needed because we allow stopping through an http endpoint and diff --git a/middleware/kubernetes/handler.go b/middleware/kubernetes/handler.go index eb3071b18..e21ea6d58 100644 --- a/middleware/kubernetes/handler.go +++ b/middleware/kubernetes/handler.go @@ -22,24 +22,6 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M m.SetReply(r) m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true - // TODO: find an alternative to this block - // TODO(miek): Why is this even here, why does the path Etcd takes not work? - // Should be a "case PTR" below. I would also like to use middleware.PTR for this. - ip := dnsutil.ExtractAddressFromReverse(state.Name()) - if ip != "" { - records := k.getServiceRecordForIP(ip, state.Name()) - if len(records) > 0 { - srvPTR := &records[0] - m.Answer = append(m.Answer, srvPTR.NewPTR(state.QName(), ip)) - - m = dnsutil.Dedup(m) - state.SizeAndDo(m) - m, _ = state.Scrub(m) - w.WriteMsg(m) - return dns.RcodeSuccess, nil - } - } - // Check that query matches one of the zones served by this middleware, // otherwise delegate to the next in the pipeline. zone := middleware.Zones(k.Zones).Matches(state.Name()) @@ -63,6 +45,8 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M records, _, err = middleware.TXT(&k, zone, state, middleware.Options{}) case "CNAME": records, _, err = middleware.CNAME(&k, zone, state, middleware.Options{}) + case "PTR": + records, _, err = middleware.PTR(&k, zone, state, middleware.Options{}) case "MX": records, extra, _, err = middleware.MX(&k, zone, state, middleware.Options{}) case "SRV": diff --git a/middleware/kubernetes/kubernetes.go b/middleware/kubernetes/kubernetes.go index 05359dc69..d5766377f 100644 --- a/middleware/kubernetes/kubernetes.go +++ b/middleware/kubernetes/kubernetes.go @@ -18,13 +18,13 @@ import ( "github.com/miekg/coredns/request" "github.com/miekg/dns" + "k8s.io/client-go/1.5/kubernetes" "k8s.io/client-go/1.5/pkg/api" unversionedapi "k8s.io/client-go/1.5/pkg/api/unversioned" - "k8s.io/client-go/1.5/kubernetes" + "k8s.io/client-go/1.5/pkg/labels" "k8s.io/client-go/1.5/rest" "k8s.io/client-go/1.5/tools/clientcmd" clientcmdapi "k8s.io/client-go/1.5/tools/clientcmd/api" - "k8s.io/client-go/1.5/pkg/labels" ) // Kubernetes implements a middleware that connects to a Kubernetes cluster. @@ -50,6 +50,17 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware. return s, nil, e // Haven't implemented debug queries yet. } +// Reverse implements the ServiceBackend interface. +func (k *Kubernetes) Reverse(state request.Request, exact bool, opt middleware.Options) ([]msg.Service, []msg.Service, error) { + ip := dnsutil.ExtractAddressFromReverse(state.Name()) + if ip == "" { + return nil, nil, nil + } + + records := k.getServiceRecordForIP(ip, state.Name()) + return records, nil, nil +} + // Lookup implements the ServiceBackend interface. func (k *Kubernetes) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) { return k.Proxy.Lookup(state, name, typ) @@ -156,13 +167,6 @@ func (k *Kubernetes) getZoneForName(name string) (string, []string) { // just this name. This is used when find matches when completing SRV lookups // for instance. func (k *Kubernetes) Records(name string, exact bool) ([]msg.Service, error) { - // TODO: refactor this. - // Right now NamespaceFromSegmentArray do not supports PRE queries - ip := dnsutil.ExtractAddressFromReverse(name) - if ip != "" { - records := k.getServiceRecordForIP(ip, name) - return records, nil - } var ( serviceName string namespace string @@ -223,7 +227,7 @@ func (k *Kubernetes) getRecordsForServiceItems(serviceItems []*api.Service, zone key = strings.Replace(key, ".", "/", -1) for i, p := range item.Spec.Ports { - s := msg.Service{Key: msg.Path(strconv.Itoa(i) + "." + key, "coredns"), Host: clusterIP, Port: int(p.Port)} + s := msg.Service{Key: msg.Path(strconv.Itoa(i)+"."+key, "coredns"), Host: clusterIP, Port: int(p.Port)} records = append(records, s) } }