Zones without a file= property (e.g. ddns zones) are included in catalog zone output for secondaries but skipped in domains.conf. Previously --bind-conf required every zone to have file= set.
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// 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 {
|
|
sorted := make([]ZoneEntry, len(entries))
|
|
copy(sorted, entries)
|
|
sort.Slice(sorted, func(i, j int) bool {
|
|
return sorted[i].Zone < sorted[j].Zone
|
|
})
|
|
|
|
var b strings.Builder
|
|
b.WriteString("# THIS FILE IS GENERATED BY catalog-zone-gen\n")
|
|
b.WriteString("#=============================================\n")
|
|
b.WriteString("#\n")
|
|
|
|
for _, entry := range sorted {
|
|
if entry.ZoneFile == "" {
|
|
continue // catalog-only zone, no BIND config needed
|
|
}
|
|
|
|
// Strip trailing dot for BIND zone name
|
|
zoneName := strings.TrimSuffix(entry.Zone, ".")
|
|
|
|
fmt.Fprintf(&b, "zone \"%s\" {\n", zoneName)
|
|
b.WriteString(" type master;\n")
|
|
|
|
fileLine := fmt.Sprintf(" file \"%s\";", entry.ZoneFile)
|
|
if entry.DNSSEC {
|
|
fileLine += " dnssec-policy standard; inline-signing yes;"
|
|
}
|
|
b.WriteString(fileLine + "\n")
|
|
b.WriteString("};\n")
|
|
}
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// 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)
|
|
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
|
return fmt.Errorf("writing bind config %s: %w", path, err)
|
|
}
|
|
return nil
|
|
}
|