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

BUG: diff2: ttl changes don't always work (#2093)

This commit is contained in:
Tom Limoncelli
2023-02-25 22:40:54 -05:00
committed by GitHub
parent ab872cc13f
commit 05dc26bf2e
8 changed files with 151 additions and 101 deletions

View File

@@ -179,58 +179,70 @@ func removeCommon(existing, desired []targetConfig) ([]targetConfig, []targetCon
// On the other hand, this function typically receives lists of 1-3 elements
// and any optimization is probably fruitless.
// Sort to make comparisons easier
sort.Slice(existing, func(i, j int) bool { return existing[i].comparableFull < existing[j].comparableFull })
sort.Slice(desired, func(i, j int) bool { return desired[i].comparableFull < desired[j].comparableFull })
eKeys := map[string]*targetConfig{}
for _, v := range existing {
v := v
eKeys[v.compareable] = &v
eKeys[v.comparableFull] = &v
}
dKeys := map[string]*targetConfig{}
for _, v := range desired {
v := v
dKeys[v.compareable] = &v
dKeys[v.comparableFull] = &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,
) {
// findTTLChanges finds the records that ONLY change their TTL. For those, generate a Change.
// Remove such items from the list.
func findTTLChanges(existing, desired []targetConfig) ([]targetConfig, []targetConfig, ChangeList) {
//fmt.Printf("DEBUG: findTTLChanges(%v,\n%v)\n", existing, desired)
if (len(existing) == 0) || (len(desired) == 0) {
return existing, desired, nil
}
// Sort to make comparisons easier
sort.Slice(existing, func(i, j int) bool { return existing[i].comparableNoTTL < existing[j].comparableNoTTL })
sort.Slice(desired, func(i, j int) bool { return desired[i].comparableNoTTL < desired[j].comparableNoTTL })
var instructions ChangeList
var existDiff, desiredDiff []targetConfig
ei := 0
di := 0
for (ei < len(existing)) && (di < len(desired)) {
er := existing[ei].rec
dr := desired[di].rec
ecomp := existing[ei].compareable
dcomp := desired[di].compareable
ecomp := existing[ei].comparableNoTTL
dcomp := desired[di].comparableNoTTL
if ecomp == dcomp && er.TTL == dr.TTL {
fmt.Printf("DEBUG: ecomp=%q dcomp=%q er.TTL=%v dr.TTL=%v\n", 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)
//m := fmt.Sprintf("CHANGE-TTL %s %s %s ttl=%d->%d", dr.NameFQDN, dr.Type, dr.GetTargetRFC1035Quoted(), er.TTL, dr.TTL)
m := fmt.Sprintf("CHANGE-TTL %s %s ", dr.NameFQDN, dr.Type) + humanDiff(existing[ei], desired[di])
instructions = append(instructions, mkChange(dr.NameFQDN, dr.Type, []string{m},
models.Records{er},
models.Records{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])
desiredDiff = append(desiredDiff, desired[di])
di++
} else {
panic("Should not happen. e and d can not be both equal, less and greater")
panic("should not happen. ecomp cant be both == and != dcomp")
}
}
// Any remainder goes to the *Diff result:
@@ -240,10 +252,10 @@ func splitTTLOnly(existing, desired []targetConfig) (
}
if di < len(desired) {
//fmt.Printf("DEBUG: append d len()=%d\n", di)
desireDiff = append(desireDiff, desired[di:]...)
desiredDiff = append(desiredDiff, desired[di:]...)
}
return
return existDiff, desiredDiff, instructions
}
// Return s but remove any items that can be found in m.
@@ -254,8 +266,8 @@ func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig {
// }
i := 0 // output index
for _, x := range s {
if _, ok := m[x.compareable]; !ok {
//fmt.Printf("DEBUG: comp %q NO\n", x.compareable)
if _, ok := m[x.comparableFull]; !ok {
//fmt.Printf("DEBUG: comp %q NO\n", x.comparable)
// copy and increment index
s[i] = x
i++
@@ -271,22 +283,19 @@ func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig {
return s
}
// humanDiff returns a human-friendly string showing what changed
// between a and b.
func humanDiff(a, b targetConfig) string {
aTTL := a.rec.TTL
bTTL := b.rec.TTL
acombined := a.compareable
bcombined := b.compareable
combinedDiff := acombined != bcombined
ttlDiff := aTTL != bTTL
// TODO(tlim): Records like MX and SRV should have more clever output.
// For example if only the MX priority changes, show that.
if combinedDiff && ttlDiff {
return fmt.Sprintf("(%s ttl=%d) -> (%s ttl=%d)", acombined, aTTL, bcombined, bTTL)
// For example if only the MX priority changes, show just that.
if a.comparableNoTTL != b.comparableNoTTL {
// The recorddata is different:
return fmt.Sprintf("(%s) -> (%s)", a.comparableFull, b.comparableFull)
}
if combinedDiff {
return fmt.Sprintf("(%s) -> (%s)", acombined, bcombined)
}
return fmt.Sprintf("%s (ttl %d->%d)", acombined, aTTL, bTTL)
// Just the TTLs are different:
return fmt.Sprintf("%s ttl=(%d->%d)", a.comparableNoTTL, a.rec.TTL, b.rec.TTL)
}
func diffTargets(existing, desired []targetConfig) ChangeList {
@@ -298,15 +307,11 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
return nil
}
// Sort to make comparisons easier
sort.Slice(existing, func(i, j int) bool { return existing[i].compareable < existing[j].compareable })
sort.Slice(desired, func(i, j int) bool { return desired[i].compareable < desired[j].compareable })
var instructions ChangeList
// remove the exact matches.
//fmt.Printf("DEBUG: diffTargets BEFORE existing=%+v\n", existing)
//fmt.Printf("DEBUG: diffTargets BEFORE desired=%+v\n", desired)
// remove the exact matches.
existing, desired = removeCommon(existing, desired)
//fmt.Printf("DEBUG: diffTargets AFTER existing=%+v\n", existing)
//fmt.Printf("DEBUG: diffTargets AFTER desired=%+v\n", desired)
@@ -315,23 +320,16 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
// 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]
existing, desired, newChanges := findTTLChanges(existing, desired)
instructions = append(instructions, newChanges...)
m := fmt.Sprintf("CHANGE %s %s ", dr.NameFQDN, dr.Type) + humanDiff(existing[i], desired[i])
// Sort to make comparisons easier
sort.Slice(existing, func(i, j int) bool { return existing[i].comparableFull < existing[j].comparableFull })
sort.Slice(desired, func(i, j int) bool { return desired[i].comparableFull < desired[j].comparableFull })
instructions = append(instructions, mkChange(dr.NameFQDN, dr.Type, []string{m},
models.Records{er},
models.Records{dr},
))
}
// the common chunk are changes (regardless of TTL)
// the remaining chunks 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
@@ -349,7 +347,7 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
for i := mi; i < len(existing); i++ {
//fmt.Println(i, "DEL")
er := existing[i].rec
m := fmt.Sprintf("DELETE %s %s %s", er.NameFQDN, er.Type, existing[i].compareable)
m := fmt.Sprintf("DELETE %s %s %s", er.NameFQDN, er.Type, existing[i].comparableFull)
instructions = append(instructions, mkDeleteRec(er.NameFQDN, er.Type, []string{m}, er))
}
@@ -357,7 +355,7 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
for i := mi; i < len(desired); i++ {
//fmt.Println(i, "CREATE")
dr := desired[i].rec
m := fmt.Sprintf("CREATE %s %s %s", dr.NameFQDN, dr.Type, desired[i].compareable)
m := fmt.Sprintf("CREATE %s %s %s", dr.NameFQDN, dr.Type, desired[i].comparableFull)
instructions = append(instructions, mkAdd(dr.NameFQDN, dr.Type, []string{m}, models.Records{dr}))
}