Revert "use keys (#2167)" (#2188)

This reverts commit 974ed086f2.
This commit is contained in:
Miek Gieben 2018-10-11 21:59:50 +01:00 committed by Chris O'Haver
parent c8fb66f8cc
commit 6ed88fab74
13 changed files with 380 additions and 291 deletions

View file

@ -16,24 +16,22 @@ type APIConnFederationTest struct {
func (APIConnFederationTest) HasSynced() bool { return true } func (APIConnFederationTest) HasSynced() bool { return true }
func (APIConnFederationTest) Run() { return } func (APIConnFederationTest) Run() { return }
func (APIConnFederationTest) Stop() error { return nil } func (APIConnFederationTest) Stop() error { return nil }
func (APIConnFederationTest) SvcIndexReverse(string) *object.Service { return nil } func (APIConnFederationTest) SvcIndexReverse(string) []*object.Service { return nil }
func (APIConnFederationTest) EpIndexReverse(string) *object.Endpoints { return nil } func (APIConnFederationTest) EpIndexReverse(string) []*object.Endpoints { return nil }
func (APIConnFederationTest) Modified() int64 { return 0 } func (APIConnFederationTest) Modified() int64 { return 0 }
func (APIConnFederationTest) SetWatchChan(watch.Chan) {} func (APIConnFederationTest) SetWatchChan(watch.Chan) {}
func (APIConnFederationTest) Watch(string) error { return nil } func (APIConnFederationTest) Watch(string) error { return nil }
func (APIConnFederationTest) StopWatching(string) {} func (APIConnFederationTest) StopWatching(string) {}
func (APIConnFederationTest) PodIndex(string) []*object.Pod { func (APIConnFederationTest) PodIndex(string) []*object.Pod {
return []*object.Pod{ return []*object.Pod{
{Namespace: "podns", PodIP: "10.240.0.1"}, // Remote IP set in test.ResponseWriter {Namespace: "podns", PodIP: "10.240.0.1"}, // Remote IP set in test.ResponseWriter
} }
} }
func (APIConnFederationTest) SvcIndex(string) []*object.Service {
func (APIConnFederationTest) SvcIndex(key string) *object.Service { svcs := []*object.Service{
svcs := map[string]*object.Service{ {
"testns/svc1": {
Name: "svc1", Name: "svc1",
Namespace: "testns", Namespace: "testns",
ClusterIP: "10.0.0.1", ClusterIP: "10.0.0.1",
@ -41,12 +39,12 @@ func (APIConnFederationTest) SvcIndex(key string) *object.Service {
{Name: "http", Protocol: "tcp", Port: 80}, {Name: "http", Protocol: "tcp", Port: 80},
}, },
}, },
"testns/hdls1": { {
Name: "hdls1", Name: "hdls1",
Namespace: "testns", Namespace: "testns",
ClusterIP: api.ClusterIPNone, ClusterIP: api.ClusterIPNone,
}, },
"testns/external": { {
Name: "external", Name: "external",
Namespace: "testns", Namespace: "testns",
ExternalName: "ext.interwebs.test", 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 { func (APIConnFederationTest) ServiceList() []*object.Service {
svcs := []*object.Service{ svcs := []*object.Service{
{ {
@ -86,9 +83,9 @@ func (APIConnFederationTest) ServiceList() []*object.Service {
return svcs return svcs
} }
func (APIConnFederationTest) EpIndex(key string) *object.Endpoints { func (APIConnFederationTest) EpIndex(string) []*object.Endpoints {
eps := map[string]*object.Endpoints{ eps := []*object.Endpoints{
"testns/svc1": { {
Subsets: []object.EndpointSubset{ Subsets: []object.EndpointSubset{
{ {
Addresses: []object.EndpointAddress{ Addresses: []object.EndpointAddress{
@ -103,7 +100,7 @@ func (APIConnFederationTest) EpIndex(key string) *object.Endpoints {
Namespace: "testns", Namespace: "testns",
}, },
} }
return eps[key] return eps
} }
func (APIConnFederationTest) EndpointsList() []*object.Endpoints { func (APIConnFederationTest) EndpointsList() []*object.Endpoints {

View file

@ -20,19 +20,21 @@ import (
) )
const ( const (
podIPIndex = "PodIP" podIPIndex = "PodIP"
svcIPIndex = "ServiceIP" svcNameNamespaceIndex = "NameNamespace"
epIPIndex = "EndpointsIP" svcIPIndex = "ServiceIP"
epNameNamespaceIndex = "EndpointNameNamespace"
epIPIndex = "EndpointsIP"
) )
type dnsController interface { type dnsController interface {
ServiceList() []*object.Service ServiceList() []*object.Service
EndpointsList() []*object.Endpoints EndpointsList() []*object.Endpoints
SvcIndex(string) *object.Service SvcIndex(string) []*object.Service
SvcIndexReverse(string) *object.Service SvcIndexReverse(string) []*object.Service
PodIndex(string) []*object.Pod PodIndex(string) []*object.Pod
EpIndex(string) *object.Endpoints EpIndex(string) []*object.Endpoints
EpIndexReverse(string) *object.Endpoints EpIndexReverse(string) []*object.Endpoints
GetNodeByName(string) (*api.Node, error) GetNodeByName(string) (*api.Node, error)
GetNamespaceByName(string) (*api.Namespace, error) GetNamespaceByName(string) (*api.Namespace, error)
@ -116,7 +118,7 @@ func newdnsController(kubeClient kubernetes.Interface, opts dnsControlOpts) *dns
&object.Service{}, &object.Service{},
opts.resyncPeriod, opts.resyncPeriod,
cache.ResourceEventHandlerFuncs{AddFunc: dns.Add, UpdateFunc: dns.Update, DeleteFunc: dns.Delete}, cache.ResourceEventHandlerFuncs{AddFunc: dns.Add, UpdateFunc: dns.Update, DeleteFunc: dns.Delete},
cache.Indexers{svcIPIndex: svcIPIndexFunc}, cache.Indexers{svcNameNamespaceIndex: svcNameNamespaceIndexFunc, svcIPIndex: svcIPIndexFunc},
object.ToService, object.ToService,
) )
@ -143,7 +145,7 @@ func newdnsController(kubeClient kubernetes.Interface, opts dnsControlOpts) *dns
&api.Endpoints{}, &api.Endpoints{},
opts.resyncPeriod, opts.resyncPeriod,
cache.ResourceEventHandlerFuncs{AddFunc: dns.Add, UpdateFunc: dns.Update, DeleteFunc: dns.Delete}, cache.ResourceEventHandlerFuncs{AddFunc: dns.Add, UpdateFunc: dns.Update, DeleteFunc: dns.Delete},
cache.Indexers{epIPIndex: epIPIndexFunc}, cache.Indexers{epNameNamespaceIndex: epNameNamespaceIndexFunc, epIPIndex: epIPIndexFunc},
object.ToEndpoints) object.ToEndpoints)
} }
@ -173,6 +175,22 @@ func svcIPIndexFunc(obj interface{}) ([]string, error) {
return []string{svc.ClusterIP}, nil 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) { func epIPIndexFunc(obj interface{}) ([]string, error) {
ep, ok := obj.(*object.Endpoints) ep, ok := obj.(*object.Endpoints)
if !ok { if !ok {
@ -341,9 +359,6 @@ func (dns *dnsControl) EndpointsList() (eps []*object.Endpoints) {
} }
func (dns *dnsControl) PodIndex(ip string) (pods []*object.Pod) { func (dns *dnsControl) PodIndex(ip string) (pods []*object.Pod) {
if dns.podLister == nil {
return nil
}
os, err := dns.podLister.ByIndex(podIPIndex, ip) os, err := dns.podLister.ByIndex(podIPIndex, ip)
if err != nil { if err != nil {
return nil return nil
@ -353,24 +368,27 @@ func (dns *dnsControl) PodIndex(ip string) (pods []*object.Pod) {
if !ok { if !ok {
continue continue
} }
return []*object.Pod{p} pods = append(pods, p)
} }
return nil return pods
} }
func (dns *dnsControl) SvcIndex(key string) *object.Service { func (dns *dnsControl) SvcIndex(idx string) (svcs []*object.Service) {
o, _, err := dns.svcLister.GetByKey(key) os, err := dns.svcLister.ByIndex(svcNameNamespaceIndex, idx)
if err != nil { if err != nil {
return nil return nil
} }
s, ok := o.(*object.Service) for _, o := range os {
if !ok { s, ok := o.(*object.Service)
return nil 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) os, err := dns.svcLister.ByIndex(svcIPIndex, ip)
if err != nil { if err != nil {
return nil return nil
@ -381,27 +399,27 @@ func (dns *dnsControl) SvcIndexReverse(ip string) *object.Service {
if !ok { if !ok {
continue continue
} }
return s svcs = append(svcs, s)
} }
return nil return svcs
} }
func (dns *dnsControl) EpIndex(key string) (ep *object.Endpoints) { func (dns *dnsControl) EpIndex(idx string) (ep []*object.Endpoints) {
o, _, err := dns.epLister.GetByKey(key) os, err := dns.epLister.ByIndex(epNameNamespaceIndex, idx)
if err != nil { if err != nil {
return nil return nil
} }
e, ok := o.(*object.Endpoints) for _, o := range os {
if !ok { e, ok := o.(*object.Endpoints)
return nil if !ok {
continue
}
ep = append(ep, e)
} }
return e return ep
} }
func (dns *dnsControl) EpIndexReverse(ip string) (ep *object.Endpoints) { func (dns *dnsControl) EpIndexReverse(ip string) (ep []*object.Endpoints) {
if dns.epLister == nil {
return nil
}
os, err := dns.epLister.ByIndex(epIPIndex, ip) os, err := dns.epLister.ByIndex(epIPIndex, ip)
if err != nil { if err != nil {
return nil return nil
@ -411,9 +429,9 @@ func (dns *dnsControl) EpIndexReverse(ip string) (ep *object.Endpoints) {
if !ok { if !ok {
continue continue
} }
return e ep = append(ep, e)
} }
return nil return ep
} }
// GetNodeByName return the node by name. If nothing is found an error is // 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 { if !ok {
continue continue
} }
if name == ns.GetName() { if name == ns.ObjectMeta.Name {
return ns, nil return ns, nil
} }
} }

View file

@ -379,15 +379,15 @@ func TestServeDNS(t *testing.T) {
type APIConnServeTest struct{} type APIConnServeTest struct{}
func (APIConnServeTest) HasSynced() bool { return true } func (APIConnServeTest) HasSynced() bool { return true }
func (APIConnServeTest) Run() { return } func (APIConnServeTest) Run() { return }
func (APIConnServeTest) Stop() error { return nil } func (APIConnServeTest) Stop() error { return nil }
func (APIConnServeTest) EpIndexReverse(string) *object.Endpoints { return nil } func (APIConnServeTest) EpIndexReverse(string) []*object.Endpoints { return nil }
func (APIConnServeTest) SvcIndexReverse(string) *object.Service { return nil } func (APIConnServeTest) SvcIndexReverse(string) []*object.Service { return nil }
func (APIConnServeTest) Modified() int64 { return time.Now().Unix() } func (APIConnServeTest) Modified() int64 { return time.Now().Unix() }
func (APIConnServeTest) SetWatchChan(watch.Chan) {} func (APIConnServeTest) SetWatchChan(watch.Chan) {}
func (APIConnServeTest) Watch(string) error { return nil } func (APIConnServeTest) Watch(string) error { return nil }
func (APIConnServeTest) StopWatching(string) {} func (APIConnServeTest) StopWatching(string) {}
func (APIConnServeTest) PodIndex(string) []*object.Pod { func (APIConnServeTest) PodIndex(string) []*object.Pod {
a := []*object.Pod{ a := []*object.Pod{
@ -396,90 +396,103 @@ func (APIConnServeTest) PodIndex(string) []*object.Pod {
return a return a
} }
var svcIndex = map[string]*object.Service{ var svcIndex = map[string][]*object.Service{
"testns/svc1": { "svc1.testns": {
Name: "svc1", {
Namespace: "testns", Name: "svc1",
Type: api.ServiceTypeClusterIP, Namespace: "testns",
ClusterIP: "10.0.0.1", Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{ ClusterIP: "10.0.0.1",
{Name: "http", Protocol: "tcp", Port: 80}, Ports: []api.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
}, },
}, },
"testns/svcempty": { "svcempty.testns": {
Name: "svcempty", {
Namespace: "testns", Name: "svcempty",
Type: api.ServiceTypeClusterIP, Namespace: "testns",
ClusterIP: "10.0.0.1", Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{ ClusterIP: "10.0.0.1",
{Name: "http", Protocol: "tcp", Port: 80}, Ports: []api.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
}, },
}, },
"testns/svc6": { "svc6.testns": {
Name: "svc6", {
Namespace: "testns", Name: "svc6",
Type: api.ServiceTypeClusterIP, Namespace: "testns",
ClusterIP: "1234:abcd::1", Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{ ClusterIP: "1234:abcd::1",
{Name: "http", Protocol: "tcp", Port: 80}, Ports: []api.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
}, },
}, },
"testns/hdls1": { "hdls1.testns": {
Name: "hdls1", {
Namespace: "testns", Name: "hdls1",
Type: api.ServiceTypeClusterIP, Namespace: "testns",
ClusterIP: api.ClusterIPNone, 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},
}, },
}, },
"testns/external-to-service": { "external.testns": {
Name: "external-to-service", {
Namespace: "testns", Name: "external",
ExternalName: "svc1.testns.svc.cluster.local.", Namespace: "testns",
Type: api.ServiceTypeExternalName, ExternalName: "ext.interwebs.test",
Ports: []api.ServicePort{ Type: api.ServiceTypeExternalName,
{Name: "http", Protocol: "tcp", Port: 80}, Ports: []api.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
}, },
}, },
"testns/hdlsprtls": { "external-to-service.testns": {
Name: "hdlsprtls", {
Namespace: "testns", Name: "external-to-service",
Type: api.ServiceTypeClusterIP, Namespace: "testns",
ClusterIP: api.ClusterIPNone, ExternalName: "svc1.testns.svc.cluster.local.",
Type: api.ServiceTypeExternalName,
Ports: []api.ServicePort{
{Name: "http", Protocol: "tcp", Port: 80},
},
},
}, },
"unexposedns/svc1": { "hdlsprtls.testns": {
Name: "svc1", {
Namespace: "unexposedns", Name: "hdlsprtls",
Type: api.ServiceTypeClusterIP, Namespace: "testns",
ClusterIP: "10.0.0.2", Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{ ClusterIP: api.ClusterIPNone,
{Name: "http", Protocol: "tcp", Port: 80}, },
},
"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 { func (APIConnServeTest) SvcIndex(s string) []*object.Service { return svcIndex[s] }
return svcIndex[s]
}
func (APIConnServeTest) ServiceList() []*object.Service { func (APIConnServeTest) ServiceList() []*object.Service {
var svcs []*object.Service var svcs []*object.Service
for _, svc := range svcIndex { for _, svc := range svcIndex {
svcs = append(svcs, svc) svcs = append(svcs, svc...)
} }
return svcs return svcs
} }
var epsIndex = map[string]*object.Endpoints{ var epsIndex = map[string][]*object.Endpoints{
"testns/svc1": { "svc1.testns": {{
Subsets: []object.EndpointSubset{ Subsets: []object.EndpointSubset{
{ {
Addresses: []object.EndpointAddress{ Addresses: []object.EndpointAddress{
@ -492,8 +505,8 @@ var epsIndex = map[string]*object.Endpoints{
}, },
Name: "svc1", Name: "svc1",
Namespace: "testns", Namespace: "testns",
}, }},
"testns/svcempty": { "svcempty.testns": {{
Subsets: []object.EndpointSubset{ Subsets: []object.EndpointSubset{
{ {
Addresses: nil, Addresses: nil,
@ -504,8 +517,8 @@ var epsIndex = map[string]*object.Endpoints{
}, },
Name: "svcempty", Name: "svcempty",
Namespace: "testns", Namespace: "testns",
}, }},
"testns/hdls1": { "hdls1.testns": {{
Subsets: []object.EndpointSubset{ Subsets: []object.EndpointSubset{
{ {
Addresses: []object.EndpointAddress{ Addresses: []object.EndpointAddress{
@ -523,8 +536,8 @@ var epsIndex = map[string]*object.Endpoints{
}, },
Name: "hdls1", Name: "hdls1",
Namespace: "testns", Namespace: "testns",
}, }},
"testns/hdlsprtls": { "hdlsprtls.testns": {{
Subsets: []object.EndpointSubset{ Subsets: []object.EndpointSubset{
{ {
Addresses: []object.EndpointAddress{ Addresses: []object.EndpointAddress{
@ -535,17 +548,17 @@ var epsIndex = map[string]*object.Endpoints{
}, },
Name: "hdlsprtls", Name: "hdlsprtls",
Namespace: "testns", Namespace: "testns",
}, }},
} }
func (APIConnServeTest) EpIndex(s string) *object.Endpoints { func (APIConnServeTest) EpIndex(s string) []*object.Endpoints {
return epsIndex[s] return epsIndex[s]
} }
func (APIConnServeTest) EndpointsList() []*object.Endpoints { func (APIConnServeTest) EndpointsList() []*object.Endpoints {
var eps []*object.Endpoints var eps []*object.Endpoints
for _, ep := range epsIndex { for _, ep := range epsIndex {
eps = append(eps, ep) eps = append(eps, ep...)
} }
return eps return eps
} }

View file

@ -444,12 +444,9 @@ func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg.
serviceList = k.APIConn.ServiceList() serviceList = k.APIConn.ServiceList()
endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EndpointsList() } endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EndpointsList() }
} else { } else {
key := object.ServiceKey(r.namespace, r.service) idx := object.ServiceKey(r.service, r.namespace)
s := k.APIConn.SvcIndex(key) serviceList = k.APIConn.SvcIndex(idx)
if s != nil { endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EpIndex(idx) }
serviceList = append(serviceList, s)
}
endpointsListFunc = func() []*object.Endpoints { return []*object.Endpoints{k.APIConn.EpIndex(key)} }
} }
for _, svc := range serviceList { for _, svc := range serviceList {

View file

@ -59,24 +59,43 @@ func TestEndpointHostname(t *testing.T) {
type APIConnServiceTest struct{} type APIConnServiceTest struct{}
func (APIConnServiceTest) HasSynced() bool { return true } func (APIConnServiceTest) HasSynced() bool { return true }
func (APIConnServiceTest) Run() { return } func (APIConnServiceTest) Run() { return }
func (APIConnServiceTest) Stop() error { return nil } func (APIConnServiceTest) Stop() error { return nil }
func (APIConnServiceTest) PodIndex(string) []*object.Pod { return nil } func (APIConnServiceTest) PodIndex(string) []*object.Pod { return nil }
func (APIConnServiceTest) SvcIndexReverse(string) *object.Service { return nil } func (APIConnServiceTest) SvcIndexReverse(string) []*object.Service { return nil }
func (APIConnServiceTest) EpIndexReverse(string) *object.Endpoints { return nil } func (APIConnServiceTest) EpIndexReverse(string) []*object.Endpoints { return nil }
func (APIConnServiceTest) Modified() int64 { return 0 } func (APIConnServiceTest) Modified() int64 { return 0 }
func (APIConnServiceTest) SetWatchChan(watch.Chan) {} func (APIConnServiceTest) SetWatchChan(watch.Chan) {}
func (APIConnServiceTest) Watch(string) error { return nil } func (APIConnServiceTest) Watch(string) error { return nil }
func (APIConnServiceTest) StopWatching(string) {} func (APIConnServiceTest) StopWatching(string) {}
func (a APIConnServiceTest) SvcIndex(key string) *object.Service { func (APIConnServiceTest) SvcIndex(string) []*object.Service {
for _, s := range a.ServiceList() { svcs := []*object.Service{
if object.ServiceKey(s.Namespace, s.Name) == key { {
return s 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 { func (APIConnServiceTest) ServiceList() []*object.Service {
@ -107,13 +126,61 @@ func (APIConnServiceTest) ServiceList() []*object.Service {
return svcs return svcs
} }
func (a APIConnServiceTest) EpIndex(key string) *object.Endpoints { func (APIConnServiceTest) EpIndex(string) []*object.Endpoints {
for _, e := range a.EndpointsList() { eps := []*object.Endpoints{
if object.EndpointsKey(e.Namespace, e.Name) == key { {
return e 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 { func (APIConnServiceTest) EndpointsList() []*object.Endpoints {
@ -157,7 +224,7 @@ func (APIConnServiceTest) EndpointsList() []*object.Endpoints {
}, },
}, },
}, },
Name: "hdls2", Name: "hdls1",
Namespace: "testns", Namespace: "testns",
}, },
{ {
@ -168,8 +235,6 @@ func (APIConnServiceTest) EndpointsList() []*object.Endpoints {
}, },
}, },
}, },
Name: "testsvc",
Namespace: "testns",
}, },
} }
return eps return eps

View file

@ -28,18 +28,14 @@ func (k *Kubernetes) localNodeName() string {
} }
// Find endpoint matching localIP // Find endpoint matching localIP
ep := k.APIConn.EpIndexReverse(localIP.String()) for _, ep := range k.APIConn.EpIndexReverse(localIP.String()) {
if ep == nil { for _, eps := range ep.Subsets {
return "" for _, addr := range eps.Addresses {
} if localIP.Equal(net.ParseIP(addr.IP)) {
return addr.NodeName
for _, eps := range ep.Subsets { }
for _, addr := range eps.Addresses {
if localIP.Equal(net.ParseIP(addr.IP)) {
return addr.NodeName
} }
} }
} }
return "" return ""
} }

View file

@ -4,7 +4,6 @@ import (
"net" "net"
"strings" "strings"
"github.com/coredns/coredns/plugin/kubernetes/object"
"github.com/miekg/dns" "github.com/miekg/dns"
api "k8s.io/api/core/v1" api "k8s.io/api/core/v1"
) )
@ -23,9 +22,8 @@ func (k *Kubernetes) nsAddr() *dns.A {
localIP := k.interfaceAddrsFunc() localIP := k.interfaceAddrsFunc()
rr.A = localIP rr.A = localIP
ep := k.APIConn.EpIndexReverse(localIP.String()) FindEndpoint:
if ep != nil { for _, ep := range k.APIConn.EpIndexReverse(localIP.String()) {
FindEndpoint:
for _, eps := range ep.Subsets { for _, eps := range ep.Subsets {
for _, addr := range eps.Addresses { for _, addr := range eps.Addresses {
if localIP.Equal(net.ParseIP(addr.IP)) { if localIP.Equal(net.ParseIP(addr.IP)) {
@ -43,12 +41,15 @@ func (k *Kubernetes) nsAddr() *dns.A {
return rr return rr
} }
svc := k.APIConn.SvcIndex(object.ServiceKey(svcNamespace, svcName)) FindService:
if svc != nil { for _, svc := range k.APIConn.ServiceList() {
if svc.ClusterIP == api.ClusterIPNone { if svcName == svc.Name && svcNamespace == svc.Namespace {
rr.A = localIP if svc.ClusterIP == api.ClusterIPNone {
} else { rr.A = localIP
rr.A = net.ParseIP(svc.ClusterIP) } else {
rr.A = net.ParseIP(svc.ClusterIP)
}
break FindService
} }
} }

View file

@ -11,26 +11,18 @@ import (
type APIConnTest struct{} type APIConnTest struct{}
func (APIConnTest) HasSynced() bool { return true } func (APIConnTest) HasSynced() bool { return true }
func (APIConnTest) Run() { return } func (APIConnTest) Run() { return }
func (APIConnTest) Stop() error { return nil } func (APIConnTest) Stop() error { return nil }
func (APIConnTest) PodIndex(string) []*object.Pod { return nil } func (APIConnTest) PodIndex(string) []*object.Pod { return nil }
func (APIConnTest) SvcIndexReverse(string) *object.Service { return nil } func (APIConnTest) SvcIndex(string) []*object.Service { return nil }
func (APIConnTest) EpIndex(string) *object.Endpoints { return nil } func (APIConnTest) SvcIndexReverse(string) []*object.Service { return nil }
func (APIConnTest) EndpointsList() []*object.Endpoints { return nil } func (APIConnTest) EpIndex(string) []*object.Endpoints { return nil }
func (APIConnTest) Modified() int64 { return 0 } func (APIConnTest) EndpointsList() []*object.Endpoints { return nil }
func (APIConnTest) SetWatchChan(watch.Chan) {} func (APIConnTest) Modified() int64 { return 0 }
func (APIConnTest) Watch(string) error { return nil } func (APIConnTest) SetWatchChan(watch.Chan) {}
func (APIConnTest) StopWatching(string) {} 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) ServiceList() []*object.Service { func (APIConnTest) ServiceList() []*object.Service {
svcs := []*object.Service{ svcs := []*object.Service{
@ -43,21 +35,23 @@ func (APIConnTest) ServiceList() []*object.Service {
return svcs return svcs
} }
func (APIConnTest) EpIndexReverse(string) *object.Endpoints { func (APIConnTest) EpIndexReverse(string) []*object.Endpoints {
eps := object.Endpoints{ eps := []*object.Endpoints{
Subsets: []object.EndpointSubset{ {
{ Subsets: []object.EndpointSubset{
Addresses: []object.EndpointAddress{ {
{ Addresses: []object.EndpointAddress{
IP: "127.0.0.1", {
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 } func (APIConnTest) GetNodeByName(name string) (*api.Node, error) { return &api.Node{}, nil }

View file

@ -40,7 +40,7 @@ type EndpointPort struct {
} }
// EndpointsKey return a string using for the index. // 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. // ToEndpoints converts an api.Service to a *Service.
func ToEndpoints(obj interface{}) interface{} { func ToEndpoints(obj interface{}) interface{} {
@ -61,7 +61,7 @@ func ToEndpoints(obj interface{}) interface{} {
Addresses: make([]EndpointAddress, len(eps.Addresses)), Addresses: make([]EndpointAddress, len(eps.Addresses)),
} }
if len(eps.Ports) == 0 { if len(eps.Ports) == 0 {
// Add sentinel if there are no ports. // Add sentinal if there are no ports.
sub.Ports = []EndpointPort{{Port: -1}} sub.Ports = []EndpointPort{{Port: -1}}
} else { } else {
sub.Ports = make([]EndpointPort, len(eps.Ports)) sub.Ports = make([]EndpointPort, len(eps.Ports))

View file

@ -20,7 +20,7 @@ type Service struct {
} }
// ServiceKey return a string using for the index. // 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. // ToService converts an api.Service to a *Service.
func ToService(obj interface{}) interface{} { func ToService(obj interface{}) interface{} {

View file

@ -18,35 +18,35 @@ func (k *Kubernetes) Reverse(state request.Request, exact bool, opt plugin.Optio
return nil, e return nil, e
} }
record := k.serviceRecordForIP(ip, state.Name()) records := k.serviceRecordForIP(ip, state.Name())
if record == nil { if len(records) == 0 {
return nil, errNoItems return records, errNoItems
} }
return []msg.Service{*record}, nil return records, nil
} }
// serviceRecordForIP gets a service record with a cluster ip matching the ip argument // 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 // 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 // First check services with cluster ips
service := k.APIConn.SvcIndexReverse(ip) for _, service := range k.APIConn.SvcIndexReverse(ip) {
if service != nil {
if len(k.Namespaces) > 0 && !k.namespaceExposed(service.Namespace) { if len(k.Namespaces) > 0 && !k.namespaceExposed(service.Namespace) {
return nil continue
} }
domain := strings.Join([]string{service.Name, service.Namespace, Svc, k.primaryZone()}, ".") 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 // If no cluster ips match, search endpoints
ep := k.APIConn.EpIndexReverse(ip) for _, ep := range k.APIConn.EpIndexReverse(ip) {
if ep == nil || len(k.Namespaces) > 0 && !k.namespaceExposed(ep.Namespace) { if len(k.Namespaces) > 0 && !k.namespaceExposed(ep.Namespace) {
return nil continue
} }
for _, eps := range ep.Subsets { for _, eps := range ep.Subsets {
for _, addr := range eps.Addresses { for _, addr := range eps.Addresses {
if addr.IP == ip { if addr.IP == ip {
domain := strings.Join([]string{endpointHostname(addr, k.endpointNameMode), ep.Name, ep.Namespace, Svc, k.primaryZone()}, ".") domain := strings.Join([]string{endpointHostname(addr, k.endpointNameMode), ep.Name, ep.Namespace, Svc, k.primaryZone()}, ".")
return &msg.Service{Host: domain, TTL: k.ttl} return []msg.Service{{Host: domain, TTL: k.ttl}}
}
} }
} }
} }

View file

@ -20,7 +20,7 @@ func (APIConnReverseTest) HasSynced() bool { return true }
func (APIConnReverseTest) Run() { return } func (APIConnReverseTest) Run() { return }
func (APIConnReverseTest) Stop() error { return nil } func (APIConnReverseTest) Stop() error { return nil }
func (APIConnReverseTest) PodIndex(string) []*object.Pod { 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) EndpointsList() []*object.Endpoints { return nil }
func (APIConnReverseTest) ServiceList() []*object.Service { return nil } func (APIConnReverseTest) ServiceList() []*object.Service { return nil }
func (APIConnReverseTest) Modified() int64 { return 0 } func (APIConnReverseTest) Modified() int64 { return 0 }
@ -28,34 +28,38 @@ func (APIConnReverseTest) SetWatchChan(watch.Chan) {}
func (APIConnReverseTest) Watch(string) error { return nil } func (APIConnReverseTest) Watch(string) error { return nil }
func (APIConnReverseTest) StopWatching(string) {} func (APIConnReverseTest) StopWatching(string) {}
func (APIConnReverseTest) SvcIndex(key string) *object.Service { func (APIConnReverseTest) SvcIndex(svc string) []*object.Service {
if key != "testns/svc1" { if svc != "svc1.testns" {
return nil return nil
} }
svc := object.Service{ svcs := []*object.Service{
Name: "svc1", {
Namespace: "testns", Name: "svc1",
ClusterIP: "192.168.1.100", Namespace: "testns",
Ports: []api.ServicePort{{Name: "http", Protocol: "tcp", Port: 80}}, 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" { if ip != "192.168.1.100" {
return nil return nil
} }
svc := object.Service{ svcs := []*object.Service{
Name: "svc1", {
Namespace: "testns", Name: "svc1",
ClusterIP: "192.168.1.100", Namespace: "testns",
Ports: []api.ServicePort{{Name: "http", Protocol: "tcp", Port: 80}}, 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 { switch ip {
case "10.0.0.100": case "10.0.0.100":
case "1234:abcd::1": case "1234:abcd::1":
@ -64,24 +68,26 @@ func (APIConnReverseTest) EpIndexReverse(ip string) *object.Endpoints {
default: default:
return nil return nil
} }
ep := object.Endpoints{ eps := []*object.Endpoints{
Subsets: []object.EndpointSubset{ {
{ Subsets: []object.EndpointSubset{
Addresses: []object.EndpointAddress{ {
{IP: "10.0.0.100", Hostname: "ep1a"}, Addresses: []object.EndpointAddress{
{IP: "1234:abcd::1", Hostname: "ep1b"}, {IP: "10.0.0.100", Hostname: "ep1a"},
{IP: "fd00:77:30::a", Hostname: "ip6svc1ex"}, {IP: "1234:abcd::1", Hostname: "ep1b"},
{IP: "fd00:77:30::2:9ba6", Hostname: "ip6svc1in"}, {IP: "fd00:77:30::a", Hostname: "ip6svc1ex"},
}, {IP: "fd00:77:30::2:9ba6", Hostname: "ip6svc1in"},
Ports: []object.EndpointPort{ },
{Port: 80, Protocol: "tcp", Name: "http"}, 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) { func (APIConnReverseTest) GetNodeByName(name string) (*api.Node, error) {

View file

@ -9,7 +9,6 @@ import (
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/etcd/msg" "github.com/coredns/coredns/plugin/etcd/msg"
"github.com/coredns/coredns/request" "github.com/coredns/coredns/request"
"k8s.io/client-go/tools/cache"
"github.com/miekg/dns" "github.com/miekg/dns"
api "k8s.io/api/core/v1" api "k8s.io/api/core/v1"
@ -115,36 +114,39 @@ func (k *Kubernetes) transfer(c chan dns.RR, zone string) {
continue continue
} }
key, err := cache.MetaNamespaceKeyFunc(svc) endpointsList := k.APIConn.EpIndex(svc.Name + "." + svc.Namespace)
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)
s.Key = strings.Join(append(svcBase, endpointHostname(addr, k.endpointNameMode)), "/") for _, ep := range endpointsList {
// Change host from IP to Name for SRV records if ep.Name != svc.Name || ep.Namespace != svc.Namespace {
host := emitAddressRecord(c, s) continue
s.Host = host }
for _, p := range eps.Ports { for _, eps := range ep.Subsets {
// As per spec unnamed ports do not have a srv record srvWeight := calcSRVWeight(len(eps.Addresses))
// https://github.com/kubernetes/dns/blob/master/docs/specification.md#232---srv-records for _, addr := range eps.Addresses {
if p.Name == "" { s := msg.Service{Host: addr.IP, TTL: k.ttl}
continue 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)
} }
} }
} }