diff options
Diffstat (limited to 'plugin/kubernetes/external.go')
-rw-r--r-- | plugin/kubernetes/external.go | 92 |
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 +} |