coredns/middleware/kubernetes/ns.go
Chris O'Haver 7f950e496a Handle K8s middleware NS record (#662)
* commit for testing in cluster

* commit for testing in cluster

* refactor and add ns.dns record

* Release 007

* reduce heap allocations

* gofmt

* revert accidental Makefile commits

* restore prior rcode for disabled pod mode

* revert Makefile deltas

* add unit tests

* more unit tests

* make isRequestInReverseRange easier to test

* more unit tests

* addressing review feedback

* commit setup.go
2017-05-22 16:05:48 -04:00

115 lines
2.7 KiB
Go

package kubernetes
import (
"net"
"strings"
"github.com/coredns/coredns/middleware/etcd/msg"
"github.com/miekg/dns"
"k8s.io/client-go/1.5/pkg/api"
)
const DefaultNSName = "ns.dns."
var corednsRecord dns.A
type InterfaceAddrser interface {
InterfaceAddrs() ([]net.Addr, error)
}
type InterfaceAddrs struct{}
func (i InterfaceAddrs) InterfaceAddrs() ([]net.Addr, error) {
return net.InterfaceAddrs()
}
func (k *Kubernetes) recordsForNS(r recordRequest, svcs *[]msg.Service) error {
ns := k.CoreDNSRecord()
s := msg.Service{
Host: ns.A.String(),
Key: msg.Path(strings.Join([]string{ns.Hdr.Name, r.zone}, "."), "coredns")}
*svcs = append(*svcs, s)
return nil
}
// DefaultNSMsg returns an msg.Service representing an A record for
// ns.dns.[zone] -> dns service ip. This A record is needed to legitimize
// the SOA response in middleware.NS(), which is hardcoded at ns.dns.[zone].
func (k *Kubernetes) defaultNSMsg(r recordRequest) msg.Service {
ns := k.CoreDNSRecord()
s := msg.Service{
Key: msg.Path(strings.Join([]string{DefaultNSName, r.zone}, "."), "coredns"),
Host: ns.A.String(),
}
return s
}
func isDefaultNS(name string, r recordRequest) bool {
return strings.Index(name, DefaultNSName) == 0 && strings.Index(name, r.zone) == len(DefaultNSName)
}
func (k *Kubernetes) CoreDNSRecord() dns.A {
var localIP net.IP
var svcName string
var svcNamespace string
var dnsIP net.IP
if len(corednsRecord.Hdr.Name) == 0 || corednsRecord.A == nil {
// get local Pod IP
addrs, _ := k.interfaceAddrs.InterfaceAddrs()
for _, addr := range addrs {
ip, _, _ := net.ParseCIDR(addr.String())
ip = ip.To4()
if ip == nil || ip.IsLoopback() {
continue
}
localIP = ip
break
}
// Find endpoint matching IP to get service and namespace
endpointsList := k.APIConn.EndpointsList()
FindEndpoint:
for _, ep := range endpointsList.Items {
for _, eps := range ep.Subsets {
for _, addr := range eps.Addresses {
if localIP.Equal(net.ParseIP(addr.IP)) {
svcNamespace = ep.ObjectMeta.Namespace
svcName = ep.ObjectMeta.Name
break FindEndpoint
}
}
}
}
if len(svcName) == 0 {
corednsRecord.Hdr.Name = DefaultNSName
corednsRecord.A = localIP
return corednsRecord
}
// Find service to get ClusterIP
serviceList := k.APIConn.ServiceList()
FindService:
for _, svc := range serviceList {
if svcName == svc.Name && svcNamespace == svc.Namespace {
if svc.Spec.ClusterIP == api.ClusterIPNone {
dnsIP = localIP
} else {
dnsIP = net.ParseIP(svc.Spec.ClusterIP)
}
break FindService
}
}
if dnsIP == nil {
dnsIP = localIP
}
corednsRecord.Hdr.Name = strings.Join([]string{svcName, svcNamespace, "svc."}, ".")
corednsRecord.A = dnsIP
}
return corednsRecord
}