1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

REFACTOR: Add a backwards compatible interface to diff2 (#1870)

This commit is contained in:
Tom Limoncelli
2022-12-30 21:53:50 -05:00
committed by GitHub
parent 801aae725b
commit 397ce107e5
9 changed files with 476 additions and 67 deletions

View File

@@ -123,7 +123,7 @@ func mkAdd(l string, t string, msgs []string, recs models.Records) Change {
func mkAddByLabel(l string, t string, msgs []string, newRecs models.Records) Change {
//fmt.Printf("DEBUG: mkAddByLabel: len(o)=%d len(m)=%d\n", len(newRecs), len(msgs))
//fmt.Printf("DEBUG: mkAddByLabel: msgs = %v\n", msgs)
c := Change{Type: CREATE, Msgs: msgs}
c := Change{Type: CREATE, Msgs: msgs, MsgsJoined: strings.Join(msgs, "\n")}
c.Key.NameFQDN = l
c.Key.Type = t
c.New = newRecs
@@ -131,7 +131,7 @@ func mkAddByLabel(l string, t string, msgs []string, newRecs models.Records) Cha
}
func mkChange(l string, t string, msgs []string, oldRecs, newRecs models.Records) Change {
c := Change{Type: CHANGE, Msgs: msgs}
c := Change{Type: CHANGE, Msgs: msgs, MsgsJoined: strings.Join(msgs, "\n")}
c.Key.NameFQDN = l
c.Key.Type = t
c.Old = oldRecs
@@ -141,7 +141,7 @@ func mkChange(l string, t string, msgs []string, oldRecs, newRecs models.Records
func mkChangeLabel(l string, t string, msgs []string, oldRecs, newRecs models.Records, msgsByKey map[models.RecordKey][]string) Change {
//fmt.Printf("DEBUG: mkChangeLabel: len(o)=%d\n", len(oldRecs))
c := Change{Type: CHANGE, Msgs: msgs}
c := Change{Type: CHANGE, Msgs: msgs, MsgsJoined: strings.Join(msgs, "\n")}
c.Key.NameFQDN = l
c.Key.Type = t
c.Old = oldRecs
@@ -151,14 +151,14 @@ func mkChangeLabel(l string, t string, msgs []string, oldRecs, newRecs models.Re
}
func mkDelete(l string, t string, oldRecs models.Records, msgs []string) Change {
c := Change{Type: DELETE, Msgs: msgs}
c := Change{Type: DELETE, Msgs: msgs, MsgsJoined: strings.Join(msgs, "\n")}
c.Key.NameFQDN = l
c.Key.Type = t
c.Old = oldRecs
return c
}
func mkDeleteRec(l string, t string, msgs []string, rec *models.RecordConfig) Change {
c := Change{Type: DELETE, Msgs: msgs}
c := Change{Type: DELETE, Msgs: msgs, MsgsJoined: strings.Join(msgs, "\n")}
c.Key.NameFQDN = l
c.Key.Type = t
c.Old = models.Records{rec}
@@ -175,16 +175,70 @@ func removeCommon(existing, desired []targetConfig) ([]targetConfig, []targetCon
eKeys := map[string]*targetConfig{}
for _, v := range existing {
v := v
eKeys[v.compareable] = &v
}
dKeys := map[string]*targetConfig{}
for _, v := range desired {
v := v
dKeys[v.compareable] = &v
}
return filterBy(existing, dKeys), filterBy(desired, eKeys)
}
// Find the changes that are exclusively changes in TTL.
func splitTTLOnly(existing, desired []targetConfig) (
existDiff []targetConfig, desireDiff []targetConfig,
existTTL models.Records, desireTTL models.Records,
) {
ei := 0
di := 0
for (ei < len(existing)) && (di < len(desired)) {
er := existing[ei].rec
dr := desired[di].rec
ecomp := er.GetTargetCombined()
dcomp := dr.GetTargetCombined()
if ecomp == dcomp && er.TTL == dr.TTL {
panic("Should not happen. There should be some difference!")
}
//fmt.Printf("DEBUG ecomp=%q dcomp=%q ettl=%d dttl=%d\n", ecomp, dcomp, er.TTL, dr.TTL)
if ecomp == dcomp && er.TTL != dr.TTL {
//fmt.Printf("DEBUG: equal\n")
existTTL = append(existTTL, er)
desireTTL = append(desireTTL, dr)
ei++
di++
} else if ecomp < dcomp {
//fmt.Printf("DEBUG: less\n")
existDiff = append(existDiff, existing[ei])
ei++
} else if ecomp > dcomp {
//fmt.Printf("DEBUG: greater\n")
desireDiff = append(desireDiff, desired[di])
di++
} else {
panic("Should not happen. e and d can not be both equal, less and greater")
}
}
// Any remainder goes to the *Diff result:
if ei < len(existing) {
//fmt.Printf("DEBUG: append e len()=%d\n", ei)
existDiff = append(existDiff, existing[ei:]...)
}
if di < len(desired) {
//fmt.Printf("DEBUG: append d len()=%d\n", di)
desireDiff = append(desireDiff, desired[di:]...)
}
return
}
// Return s but remove any items that can be found in m.
func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig {
// fmt.Printf("DEBUG: filterBy called with %v\n", s)
@@ -212,6 +266,22 @@ func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig {
return s
}
func humanDiff(a, b *models.RecordConfig) string {
acombined := a.GetTargetCombined()
bcombined := b.GetTargetCombined()
combinedDiff := acombined != bcombined
ttlDiff := a.TTL != b.TTL
// TODO(tlim): It would be nice if we included special cases for MX
// records and others.
if combinedDiff && ttlDiff {
return fmt.Sprintf("(%s ttl=%d) -> (%s ttl=%d)", acombined, a.TTL, bcombined, b.TTL)
}
if combinedDiff {
return fmt.Sprintf("(%s) -> (%s)", acombined, bcombined)
}
return fmt.Sprintf("%s (ttl %d->%d)", acombined, a.TTL, b.TTL)
}
func diffTargets(existing, desired []targetConfig) ChangeList {
//fmt.Printf("DEBUG: diffTargets called with len(e)=%d len(d)=%d\n", len(existing), len(desired))
@@ -230,17 +300,35 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
// remove the exact matches.
existing, desired = removeCommon(existing, desired)
// the common chunk are changes
// At this point the exact matches are removed. However there may be
// records that have the same GetTargetCombined() but different
// TTLs.
// Find TTL changes:
existing, desired, existingTTL, desiredTTL := splitTTLOnly(existing, desired)
for i := range desiredTTL {
er := existingTTL[i]
dr := desiredTTL[i]
m := fmt.Sprintf("CHANGE %s %s ", dr.NameFQDN, dr.Type) + humanDiff(er, dr)
instructions = append(instructions, mkChange(dr.NameFQDN, dr.Type, []string{m},
models.Records{er},
models.Records{dr},
))
}
// the common chunk are changes (regardless of TTL)
mi := min(len(existing), len(desired))
//fmt.Printf("DEBUG: min=%d\n", mi)
for i := 0; i < mi; i++ {
//fmt.Println(i, "CHANGE")
er := existing[i].rec
dr := desired[i].rec
m := fmt.Sprintf("CHANGE %s %s (%s) -> (%s)", dr.NameFQDN, dr.Type, er.GetTargetCombined(), dr.GetTargetCombined())
m := fmt.Sprintf("CHANGE %s %s ", dr.NameFQDN, dr.Type) + humanDiff(existing[i].rec, desired[i].rec)
instructions = append(instructions, mkChange(dr.NameFQDN, dr.Type, []string{m},
//models.Records{existing[i].rec},
//models.Records{desired[i].rec},
models.Records{er},
models.Records{dr},
))