diff options
author | 2016-06-06 12:49:53 -0700 | |
---|---|---|
committer | 2016-06-06 20:49:53 +0100 | |
commit | d04abdf422ae4e472b386ebbef466977eace968a (patch) | |
tree | 177141b9e9133c2c81e5b0532d0e9be14d5858d6 /middleware/kubernetes/handler.go | |
parent | 446eaa957d12a9114d4ca467312efb900bc40d5e (diff) | |
download | coredns-d04abdf422ae4e472b386ebbef466977eace968a.tar.gz coredns-d04abdf422ae4e472b386ebbef466977eace968a.tar.zst coredns-d04abdf422ae4e472b386ebbef466977eace968a.zip |
BK8s datasource middleware -- PoC for A records (#153)
* Laying down kubernetes middleware foundation
* Duplicated a bunch of code form etcd middleware
* Duplicated code hacked to compile and load as a separate middleware
* Adding verbose build option to Makefile
* Removing stubzone and tls support
tls and stubzone support was carried over from base etcd middleware code.
Removing to simplify the kube middleware implementation. (For now.)
* Adding conf directory for sample conf files
* Removing stubzone support from query handler
* Remove upstream and proxy from k8s corefile.
Not sure that upstream or proxy makes sense for a k8s backed zone.
* Comment out use of singleflight serialization
* Removing parsing support for "upstream" directive from k8s
* Removing upstream directive parsing code
* Removing CNAME and TXT lookup implementation
* Create README.md
Brain-dump of DNS record name assembly and open work items.
* Adding notes about wildcard handling
* Adding basic k8s API client
* Fleshing out methods on k8s connector
* Remove PathPrefix from middleware init
* Removing incorrect plural
* Adding brute-force k8s service lookup functions
* Initializing k8s API connector during startup
* Hacking around to call k8s connector
* Parsing incoming domain name into serviceName and namespace
* Improving and simplifying k8s zone matching and label segmentation
* Removing unused functions carried over from etcd middleware
* Adding basic return of k8s data to DNS client
* updated debugging println statements to flag with "[debug]"
* removed code in kubernetes.go::Records that was a hold-over from etcd middleware.
* Removed some random exploratory hacking.
* Minior README.md updates
* Updating with demo instructions
* Updating README.md with CoreFile and removing completed TODO items
* Updating conf file and README to reflect DNS response cache works
* Disabling DNS response caching
* Adding debug statement on entry to Records()
* Changing port number in exampes to port 53.
* Misc style and clarity changes
* Removing empty function definitions
* Adding comment to track future cleanup
* Refactoring README to follow style of other middleware
* Exposing dataobject field (typo)
Diffstat (limited to 'middleware/kubernetes/handler.go')
-rw-r--r-- | middleware/kubernetes/handler.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/middleware/kubernetes/handler.go b/middleware/kubernetes/handler.go new file mode 100644 index 000000000..44de8da3d --- /dev/null +++ b/middleware/kubernetes/handler.go @@ -0,0 +1,101 @@ +package kubernetes + +import ( + "fmt" + + "github.com/miekg/coredns/middleware" + + "github.com/miekg/dns" + "golang.org/x/net/context" +) + +func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { + + fmt.Println("[debug] here entering ServeDNS: ctx:%v dnsmsg:%v", ctx, r) + + state := middleware.State{W: w, Req: r} + if state.QClass() != dns.ClassINET { + return dns.RcodeServerFailure, fmt.Errorf("can only deal with ClassINET") + } + + // Check that query matches one of the zones served by this middleware, + // otherwise delegate to the next in the pipeline. + zone := middleware.Zones(k.Zones).Matches(state.Name()) + if zone == "" { + if k.Next == nil { + return dns.RcodeServerFailure, nil + } + return k.Next.ServeDNS(ctx, w, r) + } + + m := new(dns.Msg) + m.SetReply(r) + m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true + + var ( + records, extra []dns.RR + err error + ) + switch state.Type() { + case "A": + records, err = k.A(zone, state, nil) + case "AAAA": + records, err = k.AAAA(zone, state, nil) + case "TXT": + records, err = k.TXT(zone, state) + case "CNAME": + records, err = k.CNAME(zone, state) + case "MX": + records, extra, err = k.MX(zone, state) + case "SRV": + records, extra, err = k.SRV(zone, state) + case "SOA": + records = []dns.RR{k.SOA(zone, state)} + case "NS": + if state.Name() == zone { + records, extra, err = k.NS(zone, state) + break + } + fallthrough + default: + // Do a fake A lookup, so we can distinguish betwen NODATA and NXDOMAIN + _, err = k.A(zone, state, nil) + } + if isKubernetesNameError(err) { + return k.Err(zone, dns.RcodeNameError, state) + } + if err != nil { + return dns.RcodeServerFailure, err + } + + if len(records) == 0 { + return k.Err(zone, dns.RcodeSuccess, state) + } + + m.Answer = append(m.Answer, records...) + m.Extra = append(m.Extra, extra...) + + m = dedup(m) + state.SizeAndDo(m) + m, _ = state.Scrub(m) + w.WriteMsg(m) + return dns.RcodeSuccess, nil +} + +// NoData write a nodata response to the client. +func (k Kubernetes) Err(zone string, rcode int, state middleware.State) (int, error) { + m := new(dns.Msg) + m.SetRcode(state.Req, rcode) + m.Ns = []dns.RR{k.SOA(zone, state)} + state.SizeAndDo(m) + state.W.WriteMsg(m) + return rcode, nil +} + +func dedup(m *dns.Msg) *dns.Msg { + // TODO(miek): expensive! + m.Answer = dns.Dedup(m.Answer, nil) + m.Ns = dns.Dedup(m.Ns, nil) + m.Extra = dns.Dedup(m.Extra, nil) + return m +} |