diff --git a/plugin/backend_lookup.go b/plugin/backend_lookup.go index 002d1855b..65cdcbaf5 100644 --- a/plugin/backend_lookup.go +++ b/plugin/backend_lookup.go @@ -172,6 +172,11 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec w[serv.Priority] += weight } for _, serv := range services { + // Don't add the entry if the port is -1 (invalid). The kubernetes plugin uses port -1 when a service/endpoint + // does not have any declared ports. + if serv.Port == -1 { + continue + } w1 := 100.0 / float64(w[serv.Priority]) if serv.Weight == 0 { w1 *= 100 diff --git a/plugin/kubernetes/handler_test.go b/plugin/kubernetes/handler_test.go index 435dcb1b6..f9061bf12 100644 --- a/plugin/kubernetes/handler_test.go +++ b/plugin/kubernetes/handler_test.go @@ -124,6 +124,22 @@ var dnsTestCases = []test.Case{ test.A("hdls1.testns.svc.cluster.local. 5 IN A 172.0.0.5"), }, }, + // A Service (Headless and Portless) + { + Qname: "hdlsprtls.testns.svc.cluster.local.", Qtype: dns.TypeA, + Rcode: dns.RcodeSuccess, + Answer: []dns.RR{ + test.A("hdlsprtls.testns.svc.cluster.local. 5 IN A 172.0.0.20"), + }, + }, + // An Endpoint with no port + { + Qname: "172-0-0-20.hdlsprtls.testns.svc.cluster.local.", Qtype: dns.TypeA, + Rcode: dns.RcodeSuccess, + Answer: []dns.RR{ + test.A("172-0-0-20.hdlsprtls.testns.svc.cluster.local. 5 IN A 172.0.0.20"), + }, + }, // An Endpoint ip { Qname: "172-0-0-2.hdls1.testns.svc.cluster.local.", Qtype: dns.TypeA, @@ -169,6 +185,14 @@ var dnsTestCases = []test.Case{ test.A("dup-name.hdls1.testns.svc.cluster.local. 5 IN A 172.0.0.5"), }, }, + // SRV Service (Headless and portless) + { + Qname: "*.*.hdlsprtls.testns.svc.cluster.local.", Qtype: dns.TypeSRV, + Rcode: dns.RcodeSuccess, + Ns: []dns.RR{ + test.SOA("cluster.local. 300 IN SOA ns.dns.cluster.local. hostmaster.cluster.local. 1499347823 7200 1800 86400 60"), + }, + }, // AAAA { Qname: "5678-abcd--2.hdls1.testns.svc.cluster.local", Qtype: dns.TypeAAAA, @@ -444,6 +468,16 @@ var svcIndex = map[string][]*api.Service{ Type: api.ServiceTypeExternalName, }, }}, + "hdlsprtls.testns": {{ + ObjectMeta: meta.ObjectMeta{ + Name: "hdlsprtls", + Namespace: "testns", + }, + Spec: api.ServiceSpec{ + Type: api.ServiceTypeClusterIP, + ClusterIP: api.ClusterIPNone, + }, + }}, } func (APIConnServeTest) SvcIndex(s string) []*api.Service { @@ -539,6 +573,22 @@ var epsIndex = map[string][]*api.Endpoints{ Namespace: "testns", }, }}, + "hdlsprtls.testns": {{ + Subsets: []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{ + { + IP: "172.0.0.20", + }, + }, + Ports: []api.EndpointPort{}, + }, + }, + ObjectMeta: meta.ObjectMeta{ + Name: "hdlsprtls", + Namespace: "testns", + }, + }}, } func (APIConnServeTest) EpIndex(s string) []*api.Endpoints { diff --git a/plugin/kubernetes/kubernetes.go b/plugin/kubernetes/kubernetes.go index 03b93748b..eaadb142c 100644 --- a/plugin/kubernetes/kubernetes.go +++ b/plugin/kubernetes/kubernetes.go @@ -459,13 +459,17 @@ func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg. for _, addr := range eps.Addresses { // See comments in parse.go parseRequest about the endpoint handling. - if r.endpoint != "" { if !match(r.endpoint, endpointHostname(addr, k.endpointNameMode)) { continue } } + if len(eps.Ports) == 0 { + // add a sentinel port (-1) entry so we create records for services without any declared ports + eps.Ports = append(eps.Ports, api.EndpointPort{Port: -1}) + } + for _, p := range eps.Ports { if !(match(r.port, p.Name) && match(r.protocol, string(p.Protocol))) { continue @@ -496,6 +500,10 @@ func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg. } // ClusterIP service + if len(svc.Spec.Ports) == 0 { + // add a sentinel port (-1) entry so we create records for services without any declared ports + svc.Spec.Ports = append(svc.Spec.Ports, api.ServicePort{Port: -1}) + } for _, p := range svc.Spec.Ports { if !(match(r.port, p.Name) && match(r.protocol, string(p.Protocol))) { continue