bd4f8c5a8c
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
80 lines
1.9 KiB
Go
80 lines
1.9 KiB
Go
package diff
|
|
|
|
import "github.com/vasyakrg/dns-autoresolver/internal/model"
|
|
|
|
type ChangeKind string
|
|
|
|
const (
|
|
InSync ChangeKind = "in_sync"
|
|
Add ChangeKind = "add"
|
|
Update ChangeKind = "update"
|
|
Delete ChangeKind = "delete"
|
|
)
|
|
|
|
// RecordDiff describes one RRset's deviation between template and zone.
|
|
type RecordDiff struct {
|
|
Kind ChangeKind
|
|
Type model.RecordType
|
|
Name string
|
|
Desired *model.Record // nil for Delete
|
|
Actual *model.Record // nil for Add
|
|
ReadOnly bool // NS/SOA — shown but never applied
|
|
}
|
|
|
|
type Changeset struct {
|
|
Diffs []RecordDiff
|
|
}
|
|
|
|
// Actionable returns managed diffs that are not in sync.
|
|
func (c Changeset) Actionable() []RecordDiff {
|
|
var out []RecordDiff
|
|
for _, d := range c.Diffs {
|
|
if d.ReadOnly || d.Kind == InSync {
|
|
continue
|
|
}
|
|
out = append(out, d)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// Diff compares a template against the actual zone records.
|
|
// Records present in the zone but absent from the template yield Delete.
|
|
func Diff(template, actual []model.Record) Changeset {
|
|
current := index(actual)
|
|
seen := make(map[string]bool, len(template))
|
|
var diffs []RecordDiff
|
|
|
|
for _, t := range template {
|
|
tt := t
|
|
key := tt.Key()
|
|
seen[key] = true
|
|
ro := !tt.Type.Managed()
|
|
if a, ok := current[key]; ok {
|
|
ac := a
|
|
kind := Update
|
|
if tt.Equal(ac) {
|
|
kind = InSync
|
|
}
|
|
diffs = append(diffs, RecordDiff{Kind: kind, Type: tt.Type, Name: tt.Name, Desired: &tt, Actual: &ac, ReadOnly: ro})
|
|
} else {
|
|
diffs = append(diffs, RecordDiff{Kind: Add, Type: tt.Type, Name: tt.Name, Desired: &tt, ReadOnly: ro})
|
|
}
|
|
}
|
|
for _, a := range actual {
|
|
ac := a
|
|
if seen[ac.Key()] {
|
|
continue
|
|
}
|
|
diffs = append(diffs, RecordDiff{Kind: Delete, Type: ac.Type, Name: ac.Name, Actual: &ac, ReadOnly: !ac.Type.Managed()})
|
|
}
|
|
return Changeset{Diffs: diffs}
|
|
}
|
|
|
|
func index(recs []model.Record) map[string]model.Record {
|
|
m := make(map[string]model.Record, len(recs))
|
|
for _, r := range recs {
|
|
m[r.Key()] = r
|
|
}
|
|
return m
|
|
}
|