99 lines
3.5 KiB
Go
99 lines
3.5 KiB
Go
package controller
|
|
|
|
import (
|
|
"testing"
|
|
|
|
bindv1alpha1 "git.unkin.net/unkin/bind-operator/api/v1alpha1"
|
|
"git.unkin.net/unkin/bind-operator/internal/bind"
|
|
)
|
|
|
|
func zoneWith(spec bindv1alpha1.BindZoneSpec) *bindv1alpha1.BindZone {
|
|
spec.ZoneName = "acme.unkin.net"
|
|
return &bindv1alpha1.BindZone{Spec: spec}
|
|
}
|
|
|
|
func TestZoneNameserversFallbackIsOutOfZone(t *testing.T) {
|
|
cluster := &bindv1alpha1.BindCluster{}
|
|
cluster.Name, cluster.Namespace = "auth", "bind-internal"
|
|
got := zoneNameservers(nil, cluster)
|
|
want := "auth-0.auth-headless.bind-internal.svc.cluster.local."
|
|
if len(got) != 1 || got[0] != want {
|
|
t.Fatalf("fallback = %v; want [%s]", got, want)
|
|
}
|
|
if got := zoneNameservers([]string{"ns1.unkin.net."}, cluster); got[0] != "ns1.unkin.net." {
|
|
t.Fatalf("declared nameservers must win, got %v", got)
|
|
}
|
|
}
|
|
|
|
func TestApexNSUpdatesReplacesRRsetAndDropsGlue(t *testing.T) {
|
|
zone := zoneWith(bindv1alpha1.BindZoneSpec{
|
|
Nameservers: []string{"ns1.unkin.net", "ns2.unkin.net."},
|
|
DefaultTTL: 300,
|
|
})
|
|
got := apexNSUpdates(zone, zone.Spec.Nameservers)
|
|
want := []bind.RecordUpdate{
|
|
{FQDN: "acme.unkin.net.", Type: "NS", TTL: 300, Values: []string{"ns1.unkin.net.", "ns2.unkin.net."}},
|
|
{FQDN: "ns1.acme.unkin.net.", Type: "A", Delete: true},
|
|
}
|
|
assertUpdates(t, got, want)
|
|
}
|
|
|
|
// Without declared nameservers the apex NS still converges onto the stable
|
|
// primary name, but the ns1 glue is left alone: it may be a real record.
|
|
func TestApexNSUpdatesFallbackKeepsGlue(t *testing.T) {
|
|
zone := zoneWith(bindv1alpha1.BindZoneSpec{})
|
|
got := apexNSUpdates(zone, []string{"auth-0.auth-headless.bind-internal.svc.cluster.local."})
|
|
want := []bind.RecordUpdate{{
|
|
FQDN: "acme.unkin.net.",
|
|
Type: "NS",
|
|
TTL: 3600,
|
|
Values: []string{"auth-0.auth-headless.bind-internal.svc.cluster.local."},
|
|
}}
|
|
assertUpdates(t, got, want)
|
|
}
|
|
|
|
// spec.records is applied after the apex sync, so anything it owns must not be
|
|
// touched here: the ops would be undone and the serial would churn every pass.
|
|
func TestApexNSUpdatesYieldsToRecords(t *testing.T) {
|
|
zone := zoneWith(bindv1alpha1.BindZoneSpec{
|
|
Nameservers: []string{"ns1.unkin.net."},
|
|
Records: []bindv1alpha1.Record{
|
|
{Name: "@", Type: "ns", Values: []string{"ns.other.net."}},
|
|
{Name: "ns1", Type: "A", Values: []string{"10.0.0.53"}},
|
|
},
|
|
})
|
|
if got := apexNSUpdates(zone, zone.Spec.Nameservers); len(got) != 0 {
|
|
t.Fatalf("expected no updates, got %+v", got)
|
|
}
|
|
}
|
|
|
|
// A declared in-zone nameserver owns the ns1 record; it is glue, not a leftover.
|
|
func TestApexNSUpdatesKeepsDeclaredNs1Glue(t *testing.T) {
|
|
zone := zoneWith(bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.acme.unkin.net"}})
|
|
got := apexNSUpdates(zone, zone.Spec.Nameservers)
|
|
want := []bind.RecordUpdate{{FQDN: "acme.unkin.net.", Type: "NS", TTL: 3600, Values: []string{"ns1.acme.unkin.net."}}}
|
|
assertUpdates(t, got, want)
|
|
}
|
|
|
|
func assertUpdates(t *testing.T, got, want []bind.RecordUpdate) {
|
|
t.Helper()
|
|
if len(got) != len(want) {
|
|
t.Fatalf("got %d updates %+v; want %d %+v", len(got), got, len(want), want)
|
|
}
|
|
for i := range want {
|
|
if got[i].FQDN != want[i].FQDN || got[i].Type != want[i].Type || got[i].TTL != want[i].TTL || got[i].Delete != want[i].Delete {
|
|
t.Errorf("update %d = %+v; want %+v", i, got[i], want[i])
|
|
continue
|
|
}
|
|
if len(got[i].Values) != len(want[i].Values) {
|
|
t.Errorf("update %d values = %v; want %v", i, got[i].Values, want[i].Values)
|
|
continue
|
|
}
|
|
for j := range want[i].Values {
|
|
if got[i].Values[j] != want[i].Values[j] {
|
|
t.Errorf("update %d value %d = %q; want %q", i, j, got[i].Values[j], want[i].Values[j])
|
|
}
|
|
}
|
|
}
|
|
}
|