Add also-notify support for BIND domains.conf generation
Extend catz.yaml config with a bind-conf section mapping catalog names to also-notify IP lists. Zones in catalogs with also-notify configured get an also-notify directive in the generated domains.conf. IPs are deduplicated and sorted when a zone belongs to multiple catalogs.
This commit is contained in:
39
bindconf.go
39
bindconf.go
@@ -10,7 +10,8 @@ import (
|
||||
// generateBindConf produces a BIND domains.conf from all zone entries.
|
||||
// Zones are sorted alphabetically. Each zone block uses 8-space indentation.
|
||||
// DNSSEC zones get dnssec-policy and inline-signing directives on the file line.
|
||||
func generateBindConf(entries []ZoneEntry) string {
|
||||
// Zones in catalogs with also-notify configured get an also-notify directive.
|
||||
func generateBindConf(entries []ZoneEntry, cfg *Config) string {
|
||||
sorted := make([]ZoneEntry, len(entries))
|
||||
copy(sorted, entries)
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
@@ -38,16 +39,48 @@ func generateBindConf(entries []ZoneEntry) string {
|
||||
fileLine += " dnssec-policy standard; inline-signing yes;"
|
||||
}
|
||||
b.WriteString(fileLine + "\n")
|
||||
|
||||
// Collect also-notify IPs from all catalogs this zone belongs to
|
||||
ips := alsoNotifyIPs(entry.Catalogs, cfg)
|
||||
if len(ips) > 0 {
|
||||
b.WriteString(" also-notify {")
|
||||
for _, ip := range ips {
|
||||
fmt.Fprintf(&b, " %s;", ip)
|
||||
}
|
||||
b.WriteString(" };\n")
|
||||
}
|
||||
|
||||
b.WriteString("};\n")
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// alsoNotifyIPs returns the deduplicated, sorted list of also-notify IPs
|
||||
// for a zone based on its catalog memberships.
|
||||
func alsoNotifyIPs(catalogs []string, cfg *Config) []string {
|
||||
if len(cfg.BindConf.AlsoNotify) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
seen := make(map[string]bool)
|
||||
var ips []string
|
||||
for _, catName := range catalogs {
|
||||
for _, ip := range cfg.BindConf.AlsoNotify[catName] {
|
||||
if !seen[ip] {
|
||||
seen[ip] = true
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(ips)
|
||||
return ips
|
||||
}
|
||||
|
||||
// writeBindConf writes the BIND config to path.
|
||||
// Zones without a ZoneFile are skipped (catalog-only zones).
|
||||
func writeBindConf(path string, entries []ZoneEntry) error {
|
||||
content := generateBindConf(entries)
|
||||
func writeBindConf(path string, entries []ZoneEntry, cfg *Config) error {
|
||||
content := generateBindConf(entries, cfg)
|
||||
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||
return fmt.Errorf("writing bind config %s: %w", path, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user