Files
bind-operator/internal/controller/zone_helpers_test.go
T
unkinben fe5fbdaf6d 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
2026-07-03 15:48:13 +10:00

80 lines
2.5 KiB
Go

package controller
import (
"testing"
bindv1alpha1 "git.unkin.net/unkin/bind-operator/api/v1alpha1"
)
func TestFQDN(t *testing.T) {
cases := []struct{ name, zone, want string }{
{"@", "example.com", "example.com."},
{"", "example.com", "example.com."},
{"www", "example.com", "www.example.com."},
{"www.example.com.", "example.com", "www.example.com."},
{"host", "10.in-addr.arpa", "host.10.in-addr.arpa."},
}
for _, c := range cases {
if got := fqdn(c.name, c.zone); got != c.want {
t.Errorf("fqdn(%q,%q)=%q want %q", c.name, c.zone, got, c.want)
}
}
}
func TestRecordsToUpdatesTTLFallback(t *testing.T) {
custom := int32(60)
records := []bindv1alpha1.Record{
{Name: "@", Type: "A", Values: []string{"192.0.2.1"}},
{Name: "low", Type: "A", TTL: &custom, Values: []string{"192.0.2.2"}},
}
updates := recordsToUpdates("example.com", records, 3600)
if len(updates) != 2 {
t.Fatalf("expected 2 updates, got %d", len(updates))
}
if updates[0].TTL != 3600 {
t.Errorf("expected default TTL 3600, got %d", updates[0].TTL)
}
if updates[1].TTL != 60 {
t.Errorf("expected record TTL 60, got %d", updates[1].TTL)
}
if updates[0].FQDN != "example.com." {
t.Errorf("apex FQDN wrong: %s", updates[0].FQDN)
}
}
func TestRPZRulesToUpdates(t *testing.T) {
rules := []bindv1alpha1.RPZRule{
{Trigger: "qname", Match: "bad.example.com", Action: "nxdomain"},
{Trigger: "qname", Match: "walled.example.com", Action: "cname", Target: "block.internal"},
}
updates := rpzRulesToUpdates("rpz.internal", rules)
if len(updates) != 2 {
t.Fatalf("expected 2 updates, got %d", len(updates))
}
if updates[0].FQDN != "bad.example.com.rpz.internal." {
t.Errorf("qname owner wrong: %s", updates[0].FQDN)
}
if updates[0].Values[0] != "." {
t.Errorf("nxdomain rdata should be '.', got %q", updates[0].Values[0])
}
if updates[1].Values[0] != "block.internal." {
t.Errorf("cname rdata wrong: %q", updates[1].Values[0])
}
}
func TestCatalogEnabledDefault(t *testing.T) {
on := &bindv1alpha1.BindZone{Spec: bindv1alpha1.BindZoneSpec{Type: bindv1alpha1.ZonePrimary}}
if !catalogEnabled(on) {
t.Error("primary zone should default to catalog enabled")
}
no := false
off := &bindv1alpha1.BindZone{Spec: bindv1alpha1.BindZoneSpec{Type: bindv1alpha1.ZonePrimary, Catalog: &no}}
if catalogEnabled(off) {
t.Error("catalog=false should disable membership")
}
sec := &bindv1alpha1.BindZone{Spec: bindv1alpha1.BindZoneSpec{Type: bindv1alpha1.ZoneSecondary}}
if catalogEnabled(sec) {
t.Error("secondary zone should never be a catalog member")
}
}