Initial bind-operator: 9 CRDs + controllers
Implements a Kubernetes operator that manages fleets of BIND9 servers declaratively, using controller-runtime (matching forgebot conventions). - add BindCluster reconciler: StatefulSet (pod-0 primary, secondaries), headless + client Services, rendered named.conf ConfigMap, TSIG keys Secret and rndc control Secret; watches dependent CRs to re-render - add BindTSIGKey reconciler that generates key material into a Secret - add BindZone/DNSRecord reconcilers using fully-dynamic delivery (rndc addzone + TSIG nsupdate against the primary pod) - add BindCatalogZone reconciler so secondaries auto-provision zones - add BindPolicy (RPZ), BindDNSSECPolicy, BindView, BindACL reconcilers - render primary/secondary named.conf variants selected by pod ordinal - generate CRDs, deepcopy and RBAC; add samples mapping the three Puppet roles (authoritative/resolver/external-dns) to three BindClusters - add Makefile, Dockerfile.operator, Woodpecker CI and kind manifests
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package bind
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ZoneFilePath returns the on-pod path of a zone database file.
|
||||
func ZoneFilePath(zone string) string {
|
||||
return fmt.Sprintf("%s/zones/db.%s", DataDir, strings.TrimSuffix(zone, "."))
|
||||
}
|
||||
|
||||
// CatalogFilePath returns the on-pod path of a catalog zone database file.
|
||||
func CatalogFilePath(zone string) string {
|
||||
return fmt.Sprintf("%s/catalog/db.%s", DataDir, strings.TrimSuffix(zone, "."))
|
||||
}
|
||||
|
||||
// ZoneExists reports whether a zone is currently loaded on the pod.
|
||||
func (e *Executor) ZoneExists(ctx context.Context, namespace, pod, zone, view string) bool {
|
||||
args := []string{"zonestatus", zone}
|
||||
if view != "" {
|
||||
args = append(args, "in", view)
|
||||
}
|
||||
_, err := e.Rndc(ctx, namespace, pod, args...)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// WriteSeedZone writes a minimal loadable zone file (SOA + apex NS) to path,
|
||||
// creating parent directories. It is only safe to call when creating a zone, as
|
||||
// it overwrites any existing file.
|
||||
func (e *Executor) WriteSeedZone(ctx context.Context, namespace, pod, zone, path, primaryNS string, serial int64) error {
|
||||
origin := dot(zone)
|
||||
if primaryNS == "" {
|
||||
primaryNS = "ns1." + origin
|
||||
}
|
||||
content := fmt.Sprintf(`$TTL 3600
|
||||
@ IN SOA %s hostmaster.%s (
|
||||
%d ; serial
|
||||
3600 ; refresh
|
||||
900 ; retry
|
||||
1209600 ; expire
|
||||
300 ) ; minimum
|
||||
@ IN NS %s
|
||||
`, dot(primaryNS), origin, serial, dot(primaryNS))
|
||||
|
||||
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)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddCatalogMember registers a member zone in a catalog zone by adding the
|
||||
// catalog PTR record, so secondaries auto-provision it.
|
||||
func (e *Executor) AddCatalogMember(ctx context.Context, namespace, pod, catalogZone, memberZone string, creds TSIGCreds) error {
|
||||
hash := catalogHash(memberZone)
|
||||
owner := fmt.Sprintf("%s.zones.%s", hash, dot(catalogZone))
|
||||
updates := []RecordUpdate{{
|
||||
FQDN: owner,
|
||||
Type: "PTR",
|
||||
TTL: 3600,
|
||||
Values: []string{dot(memberZone)},
|
||||
}}
|
||||
return e.NSUpdate(ctx, namespace, pod, catalogZone, creds, updates)
|
||||
}
|
||||
|
||||
// RemoveCatalogMember deregisters a member zone from a catalog zone.
|
||||
func (e *Executor) RemoveCatalogMember(ctx context.Context, namespace, pod, catalogZone, memberZone string, creds TSIGCreds) error {
|
||||
hash := catalogHash(memberZone)
|
||||
owner := fmt.Sprintf("%s.zones.%s", hash, dot(catalogZone))
|
||||
updates := []RecordUpdate{{FQDN: owner, Type: "PTR", Delete: true}}
|
||||
return e.NSUpdate(ctx, namespace, pod, catalogZone, creds, updates)
|
||||
}
|
||||
Reference in New Issue
Block a user