BackendService: add Reverse method (#381)

Add a Reverse method to BackendService because different backends want
to to do diff. things. This allows etc/k8s to share even more code and
we can unify the PTR handling.
This commit is contained in:
Miek Gieben 2016-11-05 15:43:27 +00:00 committed by GitHub
parent 2cca527d9f
commit 8d3418c015
6 changed files with 33 additions and 37 deletions

View file

@ -9,10 +9,14 @@ import (
// ServiceBackend defines a (dynamic) backend that returns a slice of service definitions. // ServiceBackend defines a (dynamic) backend that returns a slice of service definitions.
type ServiceBackend interface { 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. // 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, []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 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)

View file

@ -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. // 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) { 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 { if err != nil {
return nil, debug, err return nil, debug, err
} }

View file

@ -46,6 +46,11 @@ func (e *Etcd) Services(state request.Request, exact bool, opt middleware.Option
return 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. // Lookup implements the ServiceBackend interface.
func (e *Etcd) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) { func (e *Etcd) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) {
return e.Proxy.Lookup(state, name, typ) return e.Proxy.Lookup(state, name, typ)

View file

@ -5,13 +5,13 @@ import (
"sync" "sync"
"time" "time"
"k8s.io/client-go/1.5/kubernetes"
"k8s.io/client-go/1.5/pkg/api" "k8s.io/client-go/1.5/pkg/api"
"k8s.io/client-go/1.5/pkg/api/v1" "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/labels"
"k8s.io/client-go/1.5/pkg/runtime" "k8s.io/client-go/1.5/pkg/runtime"
"k8s.io/client-go/1.5/pkg/watch" "k8s.io/client-go/1.5/pkg/watch"
"k8s.io/client-go/1.5/tools/cache"
) )
var ( var (

View file

@ -22,24 +22,6 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M
m.SetReply(r) m.SetReply(r)
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true 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, // Check that query matches one of the zones served by this middleware,
// otherwise delegate to the next in the pipeline. // otherwise delegate to the next in the pipeline.
zone := middleware.Zones(k.Zones).Matches(state.Name()) 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{}) 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":
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":

View file

@ -18,13 +18,13 @@ import (
"github.com/miekg/coredns/request" "github.com/miekg/coredns/request"
"github.com/miekg/dns" "github.com/miekg/dns"
"k8s.io/client-go/1.5/kubernetes"
"k8s.io/client-go/1.5/pkg/api" "k8s.io/client-go/1.5/pkg/api"
unversionedapi "k8s.io/client-go/1.5/pkg/api/unversioned" 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/rest"
"k8s.io/client-go/1.5/tools/clientcmd" "k8s.io/client-go/1.5/tools/clientcmd"
clientcmdapi "k8s.io/client-go/1.5/tools/clientcmd/api" 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. // 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. 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. // 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) {
return k.Proxy.Lookup(state, name, typ) 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 // just this name. This is used when find matches when completing SRV lookups
// for instance. // for instance.
func (k *Kubernetes) Records(name string, exact bool) ([]msg.Service, error) { 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 ( var (
serviceName string serviceName string
namespace string namespace string
@ -223,7 +227,7 @@ func (k *Kubernetes) getRecordsForServiceItems(serviceItems []*api.Service, zone
key = strings.Replace(key, ".", "/", -1) key = strings.Replace(key, ".", "/", -1)
for i, p := range item.Spec.Ports { 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) records = append(records, s)
} }
} }