mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 08:14:18 -04:00
Make the receiver a pointer so that the uptdateStubZones map update will retain the stubzones found, unlike the current case where the update will be applied and then promptly forgotten, because it is working on a copy. Add test/etcd_test.go to test a large part of the code. This didn't catch the chaos middleware hack though. The chaos middleware zones are now *not* automatically added. You have to take care of that by yourself (docs updates). When using debug queries and falling through to the next middleware in etcd, restore the original (with o-o.debug) query before passing it on.
75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package etcd
|
|
|
|
import (
|
|
"log"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/miekg/coredns/middleware/etcd/msg"
|
|
"github.com/miekg/coredns/middleware/proxy"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
func (e *Etcd) UpdateStubZones() {
|
|
go func() {
|
|
for {
|
|
e.updateStubZones()
|
|
time.Sleep(15 * time.Second)
|
|
}
|
|
}()
|
|
}
|
|
|
|
// Look in .../dns/stub/<zone>/xx for msg.Services. Loop through them
|
|
// extract <zone> and add them as forwarders (ip:port-combos) for
|
|
// the stub zones. Only numeric (i.e. IP address) hosts are used.
|
|
// Only the first zone configured on e is used for the lookup.
|
|
func (e *Etcd) updateStubZones() {
|
|
zone := e.Zones[0]
|
|
services, err := e.Records(stubDomain+"."+zone, false)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
stubmap := make(map[string]proxy.Proxy)
|
|
// track the nameservers on a per domain basis, but allow a list on the domain.
|
|
nameservers := map[string][]string{}
|
|
|
|
for _, serv := range services {
|
|
if serv.Port == 0 {
|
|
serv.Port = 53
|
|
}
|
|
ip := net.ParseIP(serv.Host)
|
|
if ip == nil {
|
|
log.Printf("[WARNING] Non IP address stub nameserver: %s", serv.Host)
|
|
continue
|
|
}
|
|
|
|
domain := msg.Domain(serv.Key)
|
|
labels := dns.SplitDomainName(domain)
|
|
|
|
// If the remaining name equals any of the zones we have, we ignore it.
|
|
for _, z := range e.Zones {
|
|
// Chop of left most label, because that is used as the nameserver place holder
|
|
// and drop the right most labels that belong to zone.
|
|
// We must *also* chop of dns.stub. which means cutting two more labels.
|
|
domain = dns.Fqdn(strings.Join(labels[1:len(labels)-dns.CountLabel(z)-2], "."))
|
|
if domain == z {
|
|
log.Printf("[WARNING] Skipping nameserver for domain we are authoritative for: %s", domain)
|
|
continue
|
|
}
|
|
nameservers[domain] = append(nameservers[domain], net.JoinHostPort(serv.Host, strconv.Itoa(serv.Port)))
|
|
}
|
|
}
|
|
for domain, nss := range nameservers {
|
|
stubmap[domain] = proxy.New(nss)
|
|
}
|
|
// atomic swap (at least that's what we hope it is)
|
|
if len(stubmap) > 0 {
|
|
e.Stubmap = &stubmap
|
|
}
|
|
return
|
|
}
|