Inspect zone file and journal before seeding a zone
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful

Fixes #19
This commit is contained in:
2026-09-19 22:33:48 +10:00
parent 8d5a231a78
commit f1d47c8ff7
4 changed files with 491 additions and 9 deletions
+12 -8
View File
@@ -26,13 +26,11 @@ func (e *Executor) ZoneExists(ctx context.Context, namespace, pod, zone, view st
return err == nil
}
// WriteSeedZone writes a minimal loadable zone file (SOA + apex NS + glue) to
// path, creating parent directories. The apex NS is the in-zone name ns1, and a
// glue A record pointing at primaryIP is included so BIND's check-integrity
// accepts the zone (an in-zone NS without an address record is a load error).
// It is only safe to call when creating a zone, as it overwrites any existing
// file. This is a placeholder that is replaced once real records are loaded.
func (e *Executor) WriteSeedZone(ctx context.Context, namespace, pod, zone, path, primaryIP string, serial int64) error {
// renderSeedZone renders a minimal loadable zone (SOA + apex NS + glue). The
// apex NS is the in-zone name ns1, and a glue A record pointing at primaryIP is
// included so BIND's check-integrity accepts the zone (an in-zone NS without an
// address record is a load error).
func renderSeedZone(zone, primaryIP string, serial int64) string {
origin := dot(zone)
ns := "ns1." + origin
// Short refresh/retry so a secondary that misses a NOTIFY (e.g. its pod IP
@@ -41,7 +39,7 @@ func (e *Executor) WriteSeedZone(ctx context.Context, namespace, pod, zone, path
// negative-cache TTL: keep it low so a stale-secondary NXDOMAIN does not
// stick in downstream resolvers for long. NOTIFY (also-notify on the
// primary) remains the fast path; these are the fallback.
content := fmt.Sprintf(`$TTL 3600
return fmt.Sprintf(`$TTL 3600
@ IN SOA %s hostmaster.%s (
%d ; serial
300 ; refresh
@@ -51,7 +49,13 @@ func (e *Executor) WriteSeedZone(ctx context.Context, namespace, pod, zone, path
@ IN NS %s
ns1 IN A %s
`, ns, origin, serial, ns, primaryIP)
}
// WriteSeedZone writes a seed zone file to path, creating parent directories.
// It overwrites any existing file, so callers must clear it with PlanSeed
// first. This is a placeholder that is replaced once real records are loaded.
func (e *Executor) WriteSeedZone(ctx context.Context, namespace, pod, zone, path, primaryIP string, serial int64) error {
content := renderSeedZone(zone, primaryIP, serial)
cmd := []string{"sh", "-c", fmt.Sprintf("mkdir -p \"$(dirname '%s')\" && cat > '%s'", path, path)}
if out, err := e.Exec(ctx, namespace, pod, cmd, content); err != nil {
return fmt.Errorf("seed zone %s: %w (out: %s)", zone, err, out)