mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 01:34:21 -04:00 
			
		
		
		
	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:
		| @@ -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) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 ( | ||||||
|   | |||||||
| @@ -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": | ||||||
|   | |||||||
| @@ -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) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user