From 6ed88fab744bd3d8cc071153a4c78970798cf9e6 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Thu, 11 Oct 2018 21:59:50 +0100 Subject: [PATCH] Revert "use keys (#2167)" (#2188) This reverts commit 974ed086f25ad45a01947e276e2eb8aa73d007a3. --- plugin/federation/kubernetes_api_test.go | 27 ++-- plugin/kubernetes/controller.go | 90 +++++++----- plugin/kubernetes/handler_test.go | 171 ++++++++++++----------- plugin/kubernetes/kubernetes.go | 9 +- plugin/kubernetes/kubernetes_test.go | 115 +++++++++++---- plugin/kubernetes/local.go | 16 +-- plugin/kubernetes/ns.go | 21 +-- plugin/kubernetes/ns_test.go | 54 ++++--- plugin/kubernetes/object/endpoint.go | 4 +- plugin/kubernetes/object/service.go | 2 +- plugin/kubernetes/reverse.go | 36 ++--- plugin/kubernetes/reverse_test.go | 68 +++++---- plugin/kubernetes/xfr.go | 58 ++++---- 13 files changed, 380 insertions(+), 291 deletions(-) diff --git a/plugin/federation/kubernetes_api_test.go b/plugin/federation/kubernetes_api_test.go index 2fa274a6d..4b62605d1 100644 --- a/plugin/federation/kubernetes_api_test.go +++ b/plugin/federation/kubernetes_api_test.go @@ -16,24 +16,22 @@ type APIConnFederationTest struct { func (APIConnFederationTest) HasSynced() bool { return true } func (APIConnFederationTest) Run() { return } func (APIConnFederationTest) Stop() error { return nil } -func (APIConnFederationTest) SvcIndexReverse(string) *object.Service { return nil } -func (APIConnFederationTest) EpIndexReverse(string) *object.Endpoints { return nil } +func (APIConnFederationTest) SvcIndexReverse(string) []*object.Service { return nil } +func (APIConnFederationTest) EpIndexReverse(string) []*object.Endpoints { return nil } func (APIConnFederationTest) Modified() int64 { return 0 } func (APIConnFederationTest) SetWatchChan(watch.Chan) {} func (APIConnFederationTest) Watch(string) error { return nil } func (APIConnFederationTest) StopWatching(string) {} - func (APIConnFederationTest) PodIndex(string) []*object.Pod { return []*object.Pod{ {Namespace: "podns", PodIP: "10.240.0.1"}, // Remote IP set in test.ResponseWriter } } - -func (APIConnFederationTest) SvcIndex(key string) *object.Service { - svcs := map[string]*object.Service{ - "testns/svc1": { +func (APIConnFederationTest) SvcIndex(string) []*object.Service { + svcs := []*object.Service{ + { Name: "svc1", Namespace: "testns", ClusterIP: "10.0.0.1", @@ -41,12 +39,12 @@ func (APIConnFederationTest) SvcIndex(key string) *object.Service { {Name: "http", Protocol: "tcp", Port: 80}, }, }, - "testns/hdls1": { + { Name: "hdls1", Namespace: "testns", ClusterIP: api.ClusterIPNone, }, - "testns/external": { + { Name: "external", Namespace: "testns", ExternalName: "ext.interwebs.test", @@ -55,10 +53,9 @@ func (APIConnFederationTest) SvcIndex(key string) *object.Service { }, }, } - return svcs[key] + return svcs } - func (APIConnFederationTest) ServiceList() []*object.Service { svcs := []*object.Service{ { @@ -86,9 +83,9 @@ func (APIConnFederationTest) ServiceList() []*object.Service { return svcs } -func (APIConnFederationTest) EpIndex(key string) *object.Endpoints { - eps := map[string]*object.Endpoints{ - "testns/svc1": { +func (APIConnFederationTest) EpIndex(string) []*object.Endpoints { + eps := []*object.Endpoints{ + { Subsets: []object.EndpointSubset{ { Addresses: []object.EndpointAddress{ @@ -103,7 +100,7 @@ func (APIConnFederationTest) EpIndex(key string) *object.Endpoints { Namespace: "testns", }, } - return eps[key] + return eps } func (APIConnFederationTest) EndpointsList() []*object.Endpoints { diff --git a/plugin/kubernetes/controller.go b/plugin/kubernetes/controller.go index b1619a624..1c41b6ddf 100644 --- a/plugin/kubernetes/controller.go +++ b/plugin/kubernetes/controller.go @@ -20,19 +20,21 @@ import ( ) const ( - podIPIndex = "PodIP" - svcIPIndex = "ServiceIP" - epIPIndex = "EndpointsIP" + podIPIndex = "PodIP" + svcNameNamespaceIndex = "NameNamespace" + svcIPIndex = "ServiceIP" + epNameNamespaceIndex = "EndpointNameNamespace" + epIPIndex = "EndpointsIP" ) type dnsController interface { ServiceList() []*object.Service EndpointsList() []*object.Endpoints - SvcIndex(string) *object.Service - SvcIndexReverse(string) *object.Service + SvcIndex(string) []*object.Service + SvcIndexReverse(string) []*object.Service PodIndex(string) []*object.Pod - EpIndex(string) *object.Endpoints - EpIndexReverse(string) *object.Endpoints + EpIndex(string) []*object.Endpoints + EpIndexReverse(string) []*object.Endpoints GetNodeByName(string) (*api.Node, error) GetNamespaceByName(string) (*api.Namespace, error) @@ -116,7 +118,7 @@ func newdnsController(kubeClient kubernetes.Interface, opts dnsControlOpts) *dns &object.Service{}, opts.resyncPeriod, cache.ResourceEventHandlerFuncs{AddFunc: dns.Add, UpdateFunc: dns.Update, DeleteFunc: dns.Delete}, - cache.Indexers{svcIPIndex: svcIPIndexFunc}, + cache.Indexers{svcNameNamespaceIndex: svcNameNamespaceIndexFunc, svcIPIndex: svcIPIndexFunc}, object.ToService, ) @@ -143,7 +145,7 @@ func newdnsController(kubeClient kubernetes.Interface, opts dnsControlOpts) *dns &api.Endpoints{}, opts.resyncPeriod, cache.ResourceEventHandlerFuncs{AddFunc: dns.Add, UpdateFunc: dns.Update, DeleteFunc: dns.Delete}, - cache.Indexers{epIPIndex: epIPIndexFunc}, + cache.Indexers{epNameNamespaceIndex: epNameNamespaceIndexFunc, epIPIndex: epIPIndexFunc}, object.ToEndpoints) } @@ -173,6 +175,22 @@ func svcIPIndexFunc(obj interface{}) ([]string, error) { return []string{svc.ClusterIP}, nil } +func svcNameNamespaceIndexFunc(obj interface{}) ([]string, error) { + s, ok := obj.(*object.Service) + if !ok { + return nil, errObj + } + return []string{s.Index}, nil +} + +func epNameNamespaceIndexFunc(obj interface{}) ([]string, error) { + s, ok := obj.(*object.Endpoints) + if !ok { + return nil, errObj + } + return []string{s.Index}, nil +} + func epIPIndexFunc(obj interface{}) ([]string, error) { ep, ok := obj.(*object.Endpoints) if !ok { @@ -341,9 +359,6 @@ func (dns *dnsControl) EndpointsList() (eps []*object.Endpoints) { } func (dns *dnsControl) PodIndex(ip string) (pods []*object.Pod) { - if dns.podLister == nil { - return nil - } os, err := dns.podLister.ByIndex(podIPIndex, ip) if err != nil { return nil @@ -353,24 +368,27 @@ func (dns *dnsControl) PodIndex(ip string) (pods []*object.Pod) { if !ok { continue } - return []*object.Pod{p} + pods = append(pods, p) } - return nil + return pods } -func (dns *dnsControl) SvcIndex(key string) *object.Service { - o, _, err := dns.svcLister.GetByKey(key) +func (dns *dnsControl) SvcIndex(idx string) (svcs []*object.Service) { + os, err := dns.svcLister.ByIndex(svcNameNamespaceIndex, idx) if err != nil { return nil } - s, ok := o.(*object.Service) - if !ok { - return nil + for _, o := range os { + s, ok := o.(*object.Service) + if !ok { + continue + } + svcs = append(svcs, s) } - return s + return svcs } -func (dns *dnsControl) SvcIndexReverse(ip string) *object.Service { +func (dns *dnsControl) SvcIndexReverse(ip string) (svcs []*object.Service) { os, err := dns.svcLister.ByIndex(svcIPIndex, ip) if err != nil { return nil @@ -381,27 +399,27 @@ func (dns *dnsControl) SvcIndexReverse(ip string) *object.Service { if !ok { continue } - return s + svcs = append(svcs, s) } - return nil + return svcs } -func (dns *dnsControl) EpIndex(key string) (ep *object.Endpoints) { - o, _, err := dns.epLister.GetByKey(key) +func (dns *dnsControl) EpIndex(idx string) (ep []*object.Endpoints) { + os, err := dns.epLister.ByIndex(epNameNamespaceIndex, idx) if err != nil { return nil } - e, ok := o.(*object.Endpoints) - if !ok { - return nil + for _, o := range os { + e, ok := o.(*object.Endpoints) + if !ok { + continue + } + ep = append(ep, e) } - return e + return ep } -func (dns *dnsControl) EpIndexReverse(ip string) (ep *object.Endpoints) { - if dns.epLister == nil { - return nil - } +func (dns *dnsControl) EpIndexReverse(ip string) (ep []*object.Endpoints) { os, err := dns.epLister.ByIndex(epIPIndex, ip) if err != nil { return nil @@ -411,9 +429,9 @@ func (dns *dnsControl) EpIndexReverse(ip string) (ep *object.Endpoints) { if !ok { continue } - return e + ep = append(ep, e) } - return nil + return ep } // GetNodeByName return the node by name. If nothing is found an error is @@ -432,7 +450,7 @@ func (dns *dnsControl) GetNamespaceByName(name string) (*api.Namespace, error) { if !ok { continue } - if name == ns.GetName() { + if name == ns.ObjectMeta.Name { return ns, nil } } diff --git a/plugin/kubernetes/handler_test.go b/plugin/kubernetes/handler_test.go index b3353af1b..604f00fab 100644 --- a/plugin/kubernetes/handler_test.go +++ b/plugin/kubernetes/handler_test.go @@ -379,15 +379,15 @@ func TestServeDNS(t *testing.T) { type APIConnServeTest struct{} -func (APIConnServeTest) HasSynced() bool { return true } -func (APIConnServeTest) Run() { return } -func (APIConnServeTest) Stop() error { return nil } -func (APIConnServeTest) EpIndexReverse(string) *object.Endpoints { return nil } -func (APIConnServeTest) SvcIndexReverse(string) *object.Service { return nil } -func (APIConnServeTest) Modified() int64 { return time.Now().Unix() } -func (APIConnServeTest) SetWatchChan(watch.Chan) {} -func (APIConnServeTest) Watch(string) error { return nil } -func (APIConnServeTest) StopWatching(string) {} +func (APIConnServeTest) HasSynced() bool { return true } +func (APIConnServeTest) Run() { return } +func (APIConnServeTest) Stop() error { return nil } +func (APIConnServeTest) EpIndexReverse(string) []*object.Endpoints { return nil } +func (APIConnServeTest) SvcIndexReverse(string) []*object.Service { return nil } +func (APIConnServeTest) Modified() int64 { return time.Now().Unix() } +func (APIConnServeTest) SetWatchChan(watch.Chan) {} +func (APIConnServeTest) Watch(string) error { return nil } +func (APIConnServeTest) StopWatching(string) {} func (APIConnServeTest) PodIndex(string) []*object.Pod { a := []*object.Pod{ @@ -396,90 +396,103 @@ func (APIConnServeTest) PodIndex(string) []*object.Pod { return a } -var svcIndex = map[string]*object.Service{ - "testns/svc1": { - Name: "svc1", - Namespace: "testns", - Type: api.ServiceTypeClusterIP, - ClusterIP: "10.0.0.1", - Ports: []api.ServicePort{ - {Name: "http", Protocol: "tcp", Port: 80}, +var svcIndex = map[string][]*object.Service{ + "svc1.testns": { + { + Name: "svc1", + Namespace: "testns", + Type: api.ServiceTypeClusterIP, + ClusterIP: "10.0.0.1", + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, }, }, - "testns/svcempty": { - Name: "svcempty", - Namespace: "testns", - Type: api.ServiceTypeClusterIP, - ClusterIP: "10.0.0.1", - Ports: []api.ServicePort{ - {Name: "http", Protocol: "tcp", Port: 80}, + "svcempty.testns": { + { + Name: "svcempty", + Namespace: "testns", + Type: api.ServiceTypeClusterIP, + ClusterIP: "10.0.0.1", + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, }, }, - "testns/svc6": { - Name: "svc6", - Namespace: "testns", - Type: api.ServiceTypeClusterIP, - ClusterIP: "1234:abcd::1", - Ports: []api.ServicePort{ - {Name: "http", Protocol: "tcp", Port: 80}, + "svc6.testns": { + { + Name: "svc6", + Namespace: "testns", + Type: api.ServiceTypeClusterIP, + ClusterIP: "1234:abcd::1", + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, }, }, - "testns/hdls1": { - Name: "hdls1", - Namespace: "testns", - Type: api.ServiceTypeClusterIP, - ClusterIP: api.ClusterIPNone, - }, - "testns/external": { - - Name: "external", - Namespace: "testns", - ExternalName: "ext.interwebs.test", - Type: api.ServiceTypeExternalName, - Ports: []api.ServicePort{ - {Name: "http", Protocol: "tcp", Port: 80}, + "hdls1.testns": { + { + Name: "hdls1", + Namespace: "testns", + Type: api.ServiceTypeClusterIP, + ClusterIP: api.ClusterIPNone, }, }, - "testns/external-to-service": { - Name: "external-to-service", - Namespace: "testns", - ExternalName: "svc1.testns.svc.cluster.local.", - Type: api.ServiceTypeExternalName, - Ports: []api.ServicePort{ - {Name: "http", Protocol: "tcp", Port: 80}, + "external.testns": { + { + Name: "external", + Namespace: "testns", + ExternalName: "ext.interwebs.test", + Type: api.ServiceTypeExternalName, + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, }, }, - "testns/hdlsprtls": { - Name: "hdlsprtls", - Namespace: "testns", - Type: api.ServiceTypeClusterIP, - ClusterIP: api.ClusterIPNone, + "external-to-service.testns": { + { + Name: "external-to-service", + Namespace: "testns", + ExternalName: "svc1.testns.svc.cluster.local.", + Type: api.ServiceTypeExternalName, + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, + }, }, - "unexposedns/svc1": { - Name: "svc1", - Namespace: "unexposedns", - Type: api.ServiceTypeClusterIP, - ClusterIP: "10.0.0.2", - Ports: []api.ServicePort{ - {Name: "http", Protocol: "tcp", Port: 80}, + "hdlsprtls.testns": { + { + Name: "hdlsprtls", + Namespace: "testns", + Type: api.ServiceTypeClusterIP, + ClusterIP: api.ClusterIPNone, + }, + }, + "svc1.unexposedns": { + { + Name: "svc1", + Namespace: "unexposedns", + Type: api.ServiceTypeClusterIP, + ClusterIP: "10.0.0.2", + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, }, }, } -func (APIConnServeTest) SvcIndex(s string) *object.Service { - return svcIndex[s] -} +func (APIConnServeTest) SvcIndex(s string) []*object.Service { return svcIndex[s] } func (APIConnServeTest) ServiceList() []*object.Service { var svcs []*object.Service for _, svc := range svcIndex { - svcs = append(svcs, svc) + svcs = append(svcs, svc...) } return svcs } -var epsIndex = map[string]*object.Endpoints{ - "testns/svc1": { +var epsIndex = map[string][]*object.Endpoints{ + "svc1.testns": {{ Subsets: []object.EndpointSubset{ { Addresses: []object.EndpointAddress{ @@ -492,8 +505,8 @@ var epsIndex = map[string]*object.Endpoints{ }, Name: "svc1", Namespace: "testns", - }, - "testns/svcempty": { + }}, + "svcempty.testns": {{ Subsets: []object.EndpointSubset{ { Addresses: nil, @@ -504,8 +517,8 @@ var epsIndex = map[string]*object.Endpoints{ }, Name: "svcempty", Namespace: "testns", - }, - "testns/hdls1": { + }}, + "hdls1.testns": {{ Subsets: []object.EndpointSubset{ { Addresses: []object.EndpointAddress{ @@ -523,8 +536,8 @@ var epsIndex = map[string]*object.Endpoints{ }, Name: "hdls1", Namespace: "testns", - }, - "testns/hdlsprtls": { + }}, + "hdlsprtls.testns": {{ Subsets: []object.EndpointSubset{ { Addresses: []object.EndpointAddress{ @@ -535,17 +548,17 @@ var epsIndex = map[string]*object.Endpoints{ }, Name: "hdlsprtls", Namespace: "testns", - }, + }}, } -func (APIConnServeTest) EpIndex(s string) *object.Endpoints { +func (APIConnServeTest) EpIndex(s string) []*object.Endpoints { return epsIndex[s] } func (APIConnServeTest) EndpointsList() []*object.Endpoints { var eps []*object.Endpoints for _, ep := range epsIndex { - eps = append(eps, ep) + eps = append(eps, ep...) } return eps } diff --git a/plugin/kubernetes/kubernetes.go b/plugin/kubernetes/kubernetes.go index 8ba21a70e..81cf19492 100644 --- a/plugin/kubernetes/kubernetes.go +++ b/plugin/kubernetes/kubernetes.go @@ -444,12 +444,9 @@ func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg. serviceList = k.APIConn.ServiceList() endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EndpointsList() } } else { - key := object.ServiceKey(r.namespace, r.service) - s := k.APIConn.SvcIndex(key) - if s != nil { - serviceList = append(serviceList, s) - } - endpointsListFunc = func() []*object.Endpoints { return []*object.Endpoints{k.APIConn.EpIndex(key)} } + idx := object.ServiceKey(r.service, r.namespace) + serviceList = k.APIConn.SvcIndex(idx) + endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EpIndex(idx) } } for _, svc := range serviceList { diff --git a/plugin/kubernetes/kubernetes_test.go b/plugin/kubernetes/kubernetes_test.go index b8274d01b..f35c9cd2c 100644 --- a/plugin/kubernetes/kubernetes_test.go +++ b/plugin/kubernetes/kubernetes_test.go @@ -59,24 +59,43 @@ func TestEndpointHostname(t *testing.T) { type APIConnServiceTest struct{} -func (APIConnServiceTest) HasSynced() bool { return true } -func (APIConnServiceTest) Run() { return } -func (APIConnServiceTest) Stop() error { return nil } -func (APIConnServiceTest) PodIndex(string) []*object.Pod { return nil } -func (APIConnServiceTest) SvcIndexReverse(string) *object.Service { return nil } -func (APIConnServiceTest) EpIndexReverse(string) *object.Endpoints { return nil } -func (APIConnServiceTest) Modified() int64 { return 0 } -func (APIConnServiceTest) SetWatchChan(watch.Chan) {} -func (APIConnServiceTest) Watch(string) error { return nil } -func (APIConnServiceTest) StopWatching(string) {} +func (APIConnServiceTest) HasSynced() bool { return true } +func (APIConnServiceTest) Run() { return } +func (APIConnServiceTest) Stop() error { return nil } +func (APIConnServiceTest) PodIndex(string) []*object.Pod { return nil } +func (APIConnServiceTest) SvcIndexReverse(string) []*object.Service { return nil } +func (APIConnServiceTest) EpIndexReverse(string) []*object.Endpoints { return nil } +func (APIConnServiceTest) Modified() int64 { return 0 } +func (APIConnServiceTest) SetWatchChan(watch.Chan) {} +func (APIConnServiceTest) Watch(string) error { return nil } +func (APIConnServiceTest) StopWatching(string) {} -func (a APIConnServiceTest) SvcIndex(key string) *object.Service { - for _, s := range a.ServiceList() { - if object.ServiceKey(s.Namespace, s.Name) == key { - return s - } +func (APIConnServiceTest) SvcIndex(string) []*object.Service { + svcs := []*object.Service{ + { + Name: "svc1", + Namespace: "testns", + ClusterIP: "10.0.0.1", + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, + }, + { + Name: "hdls1", + Namespace: "testns", + ClusterIP: api.ClusterIPNone, + }, + { + Name: "external", + Namespace: "testns", + ExternalName: "coredns.io", + Type: api.ServiceTypeExternalName, + Ports: []api.ServicePort{ + {Name: "http", Protocol: "tcp", Port: 80}, + }, + }, } - return nil + return svcs } func (APIConnServiceTest) ServiceList() []*object.Service { @@ -107,13 +126,61 @@ func (APIConnServiceTest) ServiceList() []*object.Service { return svcs } -func (a APIConnServiceTest) EpIndex(key string) *object.Endpoints { - for _, e := range a.EndpointsList() { - if object.EndpointsKey(e.Namespace, e.Name) == key { - return e - } +func (APIConnServiceTest) EpIndex(string) []*object.Endpoints { + eps := []*object.Endpoints{ + { + Subsets: []object.EndpointSubset{ + { + Addresses: []object.EndpointAddress{ + {IP: "172.0.0.1", Hostname: "ep1a"}, + }, + Ports: []object.EndpointPort{ + {Port: 80, Protocol: "tcp", Name: "http"}, + }, + }, + }, + Name: "svc1", + Namespace: "testns", + }, + { + Subsets: []object.EndpointSubset{ + { + Addresses: []object.EndpointAddress{ + {IP: "172.0.0.2"}, + }, + Ports: []object.EndpointPort{ + {Port: 80, Protocol: "tcp", Name: "http"}, + }, + }, + }, + Name: "hdls1", + Namespace: "testns", + }, + { + Subsets: []object.EndpointSubset{ + { + Addresses: []object.EndpointAddress{ + {IP: "172.0.0.3"}, + }, + Ports: []object.EndpointPort{ + {Port: 80, Protocol: "tcp", Name: "http"}, + }, + }, + }, + Name: "hdls1", + Namespace: "testns", + }, + { + Subsets: []object.EndpointSubset{ + { + Addresses: []object.EndpointAddress{ + {IP: "10.9.8.7", NodeName: "test.node.foo.bar"}, + }, + }, + }, + }, } - return nil + return eps } func (APIConnServiceTest) EndpointsList() []*object.Endpoints { @@ -157,7 +224,7 @@ func (APIConnServiceTest) EndpointsList() []*object.Endpoints { }, }, }, - Name: "hdls2", + Name: "hdls1", Namespace: "testns", }, { @@ -168,8 +235,6 @@ func (APIConnServiceTest) EndpointsList() []*object.Endpoints { }, }, }, - Name: "testsvc", - Namespace: "testns", }, } return eps diff --git a/plugin/kubernetes/local.go b/plugin/kubernetes/local.go index 7a85de1bf..e15fec497 100644 --- a/plugin/kubernetes/local.go +++ b/plugin/kubernetes/local.go @@ -28,18 +28,14 @@ func (k *Kubernetes) localNodeName() string { } // Find endpoint matching localIP - ep := k.APIConn.EpIndexReverse(localIP.String()) - if ep == nil { - return "" - } - - for _, eps := range ep.Subsets { - for _, addr := range eps.Addresses { - if localIP.Equal(net.ParseIP(addr.IP)) { - return addr.NodeName + for _, ep := range k.APIConn.EpIndexReverse(localIP.String()) { + for _, eps := range ep.Subsets { + for _, addr := range eps.Addresses { + if localIP.Equal(net.ParseIP(addr.IP)) { + return addr.NodeName + } } } } - return "" } diff --git a/plugin/kubernetes/ns.go b/plugin/kubernetes/ns.go index 722dc9ef4..2ccb51ef3 100644 --- a/plugin/kubernetes/ns.go +++ b/plugin/kubernetes/ns.go @@ -4,7 +4,6 @@ import ( "net" "strings" - "github.com/coredns/coredns/plugin/kubernetes/object" "github.com/miekg/dns" api "k8s.io/api/core/v1" ) @@ -23,9 +22,8 @@ func (k *Kubernetes) nsAddr() *dns.A { localIP := k.interfaceAddrsFunc() rr.A = localIP - ep := k.APIConn.EpIndexReverse(localIP.String()) - if ep != nil { - FindEndpoint: +FindEndpoint: + for _, ep := range k.APIConn.EpIndexReverse(localIP.String()) { for _, eps := range ep.Subsets { for _, addr := range eps.Addresses { if localIP.Equal(net.ParseIP(addr.IP)) { @@ -43,12 +41,15 @@ func (k *Kubernetes) nsAddr() *dns.A { return rr } - svc := k.APIConn.SvcIndex(object.ServiceKey(svcNamespace, svcName)) - if svc != nil { - if svc.ClusterIP == api.ClusterIPNone { - rr.A = localIP - } else { - rr.A = net.ParseIP(svc.ClusterIP) +FindService: + for _, svc := range k.APIConn.ServiceList() { + if svcName == svc.Name && svcNamespace == svc.Namespace { + if svc.ClusterIP == api.ClusterIPNone { + rr.A = localIP + } else { + rr.A = net.ParseIP(svc.ClusterIP) + } + break FindService } } diff --git a/plugin/kubernetes/ns_test.go b/plugin/kubernetes/ns_test.go index c9025288b..fd781bc14 100644 --- a/plugin/kubernetes/ns_test.go +++ b/plugin/kubernetes/ns_test.go @@ -11,26 +11,18 @@ import ( type APIConnTest struct{} -func (APIConnTest) HasSynced() bool { return true } -func (APIConnTest) Run() { return } -func (APIConnTest) Stop() error { return nil } -func (APIConnTest) PodIndex(string) []*object.Pod { return nil } -func (APIConnTest) SvcIndexReverse(string) *object.Service { return nil } -func (APIConnTest) EpIndex(string) *object.Endpoints { return nil } -func (APIConnTest) EndpointsList() []*object.Endpoints { return nil } -func (APIConnTest) Modified() int64 { return 0 } -func (APIConnTest) SetWatchChan(watch.Chan) {} -func (APIConnTest) Watch(string) error { return nil } -func (APIConnTest) StopWatching(string) {} - -func (a APIConnTest) SvcIndex(key string) *object.Service { - for _, s := range a.ServiceList() { - if object.ServiceKey(s.Namespace, s.Name) == key { - return s - } - } - return nil -} +func (APIConnTest) HasSynced() bool { return true } +func (APIConnTest) Run() { return } +func (APIConnTest) Stop() error { return nil } +func (APIConnTest) PodIndex(string) []*object.Pod { return nil } +func (APIConnTest) SvcIndex(string) []*object.Service { return nil } +func (APIConnTest) SvcIndexReverse(string) []*object.Service { return nil } +func (APIConnTest) EpIndex(string) []*object.Endpoints { return nil } +func (APIConnTest) EndpointsList() []*object.Endpoints { return nil } +func (APIConnTest) Modified() int64 { return 0 } +func (APIConnTest) SetWatchChan(watch.Chan) {} +func (APIConnTest) Watch(string) error { return nil } +func (APIConnTest) StopWatching(string) {} func (APIConnTest) ServiceList() []*object.Service { svcs := []*object.Service{ @@ -43,21 +35,23 @@ func (APIConnTest) ServiceList() []*object.Service { return svcs } -func (APIConnTest) EpIndexReverse(string) *object.Endpoints { - eps := object.Endpoints{ - Subsets: []object.EndpointSubset{ - { - Addresses: []object.EndpointAddress{ - { - IP: "127.0.0.1", +func (APIConnTest) EpIndexReverse(string) []*object.Endpoints { + eps := []*object.Endpoints{ + { + Subsets: []object.EndpointSubset{ + { + Addresses: []object.EndpointAddress{ + { + IP: "127.0.0.1", + }, }, }, }, + Name: "dns-service", + Namespace: "kube-system", }, - Name: "dns-service", - Namespace: "kube-system", } - return &eps + return eps } func (APIConnTest) GetNodeByName(name string) (*api.Node, error) { return &api.Node{}, nil } diff --git a/plugin/kubernetes/object/endpoint.go b/plugin/kubernetes/object/endpoint.go index a391c6426..b8531f050 100644 --- a/plugin/kubernetes/object/endpoint.go +++ b/plugin/kubernetes/object/endpoint.go @@ -40,7 +40,7 @@ type EndpointPort struct { } // EndpointsKey return a string using for the index. -func EndpointsKey(namespace, name string) string { return namespace + "/" + name } +func EndpointsKey(name, namespace string) string { return name + "." + namespace } // ToEndpoints converts an api.Service to a *Service. func ToEndpoints(obj interface{}) interface{} { @@ -61,7 +61,7 @@ func ToEndpoints(obj interface{}) interface{} { Addresses: make([]EndpointAddress, len(eps.Addresses)), } if len(eps.Ports) == 0 { - // Add sentinel if there are no ports. + // Add sentinal if there are no ports. sub.Ports = []EndpointPort{{Port: -1}} } else { sub.Ports = make([]EndpointPort, len(eps.Ports)) diff --git a/plugin/kubernetes/object/service.go b/plugin/kubernetes/object/service.go index 1c716b28b..be010e96b 100644 --- a/plugin/kubernetes/object/service.go +++ b/plugin/kubernetes/object/service.go @@ -20,7 +20,7 @@ type Service struct { } // ServiceKey return a string using for the index. -func ServiceKey(namespace, name string) string { return namespace + "/" + name } +func ServiceKey(name, namespace string) string { return name + "." + namespace } // ToService converts an api.Service to a *Service. func ToService(obj interface{}) interface{} { diff --git a/plugin/kubernetes/reverse.go b/plugin/kubernetes/reverse.go index 1e060283c..5873bcbc8 100644 --- a/plugin/kubernetes/reverse.go +++ b/plugin/kubernetes/reverse.go @@ -18,35 +18,35 @@ func (k *Kubernetes) Reverse(state request.Request, exact bool, opt plugin.Optio return nil, e } - record := k.serviceRecordForIP(ip, state.Name()) - if record == nil { - return nil, errNoItems + records := k.serviceRecordForIP(ip, state.Name()) + if len(records) == 0 { + return records, errNoItems } - return []msg.Service{*record}, nil + return records, nil } // serviceRecordForIP gets a service record with a cluster ip matching the ip argument // If a service cluster ip does not match, it checks all endpoints -func (k *Kubernetes) serviceRecordForIP(ip, name string) *msg.Service { +func (k *Kubernetes) serviceRecordForIP(ip, name string) []msg.Service { // First check services with cluster ips - service := k.APIConn.SvcIndexReverse(ip) - if service != nil { + for _, service := range k.APIConn.SvcIndexReverse(ip) { if len(k.Namespaces) > 0 && !k.namespaceExposed(service.Namespace) { - return nil + continue } domain := strings.Join([]string{service.Name, service.Namespace, Svc, k.primaryZone()}, ".") - return &msg.Service{Host: domain, TTL: k.ttl} + return []msg.Service{{Host: domain, TTL: k.ttl}} } // If no cluster ips match, search endpoints - ep := k.APIConn.EpIndexReverse(ip) - if ep == nil || len(k.Namespaces) > 0 && !k.namespaceExposed(ep.Namespace) { - return nil - } - for _, eps := range ep.Subsets { - for _, addr := range eps.Addresses { - if addr.IP == ip { - domain := strings.Join([]string{endpointHostname(addr, k.endpointNameMode), ep.Name, ep.Namespace, Svc, k.primaryZone()}, ".") - return &msg.Service{Host: domain, TTL: k.ttl} + for _, ep := range k.APIConn.EpIndexReverse(ip) { + if len(k.Namespaces) > 0 && !k.namespaceExposed(ep.Namespace) { + continue + } + for _, eps := range ep.Subsets { + for _, addr := range eps.Addresses { + if addr.IP == ip { + domain := strings.Join([]string{endpointHostname(addr, k.endpointNameMode), ep.Name, ep.Namespace, Svc, k.primaryZone()}, ".") + return []msg.Service{{Host: domain, TTL: k.ttl}} + } } } } diff --git a/plugin/kubernetes/reverse_test.go b/plugin/kubernetes/reverse_test.go index 20c8496c7..a706b7585 100644 --- a/plugin/kubernetes/reverse_test.go +++ b/plugin/kubernetes/reverse_test.go @@ -20,7 +20,7 @@ func (APIConnReverseTest) HasSynced() bool { return true } func (APIConnReverseTest) Run() { return } func (APIConnReverseTest) Stop() error { return nil } func (APIConnReverseTest) PodIndex(string) []*object.Pod { return nil } -func (APIConnReverseTest) EpIndex(string) *object.Endpoints { return nil } +func (APIConnReverseTest) EpIndex(string) []*object.Endpoints { return nil } func (APIConnReverseTest) EndpointsList() []*object.Endpoints { return nil } func (APIConnReverseTest) ServiceList() []*object.Service { return nil } func (APIConnReverseTest) Modified() int64 { return 0 } @@ -28,34 +28,38 @@ func (APIConnReverseTest) SetWatchChan(watch.Chan) {} func (APIConnReverseTest) Watch(string) error { return nil } func (APIConnReverseTest) StopWatching(string) {} -func (APIConnReverseTest) SvcIndex(key string) *object.Service { - if key != "testns/svc1" { +func (APIConnReverseTest) SvcIndex(svc string) []*object.Service { + if svc != "svc1.testns" { return nil } - svc := object.Service{ - Name: "svc1", - Namespace: "testns", - ClusterIP: "192.168.1.100", - Ports: []api.ServicePort{{Name: "http", Protocol: "tcp", Port: 80}}, + svcs := []*object.Service{ + { + Name: "svc1", + Namespace: "testns", + ClusterIP: "192.168.1.100", + Ports: []api.ServicePort{{Name: "http", Protocol: "tcp", Port: 80}}, + }, } - return &svc + return svcs } -func (APIConnReverseTest) SvcIndexReverse(ip string) *object.Service { +func (APIConnReverseTest) SvcIndexReverse(ip string) []*object.Service { if ip != "192.168.1.100" { return nil } - svc := object.Service{ - Name: "svc1", - Namespace: "testns", - ClusterIP: "192.168.1.100", - Ports: []api.ServicePort{{Name: "http", Protocol: "tcp", Port: 80}}, + svcs := []*object.Service{ + { + Name: "svc1", + Namespace: "testns", + ClusterIP: "192.168.1.100", + Ports: []api.ServicePort{{Name: "http", Protocol: "tcp", Port: 80}}, + }, } - return &svc + return svcs } -func (APIConnReverseTest) EpIndexReverse(ip string) *object.Endpoints { +func (APIConnReverseTest) EpIndexReverse(ip string) []*object.Endpoints { switch ip { case "10.0.0.100": case "1234:abcd::1": @@ -64,24 +68,26 @@ func (APIConnReverseTest) EpIndexReverse(ip string) *object.Endpoints { default: return nil } - ep := object.Endpoints{ - Subsets: []object.EndpointSubset{ - { - Addresses: []object.EndpointAddress{ - {IP: "10.0.0.100", Hostname: "ep1a"}, - {IP: "1234:abcd::1", Hostname: "ep1b"}, - {IP: "fd00:77:30::a", Hostname: "ip6svc1ex"}, - {IP: "fd00:77:30::2:9ba6", Hostname: "ip6svc1in"}, - }, - Ports: []object.EndpointPort{ - {Port: 80, Protocol: "tcp", Name: "http"}, + eps := []*object.Endpoints{ + { + Subsets: []object.EndpointSubset{ + { + Addresses: []object.EndpointAddress{ + {IP: "10.0.0.100", Hostname: "ep1a"}, + {IP: "1234:abcd::1", Hostname: "ep1b"}, + {IP: "fd00:77:30::a", Hostname: "ip6svc1ex"}, + {IP: "fd00:77:30::2:9ba6", Hostname: "ip6svc1in"}, + }, + Ports: []object.EndpointPort{ + {Port: 80, Protocol: "tcp", Name: "http"}, + }, }, }, + Name: "svc1", + Namespace: "testns", }, - Name: "svc1", - Namespace: "testns", } - return &ep + return eps } func (APIConnReverseTest) GetNodeByName(name string) (*api.Node, error) { diff --git a/plugin/kubernetes/xfr.go b/plugin/kubernetes/xfr.go index b76e1def9..eaf554c6a 100644 --- a/plugin/kubernetes/xfr.go +++ b/plugin/kubernetes/xfr.go @@ -9,7 +9,6 @@ import ( "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/etcd/msg" "github.com/coredns/coredns/request" - "k8s.io/client-go/tools/cache" "github.com/miekg/dns" api "k8s.io/api/core/v1" @@ -115,36 +114,39 @@ func (k *Kubernetes) transfer(c chan dns.RR, zone string) { continue } - key, err := cache.MetaNamespaceKeyFunc(svc) - if err != nil { - return - } - ep := k.APIConn.EpIndex(key) - for _, eps := range ep.Subsets { - srvWeight := calcSRVWeight(len(eps.Addresses)) - for _, addr := range eps.Addresses { - s := msg.Service{Host: addr.IP, TTL: k.ttl} - s.Key = strings.Join(svcBase, "/") - // We don't need to change the msg.Service host from IP to Name yet - // so disregard the return value here - emitAddressRecord(c, s) + endpointsList := k.APIConn.EpIndex(svc.Name + "." + svc.Namespace) - s.Key = strings.Join(append(svcBase, endpointHostname(addr, k.endpointNameMode)), "/") - // Change host from IP to Name for SRV records - host := emitAddressRecord(c, s) - s.Host = host + for _, ep := range endpointsList { + if ep.Name != svc.Name || ep.Namespace != svc.Namespace { + continue + } - for _, p := range eps.Ports { - // As per spec unnamed ports do not have a srv record - // https://github.com/kubernetes/dns/blob/master/docs/specification.md#232---srv-records - if p.Name == "" { - continue + for _, eps := range ep.Subsets { + srvWeight := calcSRVWeight(len(eps.Addresses)) + for _, addr := range eps.Addresses { + s := msg.Service{Host: addr.IP, TTL: k.ttl} + s.Key = strings.Join(svcBase, "/") + // We don't need to change the msg.Service host from IP to Name yet + // so disregard the return value here + emitAddressRecord(c, s) + + s.Key = strings.Join(append(svcBase, endpointHostname(addr, k.endpointNameMode)), "/") + // Change host from IP to Name for SRV records + host := emitAddressRecord(c, s) + s.Host = host + + for _, p := range eps.Ports { + // As per spec unnamed ports do not have a srv record + // https://github.com/kubernetes/dns/blob/master/docs/specification.md#232---srv-records + if p.Name == "" { + continue + } + + s.Port = int(p.Port) + + s.Key = strings.Join(append(svcBase, strings.ToLower("_"+string(p.Protocol)), strings.ToLower("_"+string(p.Name))), "/") + c <- s.NewSRV(msg.Domain(s.Key), srvWeight) } - - s.Port = int(p.Port) - - s.Key = strings.Join(append(svcBase, strings.ToLower("_"+string(p.Protocol)), strings.ToLower("_"+string(p.Name))), "/") - c <- s.NewSRV(msg.Domain(s.Key), srvWeight) } } }