mirror of
https://github.com/coredns/coredns.git
synced 2025-11-01 10:43:17 -04:00
middleware/auto: add (#333)
Add auto-load middleware that automatically picks up zones. Every X seconds it will scan for new zones. Add tests and documentation. Make 'make test' use -race.
This commit is contained in:
96
middleware/auto/walk.go
Normal file
96
middleware/auto/walk.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package auto
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/miekg/coredns/middleware/file"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Walk will recursively walk of the file under l.directory and adds the one that match l.re.
|
||||
func (z *Zones) Walk(l loader) error {
|
||||
|
||||
// TODO(miek): should add something so that we don't stomp on each other.
|
||||
|
||||
toDelete := make(map[string]bool)
|
||||
for _, n := range z.Names() {
|
||||
toDelete[n] = true
|
||||
}
|
||||
|
||||
filepath.Walk(l.directory, func(path string, info os.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
match, origin := matches(l.re, info.Name(), l.template)
|
||||
if !match {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, ok := z.Z[origin]; ok {
|
||||
// we already have this zone
|
||||
toDelete[origin] = false
|
||||
return nil
|
||||
}
|
||||
|
||||
reader, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Printf("[WARNING] Opening %s failed: %s", path, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
zo, err := file.Parse(reader, origin, path)
|
||||
if err != nil {
|
||||
// Parse barfs warning by itself...
|
||||
return nil
|
||||
}
|
||||
|
||||
zo.NoReload = l.noReload
|
||||
zo.TransferTo = l.transferTo
|
||||
|
||||
z.Insert(zo, origin)
|
||||
|
||||
zo.Notify()
|
||||
|
||||
log.Printf("[INFO] Inserting zone `%s' from: %s", origin, path)
|
||||
|
||||
toDelete[origin] = false
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
for origin, ok := range toDelete {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
z.Delete(origin)
|
||||
log.Printf("[INFO] Deleting zone `%s'", origin)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// matches matches re to filename, if is is a match, the subexpression will be used to expand
|
||||
// template to an origin. When match is true that origin is returned. Origin is fully qualified.
|
||||
func matches(re *regexp.Regexp, filename, template string) (match bool, origin string) {
|
||||
base := path.Base(filename)
|
||||
|
||||
matches := re.FindStringSubmatchIndex(base)
|
||||
if matches == nil {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
by := re.ExpandString(nil, template, base, matches)
|
||||
if by == nil {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
origin = dns.Fqdn(string(by))
|
||||
|
||||
return true, origin
|
||||
}
|
||||
Reference in New Issue
Block a user