| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | // Package kubernetes provides the kubernetes backend. | 
					
						
							|  |  |  | package kubernetes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-07-07 01:40:58 -07:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-02-01 12:56:10 -05:00
										 |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2016-09-23 09:48:11 -03:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin" | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/etcd/msg" | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/pkg/dnsutil" | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/fall" | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/healthcheck" | 
					
						
							| 
									
										
										
										
											2018-02-14 15:11:26 -05:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/upstream" | 
					
						
							| 
									
										
										
										
											2017-02-21 22:51:47 -08:00
										 |  |  | 	"github.com/coredns/coredns/request" | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 01:40:58 -07:00
										 |  |  | 	"github.com/miekg/dns" | 
					
						
							| 
									
										
										
										
											2018-01-03 19:11:28 +08:00
										 |  |  | 	api "k8s.io/api/core/v1" | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 	meta "k8s.io/apimachinery/pkg/apis/meta/v1" | 
					
						
							|  |  |  | 	"k8s.io/apimachinery/pkg/labels" | 
					
						
							|  |  |  | 	"k8s.io/client-go/kubernetes" | 
					
						
							|  |  |  | 	"k8s.io/client-go/rest" | 
					
						
							|  |  |  | 	"k8s.io/client-go/tools/clientcmd" | 
					
						
							|  |  |  | 	clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | // Kubernetes implements a plugin that connects to a Kubernetes cluster. | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | type Kubernetes struct { | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | 	Next             plugin.Handler | 
					
						
							|  |  |  | 	Zones            []string | 
					
						
							| 
									
										
										
										
											2018-02-14 15:11:26 -05:00
										 |  |  | 	Upstream         upstream.Upstream | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | 	APIServerList    []string | 
					
						
							|  |  |  | 	APIProxy         *apiProxy | 
					
						
							|  |  |  | 	APICertAuth      string | 
					
						
							|  |  |  | 	APIClientCert    string | 
					
						
							|  |  |  | 	APIClientKey     string | 
					
						
							|  |  |  | 	APIConn          dnsController | 
					
						
							|  |  |  | 	Namespaces       map[string]bool | 
					
						
							|  |  |  | 	podMode          string | 
					
						
							|  |  |  | 	endpointNameMode bool | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | 	Fall             fall.F | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | 	ttl              uint32 | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 	opts             dnsControlOpts | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 16:21:07 +01:00
										 |  |  | 	primaryZoneIndex   int | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | 	interfaceAddrsFunc func() net.IP | 
					
						
							| 
									
										
										
										
											2017-08-10 19:26:31 +01:00
										 |  |  | 	autoPathSearch     []string // Local search path from /etc/resolv.conf. Needed for autopath. | 
					
						
							| 
									
										
										
										
											2018-02-08 10:11:04 -06:00
										 |  |  | 	TransferTo         []string | 
					
						
							| 
									
										
										
										
											2017-06-28 18:44:30 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-29 13:16:13 -05:00
										 |  |  | // New returns a initialized Kubernetes. It default interfaceAddrFunc to return 127.0.0.1. All other | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | // values default to their zero value, primaryZoneIndex will thus point to the first zone. | 
					
						
							|  |  |  | func New(zones []string) *Kubernetes { | 
					
						
							|  |  |  | 	k := new(Kubernetes) | 
					
						
							|  |  |  | 	k.Zones = zones | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 	k.Namespaces = make(map[string]bool) | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 	k.interfaceAddrsFunc = func() net.IP { return net.ParseIP("127.0.0.1") } | 
					
						
							| 
									
										
										
										
											2017-08-22 22:11:48 +01:00
										 |  |  | 	k.podMode = podModeDisabled | 
					
						
							| 
									
										
										
										
											2017-08-27 01:32:46 +01:00
										 |  |  | 	k.ttl = defaultTTL | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return k | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 16:23:10 -05:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2017-08-22 22:11:48 +01:00
										 |  |  | 	// podModeDisabled is the default value where pod requests are ignored | 
					
						
							|  |  |  | 	podModeDisabled = "disabled" | 
					
						
							|  |  |  | 	// podModeVerified is where Pod requests are answered only if they exist | 
					
						
							|  |  |  | 	podModeVerified = "verified" | 
					
						
							|  |  |  | 	// podModeInsecure is where pod requests are answered without verfying they exist | 
					
						
							|  |  |  | 	podModeInsecure = "insecure" | 
					
						
							| 
									
										
										
										
											2017-01-29 12:06:26 -08:00
										 |  |  | 	// DNSSchemaVersion is the schema version: https://github.com/kubernetes/dns/blob/master/docs/specification.md | 
					
						
							| 
									
										
										
										
											2017-05-30 08:20:39 -04:00
										 |  |  | 	DNSSchemaVersion = "1.0.1" | 
					
						
							| 
									
										
										
										
											2017-12-07 17:04:02 -06:00
										 |  |  | 	// Svc is the DNS schema for kubernetes services | 
					
						
							|  |  |  | 	Svc = "svc" | 
					
						
							|  |  |  | 	// Pod is the DNS schema for kubernetes pods | 
					
						
							|  |  |  | 	Pod = "pod" | 
					
						
							|  |  |  | 	// defaultTTL to apply to all answers. | 
					
						
							|  |  |  | 	defaultTTL = 5 | 
					
						
							| 
									
										
										
										
											2017-01-11 16:23:10 -05:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-03 09:03:53 -07:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											2017-08-06 05:54:24 -07:00
										 |  |  | 	errNoItems        = errors.New("no items found") | 
					
						
							|  |  |  | 	errNsNotExposed   = errors.New("namespace is not exposed") | 
					
						
							|  |  |  | 	errInvalidRequest = errors.New("invalid query name") | 
					
						
							| 
									
										
										
										
											2017-08-03 09:03:53 -07:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-11-10 16:24:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | // Services implements the ServiceBackend interface. | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | func (k *Kubernetes) Services(state request.Request, exact bool, opt plugin.Options) (svcs []msg.Service, err error) { | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 	// We're looking again at types, which we've already done in ServeDNS, but there are some types k8s just can't answer. | 
					
						
							|  |  |  | 	switch state.QType() { | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 	case dns.TypeTXT: | 
					
						
							| 
									
										
										
										
											2017-08-10 22:14:19 +01:00
										 |  |  | 		// 1 label + zone, label must be "dns-version". | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 		t, _ := dnsutil.TrimZone(state.Name(), state.Zone) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 		segs := dns.SplitDomainName(t) | 
					
						
							|  |  |  | 		if len(segs) != 1 { | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 			return nil, fmt.Errorf("kubernetes: TXT query can only be for dns-version: %s", state.QName()) | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if segs[0] != "dns-version" { | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 			return nil, nil | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		svc := msg.Service{Text: DNSSchemaVersion, TTL: 28800, Key: msg.Path(state.QName(), "coredns")} | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 		return []msg.Service{svc}, nil | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-10 22:14:19 +01:00
										 |  |  | 	case dns.TypeNS: | 
					
						
							| 
									
										
										
										
											2018-06-12 03:23:25 +01:00
										 |  |  | 		// We can only get here if the qname equals the zone, see ServeDNS in handler.go. | 
					
						
							| 
									
										
										
										
											2017-08-10 23:13:08 +01:00
										 |  |  | 		ns := k.nsAddr() | 
					
						
							| 
									
										
										
										
											2017-08-10 22:14:19 +01:00
										 |  |  | 		svc := msg.Service{Host: ns.A.String(), Key: msg.Path(state.QName(), "coredns")} | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 		return []msg.Service{svc}, nil | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 	if state.QType() == dns.TypeA && isDefaultNS(state.Name(), state.Zone) { | 
					
						
							|  |  |  | 		// If this is an A request for "ns.dns", respond with a "fake" record for coredns. | 
					
						
							|  |  |  | 		// SOA records always use this hardcoded name | 
					
						
							|  |  |  | 		ns := k.nsAddr() | 
					
						
							|  |  |  | 		svc := msg.Service{Host: ns.A.String(), Key: msg.Path(state.QName(), "coredns")} | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 		return []msg.Service{svc}, nil | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-10 01:08:58 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-19 14:03:03 +01:00
										 |  |  | 	s, e := k.Records(state, false) | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// SRV for external services is not yet implemented, so remove those records. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if state.QType() != dns.TypeSRV { | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 		return s, e | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	internal := []msg.Service{} | 
					
						
							|  |  |  | 	for _, svc := range s { | 
					
						
							|  |  |  | 		if t, _ := svc.HostType(); t != dns.TypeCNAME { | 
					
						
							|  |  |  | 			internal = append(internal, svc) | 
					
						
							| 
									
										
										
										
											2017-05-30 08:20:39 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-15 14:37:18 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | 	return internal, e | 
					
						
							| 
									
										
										
										
											2017-01-15 14:37:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | // primaryZone will return the first non-reverse zone being handled by this plugin | 
					
						
							| 
									
										
										
										
											2017-09-12 10:52:43 +01:00
										 |  |  | func (k *Kubernetes) primaryZone() string { return k.Zones[k.primaryZoneIndex] } | 
					
						
							| 
									
										
										
										
											2016-11-14 19:31:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | // Lookup implements the ServiceBackend interface. | 
					
						
							|  |  |  | func (k *Kubernetes) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) { | 
					
						
							| 
									
										
										
										
											2018-02-14 15:11:26 -05:00
										 |  |  | 	return k.Upstream.Lookup(state, name, typ) | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsNameError implements the ServiceBackend interface. | 
					
						
							|  |  |  | func (k *Kubernetes) IsNameError(err error) bool { | 
					
						
							| 
									
										
										
										
											2017-08-10 22:14:19 +01:00
										 |  |  | 	return err == errNoItems || err == errNsNotExposed || err == errInvalidRequest | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 07:57:08 -04:00
										 |  |  | func (k *Kubernetes) getClientConfig() (*rest.Config, error) { | 
					
						
							| 
									
										
										
										
											2017-06-23 18:02:45 -04:00
										 |  |  | 	loadingRules := &clientcmd.ClientConfigLoadingRules{} | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	overrides := &clientcmd.ConfigOverrides{} | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | 	clusterinfo := clientcmdapi.Cluster{} | 
					
						
							|  |  |  | 	authinfo := clientcmdapi.AuthInfo{} | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 	// Connect to API from in cluster | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 	if len(k.APIServerList) == 0 { | 
					
						
							|  |  |  | 		cc, err := rest.InClusterConfig() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 		cc.ContentType = "application/vnd.kubernetes.protobuf" | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 		return cc, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 	// Connect to API from out of cluster | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 	endpoint := k.APIServerList[0] | 
					
						
							|  |  |  | 	if len(k.APIServerList) > 1 { | 
					
						
							|  |  |  | 		// Use a random port for api proxy, will get the value later through listener.Addr() | 
					
						
							|  |  |  | 		listener, err := net.Listen("tcp", "127.0.0.1:0") | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("failed to create kubernetes api proxy: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		k.APIProxy = &apiProxy{ | 
					
						
							|  |  |  | 			listener: listener, | 
					
						
							|  |  |  | 			handler: proxyHandler{ | 
					
						
							|  |  |  | 				HealthCheck: healthcheck.HealthCheck{ | 
					
						
							|  |  |  | 					FailTimeout: 3 * time.Second, | 
					
						
							|  |  |  | 					MaxFails:    1, | 
					
						
							|  |  |  | 					Path:        "/", | 
					
						
							|  |  |  | 					Interval:    5 * time.Second, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		k.APIProxy.handler.Hosts = make([]*healthcheck.UpstreamHost, len(k.APIServerList)) | 
					
						
							|  |  |  | 		for i, entry := range k.APIServerList { | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 			uh := &healthcheck.UpstreamHost{ | 
					
						
							|  |  |  | 				Name: strings.TrimPrefix(entry, "http://"), | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 				CheckDown: func(upstream *proxyHandler) healthcheck.UpstreamHostDownFunc { | 
					
						
							|  |  |  | 					return func(uh *healthcheck.UpstreamHost) bool { | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 						fails := atomic.LoadInt32(&uh.Fails) | 
					
						
							|  |  |  | 						if fails >= upstream.MaxFails && upstream.MaxFails != 0 { | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 							return true | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 						return false | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				}(&k.APIProxy.handler), | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 			k.APIProxy.handler.Hosts[i] = uh | 
					
						
							| 
									
										
										
										
											2017-08-10 17:14:56 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 		k.APIProxy.Handler = &k.APIProxy.handler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Find the random port used for api proxy | 
					
						
							|  |  |  | 		endpoint = fmt.Sprintf("http://%s", listener.Addr()) | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-23 16:30:19 +01:00
										 |  |  | 	clusterinfo.Server = endpoint | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | 	if len(k.APICertAuth) > 0 { | 
					
						
							|  |  |  | 		clusterinfo.CertificateAuthority = k.APICertAuth | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | 	if len(k.APIClientCert) > 0 { | 
					
						
							|  |  |  | 		authinfo.ClientCertificate = k.APIClientCert | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(k.APIClientKey) > 0 { | 
					
						
							|  |  |  | 		authinfo.ClientKey = k.APIClientKey | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | 	overrides.ClusterInfo = clusterinfo | 
					
						
							|  |  |  | 	overrides.AuthInfo = authinfo | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides) | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 	cc, err := clientConfig.ClientConfig() | 
					
						
							| 
									
										
										
										
											2017-11-13 11:01:57 -05:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 	cc.ContentType = "application/vnd.kubernetes.protobuf" | 
					
						
							|  |  |  | 	return cc, err | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | // InitKubeCache initializes a new Kubernetes cache. | 
					
						
							|  |  |  | func (k *Kubernetes) InitKubeCache() (err error) { | 
					
						
							| 
									
										
										
										
											2016-09-23 18:07:06 -04:00
										 |  |  | 	config, err := k.getClientConfig() | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 07:57:08 -04:00
										 |  |  | 	kubeClient, err := kubernetes.NewForConfig(config) | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 		return fmt.Errorf("failed to create kubernetes notification controller: %q", err) | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 	if k.opts.labelSelector != nil { | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		var selector labels.Selector | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 		selector, err = meta.LabelSelectorAsSelector(k.opts.labelSelector) | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 			return fmt.Errorf("unable to create Selector for LabelSelector '%s': %q", k.opts.labelSelector, err) | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 		k.opts.selector = selector | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 	k.opts.initPodCache = k.podMode == podModeVerified | 
					
						
							| 
									
										
										
										
											2016-10-30 15:54:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-27 07:45:32 -07:00
										 |  |  | 	k.opts.zones = k.Zones | 
					
						
							|  |  |  | 	k.opts.endpointNameMode = k.endpointNameMode | 
					
						
							| 
									
										
										
										
											2018-02-12 14:27:16 -05:00
										 |  |  | 	k.APIConn = newdnsController(kubeClient, k.opts) | 
					
						
							| 
									
										
										
										
											2016-08-22 23:15:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 18:19:51 -07:00
										 |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-19 14:03:03 +01:00
										 |  |  | // Records looks up services in kubernetes. | 
					
						
							|  |  |  | func (k *Kubernetes) Records(state request.Request, exact bool) ([]msg.Service, error) { | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 	r, e := parseRequest(state) | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 	if e != nil { | 
					
						
							|  |  |  | 		return nil, e | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-18 12:12:28 -04:00
										 |  |  | 	if r.podOrSvc == "" { | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 08:43:19 -08:00
										 |  |  | 	if dnsutil.IsReverse(state.Name()) > 0 { | 
					
						
							| 
									
										
										
										
											2018-02-28 10:53:12 -05:00
										 |  |  | 		return nil, errNoItems | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 	if !wildcard(r.namespace) && !k.namespaceExposed(r.namespace) { | 
					
						
							| 
									
										
										
										
											2016-11-11 16:56:15 +00:00
										 |  |  | 		return nil, errNsNotExposed | 
					
						
							| 
									
										
										
										
											2016-07-07 01:40:58 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 	if r.podOrSvc == Pod { | 
					
						
							|  |  |  | 		pods, err := k.findPods(r, state.Zone) | 
					
						
							|  |  |  | 		return pods, err | 
					
						
							| 
									
										
										
										
											2016-07-07 01:40:58 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 	services, err := k.findServices(r, state.Zone) | 
					
						
							|  |  |  | 	return services, err | 
					
						
							| 
									
										
										
										
											2016-07-07 01:40:58 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-27 07:45:32 -07:00
										 |  |  | // serviceFQDN returns the k8s cluster dns spec service FQDN for the service (or endpoint) object. | 
					
						
							|  |  |  | func serviceFQDN(obj meta.Object, zone string) string { | 
					
						
							|  |  |  | 	return dnsutil.Join(append([]string{}, obj.GetName(), obj.GetNamespace(), Svc, zone)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // podFQDN returns the k8s cluster dns spec FQDN for the pod. | 
					
						
							|  |  |  | func podFQDN(p *api.Pod, zone string) string { | 
					
						
							|  |  |  | 	name := strings.Replace(p.Status.PodIP, ".", "-", -1) | 
					
						
							|  |  |  | 	name = strings.Replace(name, ":", "-", -1) | 
					
						
							|  |  |  | 	return dnsutil.Join(append([]string{}, name, p.GetNamespace(), Pod, zone)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // endpointFQDN returns a list of k8s cluster dns spec service FQDNs for each subset in the endpoint. | 
					
						
							|  |  |  | func endpointFQDN(ep *api.Endpoints, zone string, endpointNameMode bool) []string { | 
					
						
							|  |  |  | 	var names []string | 
					
						
							|  |  |  | 	for _, ss := range ep.Subsets { | 
					
						
							|  |  |  | 		for _, addr := range ss.Addresses { | 
					
						
							|  |  |  | 			names = append(names, dnsutil.Join(append([]string{}, endpointHostname(addr, endpointNameMode), serviceFQDN(ep, zone)))) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return names | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | func endpointHostname(addr api.EndpointAddress, endpointNameMode bool) string { | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 	if addr.Hostname != "" { | 
					
						
							|  |  |  | 		return strings.ToLower(addr.Hostname) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | 	if endpointNameMode && addr.TargetRef != nil && addr.TargetRef.Name != "" { | 
					
						
							|  |  |  | 		return addr.TargetRef.Name | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 	if strings.Contains(addr.IP, ".") { | 
					
						
							|  |  |  | 		return strings.Replace(addr.IP, ".", "-", -1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if strings.Contains(addr.IP, ":") { | 
					
						
							|  |  |  | 		return strings.ToLower(strings.Replace(addr.IP, ":", "-", -1)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | func (k *Kubernetes) findPods(r recordRequest, zone string) (pods []msg.Service, err error) { | 
					
						
							| 
									
										
										
										
											2017-08-22 22:11:48 +01:00
										 |  |  | 	if k.podMode == podModeDisabled { | 
					
						
							| 
									
										
										
										
											2017-11-08 13:58:48 -05:00
										 |  |  | 		return nil, errNoItems | 
					
						
							| 
									
										
										
										
											2017-01-11 16:23:10 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 	namespace := r.namespace | 
					
						
							|  |  |  | 	podname := r.service | 
					
						
							|  |  |  | 	zonePath := msg.Path(zone, "coredns") | 
					
						
							|  |  |  | 	ip := "" | 
					
						
							| 
									
										
										
										
											2017-11-13 21:51:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 16:23:10 -05:00
										 |  |  | 	if strings.Count(podname, "-") == 3 && !strings.Contains(podname, "--") { | 
					
						
							|  |  |  | 		ip = strings.Replace(podname, "-", ".", -1) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ip = strings.Replace(podname, "-", ":", -1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 22:11:48 +01:00
										 |  |  | 	if k.podMode == podModeInsecure { | 
					
						
							| 
									
										
										
										
											2018-01-05 17:48:08 +00:00
										 |  |  | 		if !wildcard(namespace) && !k.namespace(namespace) { // no wildcard, but namespace does not exist | 
					
						
							|  |  |  | 			return nil, errNoItems | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-06 15:56:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// If ip does not parse as an IP address, we return an error, otherwise we assume a CNAME and will try to resolve it in backend_lookup.go | 
					
						
							|  |  |  | 		if net.ParseIP(ip) == nil { | 
					
						
							|  |  |  | 			return nil, errNoItems | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 17:48:08 +00:00
										 |  |  | 		return []msg.Service{{Key: strings.Join([]string{zonePath, Pod, namespace, podname}, "/"), Host: ip, TTL: k.ttl}}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = errNoItems | 
					
						
							|  |  |  | 	if wildcard(podname) && !wildcard(namespace) { | 
					
						
							|  |  |  | 		// If namespace exist, err should be nil, so that we return nodata instead of NXDOMAIN | 
					
						
							|  |  |  | 		if k.namespace(namespace) { | 
					
						
							|  |  |  | 			err = nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-11 16:23:10 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 02:22:11 -05:00
										 |  |  | 	// PodModeVerified | 
					
						
							| 
									
										
										
										
											2017-09-29 15:58:50 -04:00
										 |  |  | 	for _, p := range k.APIConn.PodIndex(ip) { | 
					
						
							| 
									
										
										
										
											2017-01-20 02:22:11 -05:00
										 |  |  | 		// If namespace has a wildcard, filter results against Corefile namespace list. | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 		if wildcard(namespace) && !k.namespaceExposed(p.Namespace) { | 
					
						
							| 
									
										
										
										
											2017-01-20 02:22:11 -05:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-05 17:48:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 03:06:03 -04:00
										 |  |  | 		// exclude pods in the process of termination | 
					
						
							|  |  |  | 		if !p.ObjectMeta.DeletionTimestamp.IsZero() { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 02:22:11 -05:00
										 |  |  | 		// check for matching ip and namespace | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 		if ip == p.Status.PodIP && match(namespace, p.Namespace) { | 
					
						
							| 
									
										
										
										
											2017-11-15 14:06:37 +00:00
										 |  |  | 			s := msg.Service{Key: strings.Join([]string{zonePath, Pod, namespace, podname}, "/"), Host: ip, TTL: k.ttl} | 
					
						
							| 
									
										
										
										
											2017-01-20 02:22:11 -05:00
										 |  |  | 			pods = append(pods, s) | 
					
						
							| 
									
										
										
										
											2017-01-11 16:23:10 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 			err = nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-01-15 03:12:28 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 	return pods, err | 
					
						
							| 
									
										
										
										
											2017-01-15 03:12:28 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | // findServices returns the services matching r from the cache. | 
					
						
							|  |  |  | func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg.Service, err error) { | 
					
						
							|  |  |  | 	zonePath := msg.Path(zone, "coredns") | 
					
						
							| 
									
										
										
										
											2017-11-13 21:51:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = errNoItems | 
					
						
							|  |  |  | 	if wildcard(r.service) && !wildcard(r.namespace) { | 
					
						
							|  |  |  | 		// If namespace exist, err should be nil, so that we return nodata instead of NXDOMAIN | 
					
						
							|  |  |  | 		if k.namespace(namespace) { | 
					
						
							|  |  |  | 			err = nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 		endpointsListFunc func() []*api.Endpoints | 
					
						
							|  |  |  | 		endpointsList     []*api.Endpoints | 
					
						
							|  |  |  | 		serviceList       []*api.Service | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 	if wildcard(r.service) || wildcard(r.namespace) { | 
					
						
							|  |  |  | 		serviceList = k.APIConn.ServiceList() | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 		endpointsListFunc = func() []*api.Endpoints { return k.APIConn.EndpointsList() } | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 		idx := r.service + "." + r.namespace | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 		serviceList = k.APIConn.SvcIndex(idx) | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 		endpointsListFunc = func() []*api.Endpoints { return k.APIConn.EpIndex(idx) } | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-20 22:53:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 	for _, svc := range serviceList { | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 		if !(match(r.namespace, svc.Namespace) && match(r.service, svc.Name)) { | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-18 14:45:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 		// If namespace has a wildcard, filter results against Corefile namespace list. | 
					
						
							|  |  |  | 		// (Namespaces without a wildcard were filtered before the call to this function.) | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 		if wildcard(r.namespace) && !k.namespaceExposed(svc.Namespace) { | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-23 14:57:59 +02:00
										 |  |  | 		if k.opts.ignoreEmptyService && svc.Spec.ClusterIP != api.ClusterIPNone { | 
					
						
							|  |  |  | 			// serve NXDOMAIN if no endpoint is able to answer | 
					
						
							|  |  |  | 			podsCount := 0 | 
					
						
							|  |  |  | 			for _, ep := range endpointsListFunc() { | 
					
						
							|  |  |  | 				for _, eps := range ep.Subsets { | 
					
						
							|  |  |  | 					podsCount = podsCount + len(eps.Addresses) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if podsCount == 0 { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 		// Endpoint query or headless service | 
					
						
							|  |  |  | 		if svc.Spec.ClusterIP == api.ClusterIPNone || r.endpoint != "" { | 
					
						
							| 
									
										
										
										
											2017-10-24 12:44:34 +01:00
										 |  |  | 			if endpointsList == nil { | 
					
						
							|  |  |  | 				endpointsList = endpointsListFunc() | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-10-17 21:30:54 -04:00
										 |  |  | 			for _, ep := range endpointsList { | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 				if ep.ObjectMeta.Name != svc.Name || ep.ObjectMeta.Namespace != svc.Namespace { | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 				for _, eps := range ep.Subsets { | 
					
						
							|  |  |  | 					for _, addr := range eps.Addresses { | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						// See comments in parse.go parseRequest about the endpoint handling. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if r.endpoint != "" { | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | 							if !match(r.endpoint, endpointHostname(addr, k.endpointNameMode)) { | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 								continue | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						for _, p := range eps.Ports { | 
					
						
							|  |  |  | 							if !(match(r.port, p.Name) && match(r.protocol, string(p.Protocol))) { | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 								continue | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-08-27 01:32:46 +01:00
										 |  |  | 							s := msg.Service{Host: addr.IP, Port: int(p.Port), TTL: k.ttl} | 
					
						
							| 
									
										
										
										
											2017-11-08 08:07:10 -05:00
										 |  |  | 							s.Key = strings.Join([]string{zonePath, Svc, svc.Namespace, svc.Name, endpointHostname(addr, k.endpointNameMode)}, "/") | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							err = nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							services = append(services, s) | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// External service | 
					
						
							| 
									
										
										
										
											2017-11-22 06:17:27 -05:00
										 |  |  | 		if svc.Spec.Type == api.ServiceTypeExternalName { | 
					
						
							| 
									
										
										
										
											2017-08-27 01:32:46 +01:00
										 |  |  | 			s := msg.Service{Key: strings.Join([]string{zonePath, Svc, svc.Namespace, svc.Name}, "/"), Host: svc.Spec.ExternalName, TTL: k.ttl} | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 			if t, _ := s.HostType(); t == dns.TypeCNAME { | 
					
						
							|  |  |  | 				s.Key = strings.Join([]string{zonePath, Svc, svc.Namespace, svc.Name}, "/") | 
					
						
							|  |  |  | 				services = append(services, s) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				err = nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-22 06:17:27 -05:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2017-01-05 10:09:59 -05:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-05-22 16:05:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 		// ClusterIP service | 
					
						
							|  |  |  | 		for _, p := range svc.Spec.Ports { | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | 			if !(match(r.port, p.Name) && match(r.protocol, string(p.Protocol))) { | 
					
						
							| 
									
										
										
										
											2016-07-14 14:50:14 -07:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-06-14 10:29:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 			err = nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-27 01:32:46 +01:00
										 |  |  | 			s := msg.Service{Host: svc.Spec.ClusterIP, Port: int(p.Port), TTL: k.ttl} | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 			s.Key = strings.Join([]string{zonePath, Svc, svc.Namespace, svc.Name}, "/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			services = append(services, s) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-14 14:50:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-23 07:19:41 +01:00
										 |  |  | 	return services, err | 
					
						
							| 
									
										
										
										
											2016-06-06 12:49:53 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | // match checks if a and b are equal taking wildcards into account. | 
					
						
							|  |  |  | func match(a, b string) bool { | 
					
						
							|  |  |  | 	if wildcard(a) { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if wildcard(b) { | 
					
						
							| 
									
										
										
										
											2017-01-15 03:12:28 -05:00
										 |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-05 12:29:43 -07:00
										 |  |  | 	return strings.EqualFold(a, b) | 
					
						
							| 
									
										
										
										
											2016-07-14 14:50:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 20:44:42 +01:00
										 |  |  | // wildcard checks whether s contains a wildcard value defined as "*" or "any". | 
					
						
							|  |  |  | func wildcard(s string) bool { | 
					
						
							|  |  |  | 	return s == "*" || s == "any" | 
					
						
							|  |  |  | } |