aboutsummaryrefslogtreecommitdiff
path: root/middleware/kubernetes/parse.go
diff options
context:
space:
mode:
authorGravatar Miek Gieben <miek@miek.nl> 2017-08-10 01:08:58 -0700
committerGravatar GitHub <noreply@github.com> 2017-08-10 01:08:58 -0700
commit7e56cc74e5420bfc1670ddf858420909fdaf3fee (patch)
treeb8d2992c476a57c11082239c9501761f19f52ef8 /middleware/kubernetes/parse.go
parentfefc4374d72086d6325019471677a6ae73622a63 (diff)
downloadcoredns-7e56cc74e5420bfc1670ddf858420909fdaf3fee.tar.gz
coredns-7e56cc74e5420bfc1670ddf858420909fdaf3fee.tar.zst
coredns-7e56cc74e5420bfc1670ddf858420909fdaf3fee.zip
WIP: Parserequest2 cutback (#868)
* middleware/kubernetes: pull TXT out of parseRequest Put the TXT handling one layer higher and remove it from parseRequest. Also rename the podsvc field in there to podOrSvc. Now that it isn't used anymore for TXT record (dns-version) that was put in there. We can make this a boolean (in a future PR). Make parseRequest get an optional Zone that is from state.Zone and use that instead of its own code. Removed some tests and other smaller cleanups. Fixes #836 * add this reverse * another check * readd * Rename to kPod and kService for some clarity
Diffstat (limited to 'middleware/kubernetes/parse.go')
-rw-r--r--middleware/kubernetes/parse.go120
1 files changed, 120 insertions, 0 deletions
diff --git a/middleware/kubernetes/parse.go b/middleware/kubernetes/parse.go
new file mode 100644
index 000000000..790060896
--- /dev/null
+++ b/middleware/kubernetes/parse.go
@@ -0,0 +1,120 @@
+package kubernetes
+
+import (
+ "github.com/coredns/coredns/middleware/pkg/dnsutil"
+
+ "github.com/miekg/dns"
+)
+
+type recordRequest struct {
+ // The named port from the kubernetes DNS spec, this is the service part (think _https) from a well formed
+ // SRV record.
+ port string
+ // The protocol is usually _udp or _tcp (if set), and comes from the protocol part of a well formed
+ // SRV record.
+ protocol string
+ endpoint string
+ service string
+ namespace string
+ // A each name can be for a pod or a service, here we track what we've seen. This value is true for
+ // pods and false for services. If we ever need to extend this well use a typed value.
+ podOrSvc string
+ zone string
+ federation string
+}
+
+// TODO(miek): make it use request.Request.
+func (k *Kubernetes) parseRequest(lowerCasedName string, qtype uint16, zone ...string) (r recordRequest, err error) {
+ // 3 Possible cases
+ // SRV Request: _port._protocol.service.namespace.[federation.]type.zone
+ // A Request (endpoint): endpoint.service.namespace.[federation.]type.zone
+ // A Request (service): service.namespace.[federation.]type.zone
+
+ if len(zone) == 0 {
+ panic("parseRequest must be called with a zone")
+ }
+
+ base, _ := dnsutil.TrimZone(lowerCasedName, zone[0])
+ segs := dns.SplitDomainName(base)
+
+ r.zone = zone[0]
+ r.federation, segs = k.stripFederation(segs)
+
+ if qtype == dns.TypeNS {
+ return r, nil
+ }
+
+ if qtype == dns.TypeA && isDefaultNS(lowerCasedName, r) {
+ return r, nil
+ }
+
+ offset := 0
+ if qtype == dns.TypeSRV {
+ // The kubernetes peer-finder expects queries with empty port and service to resolve
+ // If neither is specified, treat it as a wildcard
+ if len(segs) == 3 {
+ r.port = "*"
+ r.service = "*"
+ offset = 0
+ } else {
+ if len(segs) != 5 {
+ return r, errInvalidRequest
+ }
+ // This is a SRV style request, get first two elements as port and
+ // protocol, stripping leading underscores if present.
+ if segs[0][0] == '_' {
+ r.port = segs[0][1:]
+ } else {
+ r.port = segs[0]
+ if !wildcard(r.port) {
+ return r, errInvalidRequest
+ }
+ }
+ if segs[1][0] == '_' {
+ r.protocol = segs[1][1:]
+ if r.protocol != "tcp" && r.protocol != "udp" {
+ return r, errInvalidRequest
+ }
+ } else {
+ r.protocol = segs[1]
+ if !wildcard(r.protocol) {
+ return r, errInvalidRequest
+ }
+ }
+ if r.port == "" || r.protocol == "" {
+ return r, errInvalidRequest
+ }
+ offset = 2
+ }
+ }
+ if (qtype == dns.TypeA || qtype == dns.TypeAAAA) && len(segs) == 4 {
+ // This is an endpoint A/AAAA record request. Get first element as endpoint.
+ r.endpoint = segs[0]
+ offset = 1
+ }
+
+ if len(segs) == (offset + 3) {
+ r.service = segs[offset]
+ r.namespace = segs[offset+1]
+ r.podOrSvc = segs[offset+2]
+
+ return r, nil
+ }
+
+ return r, errInvalidRequest
+}
+
+// String return a string representation of r, it just returns all
+// fields concatenated with dots.
+// This is mostly used in tests.
+func (r recordRequest) String() string {
+ s := r.port
+ s += "." + r.protocol
+ s += "." + r.endpoint
+ s += "." + r.service
+ s += "." + r.namespace
+ s += "." + r.podOrSvc
+ s += "." + r.zone
+ s += "." + r.federation
+ return s
+}