From 75f1b9c988e036a56f0ae31224401aa9b652e9ef Mon Sep 17 00:00:00 2001 From: Bingshen Wang Date: Sat, 25 Aug 2018 20:53:41 +0800 Subject: [PATCH] fix kubernetes in-cluster CNAME lookup (#2040) fix #2038 Signed-off-by: bingshen.wbs --- plugin/backend_lookup.go | 41 +++++++++++++++---------------- plugin/kubernetes/handler_test.go | 24 ++++++++++++++++++ plugin/kubernetes/parse_test.go | 12 ++++----- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/plugin/backend_lookup.go b/plugin/backend_lookup.go index 3946c9fee..002d1855b 100644 --- a/plugin/backend_lookup.go +++ b/plugin/backend_lookup.go @@ -40,24 +40,22 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d if dnsutil.DuplicateCNAME(newRecord, previousRecords) { continue } + if dns.IsSubDomain(zone, dns.Fqdn(serv.Host)) { + state1 := state.NewWithQuestion(serv.Host, state.QType()) + state1.Zone = zone + nextRecords, err := A(b, zone, state1, append(previousRecords, newRecord), opt) - state1 := state.NewWithQuestion(serv.Host, state.QType()) - nextRecords, err := A(b, zone, state1, append(previousRecords, newRecord), opt) - - if err == nil { - // Not only have we found something we should add the CNAME and the IP addresses. - if len(nextRecords) > 0 { - records = append(records, newRecord) - records = append(records, nextRecords...) + if err == nil { + // Not only have we found something we should add the CNAME and the IP addresses. + if len(nextRecords) > 0 { + records = append(records, newRecord) + records = append(records, nextRecords...) + } } continue } // This means we can not complete the CNAME, try to look else where. target := newRecord.Target - if dns.IsSubDomain(zone, target) { - // We should already have found it - continue - } // Lookup m1, e1 := b.Lookup(state, target, state.QType()) if e1 != nil { @@ -110,19 +108,20 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords if dnsutil.DuplicateCNAME(newRecord, previousRecords) { continue } + if dns.IsSubDomain(zone, dns.Fqdn(serv.Host)) { + state1 := state.NewWithQuestion(serv.Host, state.QType()) + state1.Zone = zone + nextRecords, err := AAAA(b, zone, state1, append(previousRecords, newRecord), opt) - state1 := state.NewWithQuestion(serv.Host, state.QType()) - nextRecords, err := AAAA(b, zone, state1, append(previousRecords, newRecord), opt) - - if err == nil { - // Not only have we found something we should add the CNAME and the IP addresses. - if len(nextRecords) > 0 { - records = append(records, newRecord) - records = append(records, nextRecords...) + if err == nil { + // Not only have we found something we should add the CNAME and the IP addresses. + if len(nextRecords) > 0 { + records = append(records, newRecord) + records = append(records, nextRecords...) + } } continue } - // This means we can not complete the CNAME, try to look else where. target := newRecord.Target m1, e1 := b.Lookup(state, target, state.QType()) diff --git a/plugin/kubernetes/handler_test.go b/plugin/kubernetes/handler_test.go index 2edeb8e8e..435dcb1b6 100644 --- a/plugin/kubernetes/handler_test.go +++ b/plugin/kubernetes/handler_test.go @@ -183,6 +183,15 @@ var dnsTestCases = []test.Case{ test.CNAME("external.testns.svc.cluster.local. 5 IN CNAME ext.interwebs.test."), }, }, + // CNAME External To Internal Service + { + Qname: "external-to-service.testns.svc.cluster.local", Qtype: dns.TypeA, + Rcode: dns.RcodeSuccess, + Answer: []dns.RR{ + test.CNAME("external-to-service.testns.svc.cluster.local. 5 IN CNAME svc1.testns.svc.cluster.local."), + test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1"), + }, + }, // AAAA Service (with an existing A record, but no AAAA record) { Qname: "svc1.testns.svc.cluster.local.", Qtype: dns.TypeAAAA, @@ -420,6 +429,21 @@ var svcIndex = map[string][]*api.Service{ Type: api.ServiceTypeExternalName, }, }}, + "external-to-service.testns": {{ + ObjectMeta: meta.ObjectMeta{ + Name: "external-to-service", + Namespace: "testns", + }, + Spec: api.ServiceSpec{ + ExternalName: "svc1.testns.svc.cluster.local.", + Ports: []api.ServicePort{{ + Name: "http", + Protocol: "tcp", + Port: 80, + }}, + Type: api.ServiceTypeExternalName, + }, + }}, } func (APIConnServeTest) SvcIndex(s string) []*api.Service { diff --git a/plugin/kubernetes/parse_test.go b/plugin/kubernetes/parse_test.go index 7907afc65..0ce4b7d98 100644 --- a/plugin/kubernetes/parse_test.go +++ b/plugin/kubernetes/parse_test.go @@ -14,17 +14,17 @@ func TestParseRequest(t *testing.T) { expected string // output from r.String() }{ // valid SRV request - {"_http._tcp.webs.mynamespace.svc.inter.webs.test.", "http.tcp..webs.mynamespace.svc"}, + {"_http._tcp.webs.mynamespace.svc.inter.webs.tests.", "http.tcp..webs.mynamespace.svc"}, // wildcard acceptance - {"*.any.*.any.svc.inter.webs.test.", "*.any..*.any.svc"}, + {"*.any.*.any.svc.inter.webs.tests.", "*.any..*.any.svc"}, // A request of endpoint - {"1-2-3-4.webs.mynamespace.svc.inter.webs.test.", "*.*.1-2-3-4.webs.mynamespace.svc"}, + {"1-2-3-4.webs.mynamespace.svc.inter.webs.tests.", "*.*.1-2-3-4.webs.mynamespace.svc"}, // bare zone - {"inter.webs.test.", "....."}, + {"inter.webs.tests.", "....."}, // bare svc type - {"svc.inter.webs.test.", "....."}, + {"svc.inter.webs.tests.", "....."}, // bare pod type - {"pod.inter.webs.test.", "....."}, + {"pod.inter.webs.tests.", "....."}, } for i, tc := range tests { m := new(dns.Msg)