test(diff): пустой шаблон — массовый Delete управляемых, NS остаётся ReadOnly
This commit is contained in:
@@ -59,6 +59,46 @@ func TestDiffMarksReadOnlyForNSSOA(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global Constraint: an empty/nil template must not silently no-op — every managed
|
||||||
|
// record in the zone must surface as a Delete, while read-only records (NS/SOA)
|
||||||
|
// stay ReadOnly and excluded from Actionable(). This guards against mass deletion
|
||||||
|
// bugs where a missing template accidentally wipes the zone unattended.
|
||||||
|
func TestDiffEmptyTemplateDeletesAllManagedKeepsNSReadOnly(t *testing.T) {
|
||||||
|
actual := []model.Record{
|
||||||
|
{Type: model.A, Name: "a.example.com.", TTL: 300, Values: []string{"1.1.1.1"}},
|
||||||
|
{Type: model.A, Name: "b.example.com.", TTL: 300, Values: []string{"2.2.2.2"}},
|
||||||
|
{Type: model.NS, Name: "example.com.", TTL: 3600, Values: []string{"ns1.example.com."}},
|
||||||
|
}
|
||||||
|
cs := Diff(nil, actual)
|
||||||
|
|
||||||
|
if len(cs.Diffs) != 3 {
|
||||||
|
t.Fatalf("expected 3 diffs (2 A deletes + 1 NS), got %d: %+v", len(cs.Diffs), cs.Diffs)
|
||||||
|
}
|
||||||
|
|
||||||
|
da := find(cs, "A a.example.com.")
|
||||||
|
if da == nil || da.Kind != Delete || da.ReadOnly {
|
||||||
|
t.Fatalf("A a.example.com. must be a non-read-only Delete, got %+v", da)
|
||||||
|
}
|
||||||
|
db := find(cs, "A b.example.com.")
|
||||||
|
if db == nil || db.Kind != Delete || db.ReadOnly {
|
||||||
|
t.Fatalf("A b.example.com. must be a non-read-only Delete, got %+v", db)
|
||||||
|
}
|
||||||
|
dns := find(cs, "NS example.com.")
|
||||||
|
if dns == nil || dns.Kind != Delete || !dns.ReadOnly {
|
||||||
|
t.Fatalf("NS example.com. must be a ReadOnly Delete, got %+v", dns)
|
||||||
|
}
|
||||||
|
|
||||||
|
act := cs.Actionable()
|
||||||
|
if len(act) != 2 {
|
||||||
|
t.Fatalf("expected 2 actionable deletes (A records only), got %d: %+v", len(act), act)
|
||||||
|
}
|
||||||
|
for _, d := range act {
|
||||||
|
if d.Type == model.NS {
|
||||||
|
t.Fatalf("NS must be excluded from Actionable(), got %+v", d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestActionableExcludesInSyncAndReadOnly(t *testing.T) {
|
func TestActionableExcludesInSyncAndReadOnly(t *testing.T) {
|
||||||
tmpl := []model.Record{
|
tmpl := []model.Record{
|
||||||
{Type: model.A, Name: "a.example.com.", TTL: 300, Values: []string{"1.1.1.1"}}, // in sync
|
{Type: model.A, Name: "a.example.com.", TTL: 300, Values: []string{"1.1.1.1"}}, // in sync
|
||||||
|
|||||||
Reference in New Issue
Block a user