aboutsummaryrefslogtreecommitdiff
path: root/plugin/kubernetes/external.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/kubernetes/external.go')
-rw-r--r--plugin/kubernetes/external.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/plugin/kubernetes/external.go b/plugin/kubernetes/external.go
new file mode 100644
index 000000000..1770872b3
--- /dev/null
+++ b/plugin/kubernetes/external.go
@@ -0,0 +1,92 @@
+package kubernetes
+
+import (
+ "strings"
+
+ "github.com/coredns/coredns/plugin/etcd/msg"
+ "github.com/coredns/coredns/plugin/kubernetes/object"
+ "github.com/coredns/coredns/plugin/pkg/dnsutil"
+ "github.com/coredns/coredns/request"
+
+ "github.com/miekg/dns"
+)
+
+// External implements the ExternalFunc call from the external plugin.
+// It returns any services matching in the services' ExternalIPs.
+func (k *Kubernetes) External(state request.Request) ([]msg.Service, int) {
+ base, _ := dnsutil.TrimZone(state.Name(), state.Zone)
+
+ segs := dns.SplitDomainName(base)
+ last := len(segs) - 1
+ if last < 0 {
+ return nil, dns.RcodeServerFailure
+ }
+ // We dealing with a fairly normal domain name here, but; we still need to have the service
+ // and the namespace:
+ // service.namespace.<base>
+ //
+ // for service (and SRV) you can also say _tcp, and port (i.e. _http), we need those be picked
+ // up, unless they are not specified, then we use an internal wildcard.
+ port := "*"
+ protocol := "*"
+ namespace := segs[last]
+ if !k.namespaceExposed(namespace) || !k.namespace(namespace) {
+ return nil, dns.RcodeNameError
+ }
+
+ last--
+ if last < 0 {
+ return nil, dns.RcodeSuccess
+ }
+
+ service := segs[last]
+ last--
+ if last == 1 {
+ protocol = stripUnderscore(segs[last])
+ port = stripUnderscore(segs[last-1])
+ last -= 2
+ }
+
+ if last != -1 {
+ // too long
+ return nil, dns.RcodeNameError
+ }
+
+ idx := object.ServiceKey(service, namespace)
+ serviceList := k.APIConn.SvcIndex(idx)
+
+ services := []msg.Service{}
+ zonePath := msg.Path(state.Zone, coredns)
+ rcode := dns.RcodeNameError
+
+ for _, svc := range serviceList {
+ if namespace != svc.Namespace {
+ continue
+ }
+ if service != svc.Name {
+ continue
+ }
+
+ for _, ip := range svc.ExternalIPs {
+ for _, p := range svc.Ports {
+ if !(match(port, p.Name) && match(protocol, string(p.Protocol))) {
+ continue
+ }
+ rcode = dns.RcodeSuccess
+ s := msg.Service{Host: ip, Port: int(p.Port), TTL: k.ttl}
+ s.Key = strings.Join([]string{zonePath, svc.Namespace, svc.Name}, "/")
+
+ services = append(services, s)
+ }
+ }
+ }
+ return services, rcode
+}
+
+// ExternalAddress returns the external service address(es) for the CoreDNS service.
+func (k *Kubernetes) ExternalAddress(state request.Request) []dns.RR {
+ // This is probably wrong, because of all the fallback behavior of k.nsAddr, i.e. can get
+ // an address that isn't reacheable from outside the cluster.
+ rrs := []dns.RR{k.nsAddr()}
+ return rrs
+}