Files
bind-operator/internal/controller/zone_helpers_test.go
unkin-agent afb4fe2631
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
reject an apex NS DNSRecord instead of appending to the live RRset
BIND ignores an RRset-wide delete at a zone apex, so a DNSRecord for the
apex NS can only add to what the zone was seeded with while reporting
success. BindZone.spec.nameservers converges it per rdata.
2026-09-27 10:58:45 +10:00

106 lines
3.2 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")
}
}
func TestIsApexNS(t *testing.T) {
const zone = "acme.unkin.net"
cases := []struct {
name, typ string
want bool
}{
{"@", "NS", true},
{"", "NS", true},
{"acme.unkin.net.", "NS", true},
{"ACME.UNKIN.NET.", "ns", true},
{"@", "ns", true},
// No trailing dot means relative: acme.unkin.net.acme.unkin.net.
{"acme.unkin.net", "NS", false},
{"sub", "NS", false},
{"ns1", "NS", false},
{"@", "TXT", false},
{"@", "MX", false},
{"@", "SOA", false},
}
for _, c := range cases {
if got := isApexNS(c.name, c.typ, zone); got != c.want {
t.Errorf("isApexNS(%q,%q)=%v want %v", c.name, c.typ, got, c.want)
}
}
}