retract apex NS from recorded state, not a live query
An unsigned localhost query silently returns nothing for a zone behind a BindView, which would strand the placeholder. Record what was published instead.
This commit is contained in:
@@ -22,36 +22,58 @@ func testCluster() *bindv1alpha1.BindCluster {
|
||||
const stableNS = "auth-0.auth-headless.bind-internal.svc.cluster.local."
|
||||
|
||||
func TestZoneNameservers(t *testing.T) {
|
||||
ttl60 := int32(60)
|
||||
cases := []struct {
|
||||
name string
|
||||
spec bindv1alpha1.BindZoneSpec
|
||||
want []string
|
||||
ttl int32
|
||||
declared bool
|
||||
}{
|
||||
{"fallback is out-of-zone, so it needs no glue", bindv1alpha1.BindZoneSpec{}, []string{stableNS}, false},
|
||||
{"declared wins", bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.unkin.net"}}, []string{"ns1.unkin.net."}, true},
|
||||
{"fallback is out-of-zone, so it needs no glue", bindv1alpha1.BindZoneSpec{}, []string{stableNS}, 3600, false},
|
||||
{"declared wins", bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.unkin.net"}}, []string{"ns1.unkin.net."}, 3600, true},
|
||||
{"spec.defaultTTL applies", bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.unkin.net."}, DefaultTTL: 60}, []string{"ns1.unkin.net."}, 60, true},
|
||||
// An apex NS in spec.records cannot converge on its own: BIND ignores an
|
||||
// RRset-wide delete at the apex, so it has to go through the apex path.
|
||||
{"apex NS in records counts as declared", bindv1alpha1.BindZoneSpec{Records: []bindv1alpha1.Record{
|
||||
{Name: "@", Type: "ns", Values: []string{"a.ns.unkin.net.", "b.ns.unkin.net."}},
|
||||
{Name: "www", Type: "A", Values: []string{"10.0.0.1"}},
|
||||
}}, []string{"a.ns.unkin.net.", "b.ns.unkin.net."}, true},
|
||||
}}, []string{"a.ns.unkin.net.", "b.ns.unkin.net."}, 3600, true},
|
||||
// A TTL on the apex NS record itself must survive the fold.
|
||||
{"record TTL beats the zone default", bindv1alpha1.BindZoneSpec{DefaultTTL: 3600, Records: []bindv1alpha1.Record{
|
||||
{Name: "@", Type: "NS", TTL: &ttl60, Values: []string{"a.ns.unkin.net."}},
|
||||
}}, []string{"a.ns.unkin.net."}, 60, true},
|
||||
{"spec.nameservers beats records", bindv1alpha1.BindZoneSpec{
|
||||
Nameservers: []string{"ns1.unkin.net."},
|
||||
Records: []bindv1alpha1.Record{{Name: "@", Type: "NS", Values: []string{"other.unkin.net."}}},
|
||||
}, []string{"ns1.unkin.net."}, true},
|
||||
}, []string{"ns1.unkin.net."}, 3600, true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got, declared := zoneNameservers(zoneWith(c.spec), testCluster())
|
||||
if declared != c.declared || strings.Join(got, ",") != strings.Join(c.want, ",") {
|
||||
t.Errorf("%s: got %v/%v; want %v/%v", c.name, got, declared, c.want, c.declared)
|
||||
got, ttl, declared := zoneNameservers(zoneWith(c.spec), testCluster())
|
||||
if declared != c.declared || ttl != c.ttl || strings.Join(got, ",") != strings.Join(c.want, ",") {
|
||||
t.Errorf("%s: got %v/%d/%v; want %v/%d/%v", c.name, got, ttl, declared, c.want, c.ttl, c.declared)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Before the operator has recorded anything, the only names it can have published
|
||||
// are the ones a seed writes; afterwards its record is the authority, so it never
|
||||
// retracts a name someone else added.
|
||||
func TestPublishedNameservers(t *testing.T) {
|
||||
zone := zoneWith(bindv1alpha1.BindZoneSpec{})
|
||||
want := "ns1.acme.unkin.net.," + stableNS
|
||||
if got := publishedNameservers(zone, testCluster()); strings.Join(got, ",") != want {
|
||||
t.Errorf("unrecorded: got %v; want %s", got, want)
|
||||
}
|
||||
zone.Status.Nameservers = []string{"a.ns.unkin.net."}
|
||||
if got := publishedNameservers(zone, testCluster()); strings.Join(got, ",") != "a.ns.unkin.net." {
|
||||
t.Errorf("recorded: got %v; want [a.ns.unkin.net.]", got)
|
||||
}
|
||||
}
|
||||
|
||||
// The apex NS RRset must be converged per record: an RRset-wide delete at the
|
||||
// apex is ignored by BIND, which would leave the placeholder published alongside
|
||||
// the real nameservers.
|
||||
// the real nameservers. Retracting an in-zone name takes its glue with it.
|
||||
func TestApexNSUpdatesConverges(t *testing.T) {
|
||||
zone := zoneWith(bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.unkin.net."}, DefaultTTL: 60})
|
||||
got := apexNSUpdates(zone, []string{"ns1.unkin.net."}, []string{"ns1.acme.unkin.net."}, 60)
|
||||
@@ -62,6 +84,18 @@ func TestApexNSUpdatesConverges(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// Glue retirement is not special-cased to the name ns1: the seed glues every
|
||||
// declared in-zone nameserver.
|
||||
func TestApexNSUpdatesRetiresAnyInZoneGlue(t *testing.T) {
|
||||
zone := zoneWith(bindv1alpha1.BindZoneSpec{Nameservers: []string{"a.ns.unkin.net."}})
|
||||
got := apexNSUpdates(zone, []string{"a.ns.unkin.net."}, []string{"dns.acme.unkin.net."}, 3600)
|
||||
assertUpdates(t, got, []bind.RecordUpdate{
|
||||
{FQDN: "acme.unkin.net.", Type: "NS", TTL: 3600, Values: []string{"a.ns.unkin.net."}, PerValue: true},
|
||||
{FQDN: "acme.unkin.net.", Type: "NS", Values: []string{"dns.acme.unkin.net."}, PerValue: true, Delete: true},
|
||||
{FQDN: "dns.acme.unkin.net.", Type: "A", Delete: true},
|
||||
})
|
||||
}
|
||||
|
||||
func TestApexNSUpdatesNoopWhenConverged(t *testing.T) {
|
||||
zone := zoneWith(bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.unkin.net"}})
|
||||
// Case differs: DNS names compare case-insensitively, so this is converged.
|
||||
@@ -80,7 +114,7 @@ func TestApexNSUpdatesPartialChange(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// A declared in-zone ns1 owns the glue; removing it would fail named's
|
||||
// A declared in-zone nameserver owns its glue; removing it would fail named's
|
||||
// post-update nameserver sanity check.
|
||||
func TestApexNSUpdatesKeepsNeededGlue(t *testing.T) {
|
||||
zone := zoneWith(bindv1alpha1.BindZoneSpec{Nameservers: []string{"ns1.acme.unkin.net."}})
|
||||
|
||||
Reference in New Issue
Block a user