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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 476 additions and 67 deletions

View file

@ -703,8 +703,18 @@ func makeTests(t *testing.T) []*TestGroup {
tc("Change single target from set", ttl(a("@", "1.2.3.4"), 1000), a("www", "2.2.2.2"), a("www", "5.6.7.8")), tc("Change single target from set", ttl(a("@", "1.2.3.4"), 1000), a("www", "2.2.2.2"), a("www", "5.6.7.8")),
tc("Change all ttls", ttl(a("@", "1.2.3.4"), 500), ttl(a("www", "2.2.2.2"), 400), ttl(a("www", "5.6.7.8"), 400)), tc("Change all ttls", ttl(a("@", "1.2.3.4"), 500), ttl(a("www", "2.2.2.2"), 400), ttl(a("www", "5.6.7.8"), 400)),
tc("Delete one", ttl(a("@", "1.2.3.4"), 500), ttl(a("www", "5.6.7.8"), 400)), tc("Delete one", ttl(a("@", "1.2.3.4"), 500), ttl(a("www", "5.6.7.8"), 400)),
tc("Add back and change ttl", ttl(a("www", "5.6.7.8"), 700), ttl(a("www", "1.2.3.4"), 700)), ),
tc("Change targets and ttls", a("www", "1.1.1.1"), a("www", "2.2.2.2")),
testgroup("add to existing label",
tc("Setup", ttl(a("www", "5.6.7.8"), 400)),
tc("Add at same label", ttl(a("www", "5.6.7.8"), 400), ttl(a("www", "1.2.3.4"), 400)),
),
// This is a strange one. It adds a new record to an existing
// label but the pre-existing label has its TTL change.
testgroup("add to label and change orig ttl",
tc("Setup", ttl(a("www", "5.6.7.8"), 400)),
tc("Add at same label, new ttl", ttl(a("www", "5.6.7.8"), 700), ttl(a("www", "1.2.3.4"), 700)),
), ),
testgroup("Protocol-Wildcard", testgroup("Protocol-Wildcard",

View file

@ -39,3 +39,20 @@ ProTip: If you run these tests frequently (and we hope you do), you
should create a script that you can `source` to set these should create a script that you can `source` to set these
variables. Be careful not to check this script into Git since it variables. Be careful not to check this script into Git since it
contains credentials. contains credentials.
## Debugger
Test a particular function:
```
dlv test github.com/StackExchange/dnscontrol/v3/pkg/diff2 -- -test.run Test_analyzeByRecordSet
^^^^^^^^^
Assumes you are in the pkg/diff2 directory.
```
Debug the integration tests:
```
dlv test github.com/StackExchange/dnscontrol/v3/integrationTest -- -test.v -test.run ^TestDNSProviders -verbose -provider NAMEDOTCOM -start 1 -end 1 -diff2
```

88
pkg/diff/diff2compat.go Normal file
View file

@ -0,0 +1,88 @@
package diff
import (
"github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
)
// NewCompat is a constructor that uses the new pkg/diff2 system
// instead of pkg/diff.
//
// It is for backwards compatibility only. New providers should use
// pkg/diff2. Older providers should use this to reduce their
// dependency on pkg/diff2 until they can move to the pkg/diff2/By*()
// functions.
//
// To use this simply change New() to NewCompat(). If that doesn't
// work please report a bug. The only exception is if you depend on
// the extraValues feature, which will not be supported
func NewCompat(dc *models.DomainConfig, extraValues ...func(*models.RecordConfig) map[string]string) Differ {
if len(extraValues) != 0 {
panic("extraValues not supported")
}
d := New(dc)
return &differCompat{
OldDiffer: d.(*differ),
dc: dc,
}
}
// differCompat meets the Differ interface but provides its service
// using pkg/diff2 instead of pkg/diff.
type differCompat struct {
OldDiffer *differ // Store the backwards-compatible "d" for pkg/diff
dc *models.DomainConfig
}
// IncrementalDiff generates the diff using the pkg/diff2 code.
func (d *differCompat) IncrementalDiff(existing []*models.RecordConfig) (unchanged, create, toDelete, modify Changeset, err error) {
unchanged = Changeset{}
create = Changeset{}
toDelete = Changeset{}
modify = Changeset{}
instructions, err := diff2.ByRecord(existing, d.dc, nil)
if err != nil {
return nil, nil, nil, nil, err
}
for _, inst := range instructions {
cor := Correlation{d: d.OldDiffer}
switch inst.Type {
case diff2.CREATE:
cor.Desired = inst.New[0]
create = append(create, cor)
case diff2.CHANGE:
cor.Existing = inst.Old[0]
cor.Desired = inst.New[0]
modify = append(modify, cor)
case diff2.DELETE:
cor.Existing = inst.Old[0]
toDelete = append(toDelete, cor)
}
}
return
}
// ChangedGroups provides the same results as IncrementalDiff but grouped by key.
func (d *differCompat) ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, error) {
changedKeys := map[models.RecordKey][]string{}
_, create, toDelete, modify, err := d.IncrementalDiff(existing)
if err != nil {
return nil, err
}
for _, c := range create {
changedKeys[c.Desired.Key()] = append(changedKeys[c.Desired.Key()], c.String())
}
for _, d := range toDelete {
changedKeys[d.Existing.Key()] = append(changedKeys[d.Existing.Key()], d.String())
}
for _, m := range modify {
changedKeys[m.Desired.Key()] = append(changedKeys[m.Desired.Key()], m.String())
}
return changedKeys, nil
}

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 { 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: len(o)=%d len(m)=%d\n", len(newRecs), len(msgs))
//fmt.Printf("DEBUG: mkAddByLabel: msgs = %v\n", 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.NameFQDN = l
c.Key.Type = t c.Key.Type = t
c.New = newRecs 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 { 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.NameFQDN = l
c.Key.Type = t c.Key.Type = t
c.Old = oldRecs 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 { 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)) //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.NameFQDN = l
c.Key.Type = t c.Key.Type = t
c.Old = oldRecs 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 { 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.NameFQDN = l
c.Key.Type = t c.Key.Type = t
c.Old = oldRecs c.Old = oldRecs
return c return c
} }
func mkDeleteRec(l string, t string, msgs []string, rec *models.RecordConfig) Change { 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.NameFQDN = l
c.Key.Type = t c.Key.Type = t
c.Old = models.Records{rec} c.Old = models.Records{rec}
@ -175,16 +175,70 @@ func removeCommon(existing, desired []targetConfig) ([]targetConfig, []targetCon
eKeys := map[string]*targetConfig{} eKeys := map[string]*targetConfig{}
for _, v := range existing { for _, v := range existing {
v := v
eKeys[v.compareable] = &v eKeys[v.compareable] = &v
} }
dKeys := map[string]*targetConfig{} dKeys := map[string]*targetConfig{}
for _, v := range desired { for _, v := range desired {
v := v
dKeys[v.compareable] = &v dKeys[v.compareable] = &v
} }
return filterBy(existing, dKeys), filterBy(desired, eKeys) 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. // Return s but remove any items that can be found in m.
func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig { func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig {
// fmt.Printf("DEBUG: filterBy called with %v\n", s) // fmt.Printf("DEBUG: filterBy called with %v\n", s)
@ -212,6 +266,22 @@ func filterBy(s []targetConfig, m map[string]*targetConfig) []targetConfig {
return s 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 { func diffTargets(existing, desired []targetConfig) ChangeList {
//fmt.Printf("DEBUG: diffTargets called with len(e)=%d len(d)=%d\n", len(existing), len(desired)) //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. // remove the exact matches.
existing, desired = removeCommon(existing, desired) 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)) mi := min(len(existing), len(desired))
//fmt.Printf("DEBUG: min=%d\n", mi) //fmt.Printf("DEBUG: min=%d\n", mi)
for i := 0; i < mi; i++ { for i := 0; i < mi; i++ {
//fmt.Println(i, "CHANGE") //fmt.Println(i, "CHANGE")
er := existing[i].rec er := existing[i].rec
dr := desired[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}, 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{er},
models.Records{dr}, models.Records{dr},
)) ))

View file

@ -42,8 +42,6 @@ var d11 = makeRec("labg", "NS", "10.10.10.97") // [11']
var d12 = makeRec("labh", "A", "1.2.3.4") // [12'] var d12 = makeRec("labh", "A", "1.2.3.4") // [12']
var testDataApexMX22bbb = makeRec("", "MX", "22 bbb") var testDataApexMX22bbb = makeRec("", "MX", "22 bbb")
var d0tc = mkTargetConfig(testDataAA1234clone)
func makeChange(v Verb, l, t string, old, new models.Records, msgs []string) Change { func makeChange(v Verb, l, t string, old, new models.Records, msgs []string) Change {
c := Change{ c := Change{
Type: v, Type: v,
@ -425,6 +423,7 @@ func mkTargetConfigMap(x ...*models.RecordConfig) map[string]*targetConfig {
} }
func Test_diffTargets(t *testing.T) { func Test_diffTargets(t *testing.T) {
type args struct { type args struct {
existing []targetConfig existing []targetConfig
desired []targetConfig desired []targetConfig
@ -435,6 +434,24 @@ func Test_diffTargets(t *testing.T) {
want ChangeList want ChangeList
}{ }{
{
name: "add1changettl",
args: args{
existing: mkTargetConfig(testDataAA5678),
desired: mkTargetConfig(testDataAA5678ttl700, testDataAA1234ttl700),
},
want: ChangeList{
Change{Type: CHANGE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "A"},
New: models.Records{testDataAA5678ttl700, testDataAA1234ttl700},
Msgs: []string{
"CHANGE laba.f.com A 5.6.7.8 (ttl 300->700)",
"CREATE laba.f.com A 1.2.3.4",
},
},
},
},
{ {
name: "single", name: "single",
args: args{ args: args{
@ -530,15 +547,26 @@ func Test_removeCommon(t *testing.T) {
want []targetConfig want []targetConfig
want1 []targetConfig want1 []targetConfig
}{ }{
{ {
name: "same", name: "same",
args: args{ args: args{
existing: d0tc, existing: mkTargetConfig(testDataAA1234clone),
desired: d0tc, desired: mkTargetConfig(testDataAA1234clone),
}, },
want: []targetConfig{}, want: []targetConfig{},
want1: []targetConfig{}, want1: []targetConfig{},
}, },
{
name: "disjoint",
args: args{
existing: mkTargetConfig(testDataAA1234),
desired: mkTargetConfig(testDataAA5678),
},
want: mkTargetConfig(testDataAA1234),
want1: mkTargetConfig(testDataAA5678),
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
@ -607,3 +635,60 @@ func Test_filterBy(t *testing.T) {
}) })
} }
} }
func Test_splitTTLOnly(t *testing.T) {
type args struct {
existing []targetConfig
desired []targetConfig
}
tests := []struct {
name string
args args
wantExistDiff []targetConfig
wantDesireDiff []targetConfig
wantExistTTL models.Records
wantDesireTTL models.Records
}{
{
name: "simple",
args: args{
existing: mkTargetConfig(testDataAA1234),
desired: mkTargetConfig(testDataAA1234ttl700),
},
wantExistDiff: mkTargetConfig(),
wantDesireDiff: mkTargetConfig(),
wantExistTTL: models.Records{testDataAA1234},
wantDesireTTL: models.Records{testDataAA1234ttl700},
},
{
name: "both",
args: args{
existing: mkTargetConfig(testDataAA1234),
desired: mkTargetConfig(testDataAA5678),
},
wantExistDiff: mkTargetConfig(testDataAA1234),
wantDesireDiff: mkTargetConfig(testDataAA5678),
wantExistTTL: models.Records{},
wantDesireTTL: models.Records{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotExistDiff, gotDesireDiff, gotExistTTL, gotDesireTTL := splitTTLOnly(tt.args.existing, tt.args.desired)
if !reflect.DeepEqual(gotExistDiff, tt.wantExistDiff) {
t.Errorf("splitTTLOnly() gotExistDiff = %v, want %v", gotExistDiff, tt.wantExistDiff)
}
if !reflect.DeepEqual(gotDesireDiff, tt.wantDesireDiff) {
t.Errorf("splitTTLOnly() gotDesireDiff = %v, want %v", gotDesireDiff, tt.wantDesireDiff)
}
if ((len(tt.wantExistTTL) != 0) && len(gotExistTTL) != 0) && !reflect.DeepEqual(gotExistTTL, tt.wantExistTTL) {
t.Errorf("splitTTLOnly() gotExistTTL = %v, want %v (len=%d %d)", gotExistTTL, tt.wantExistTTL, len(gotExistTTL), len(tt.wantExistTTL))
}
if ((len(tt.wantDesireTTL) != 0) && len(gotDesireTTL) != 0) && !reflect.DeepEqual(gotDesireTTL, tt.wantDesireTTL) {
t.Errorf("splitTTLOnly() gotDesireTTL = %v, want %v", gotDesireTTL, tt.wantDesireTTL)
}
})
}
}

View file

@ -202,10 +202,12 @@ func (cc *CompareConfig) addRecords(recs models.Records, storeInExisting bool) {
//fmt.Printf("BEFORE E/D: %v/%v\n", len(td.existingRecs), len(td.desiredRecs)) //fmt.Printf("BEFORE E/D: %v/%v\n", len(td.existingRecs), len(td.desiredRecs))
if storeInExisting { if storeInExisting {
cc.ldata[labelIdx].tdata[rtIdx].existingRecs = append(cc.ldata[labelIdx].tdata[rtIdx].existingRecs, rec) cc.ldata[labelIdx].tdata[rtIdx].existingRecs = append(cc.ldata[labelIdx].tdata[rtIdx].existingRecs, rec)
cc.ldata[labelIdx].tdata[rtIdx].existingTargets = append(cc.ldata[labelIdx].tdata[rtIdx].existingTargets, targetConfig{compareable: comp, rec: rec}) cc.ldata[labelIdx].tdata[rtIdx].existingTargets = append(cc.ldata[labelIdx].tdata[rtIdx].existingTargets,
targetConfig{compareable: comp, rec: rec})
} else { } else {
cc.ldata[labelIdx].tdata[rtIdx].desiredRecs = append(cc.ldata[labelIdx].tdata[rtIdx].desiredRecs, rec) cc.ldata[labelIdx].tdata[rtIdx].desiredRecs = append(cc.ldata[labelIdx].tdata[rtIdx].desiredRecs, rec)
cc.ldata[labelIdx].tdata[rtIdx].desiredTargets = append(cc.ldata[labelIdx].tdata[rtIdx].desiredTargets, targetConfig{compareable: comp, rec: rec}) cc.ldata[labelIdx].tdata[rtIdx].desiredTargets = append(cc.ldata[labelIdx].tdata[rtIdx].desiredTargets,
targetConfig{compareable: comp, rec: rec})
} }
//fmt.Printf("AFTER L: %v\n", len(cc.ldata)) //fmt.Printf("AFTER L: %v\n", len(cc.ldata))
//fmt.Printf("AFTER E/D: %v/%v\n", len(td.existingRecs), len(td.desiredRecs)) //fmt.Printf("AFTER E/D: %v/%v\n", len(td.existingRecs), len(td.desiredRecs))

85
pkg/diff2/compat.go Normal file
View file

@ -0,0 +1,85 @@
package diff2
// import (
// "github.com/StackExchange/dnscontrol/v3/models"
// "github.com/StackExchange/dnscontrol/v3/pkg/diff"
// )
// // Provide an interface that is backwards compatible with pkg/diff.
// // // /diff/IncrementalDiffCompat(). It not as efficient as converting
// // to the diff2.By*() functions. However, using this is better than
// // staying with pkg/diff.
// func CompatIncrementalDiff(dc *models.DomainConfig, existing []*models.RecordConfig) (unchanged, create, toDelete, modify diff.Changeset, err error) {
// unchanged = diff.Changeset{}
// create = diff.Changeset{}
// toDelete = diff.Changeset{}
// modify = diff.Changeset{}
// instructions, err := ByRecord(existing, dc, nil)
// if err != nil {
// return nil, nil, nil, nil, err
// }
// d := diff.New(dc, nil)
// for _, inst := range instructions {
// //cor := Correlation{d: d}
// cor := diff.Correlation{d: d}
// switch inst.Type {
// case CREATE:
// cor.Desired = inst.New[0]
// create = append(create, cor)
// case CHANGE:
// cor.Existing = inst.Old[0]
// cor.Desired = inst.New[0]
// modify = append(modify, cor)
// case DELETE:
// cor.Existing = inst.Old[0]
// toDelete = append(toDelete, cor)
// }
// }
// return
// }
// // func (d *Differ) ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, error) {
// // changedKeys := map[models.RecordKey][]string{}
// // _, create, toDelete, modify, err := d.IncrementalDiff(existing)
// // if err != nil {
// // return nil, err
// // }
// // for _, c := range create {
// // changedKeys[c.Desired.Key()] = append(changedKeys[c.Desired.Key()], c.String())
// // }
// // for _, d := range toDelete {
// // changedKeys[d.Existing.Key()] = append(changedKeys[d.Existing.Key()], d.String())
// // }
// // for _, m := range modify {
// // changedKeys[m.Desired.Key()] = append(changedKeys[m.Desired.Key()], m.String())
// // }
// // return changedKeys, nil
// // }
// // func (c Correlation) String() string {
// // if c.Existing == nil {
// // return fmt.Sprintf("CREATE %s %s %s", c.Desired.Type, c.Desired.GetLabelFQDN(), c.d.content(c.Desired))
// // }
// // if c.Desired == nil {
// // return fmt.Sprintf("DELETE %s %s %s", c.Existing.Type, c.Existing.GetLabelFQDN(), c.d.content(c.Existing))
// // }
// // return fmt.Sprintf("MODIFY %s %s: (%s) -> (%s)", c.Existing.Type, c.Existing.GetLabelFQDN(), c.d.content(c.Existing), c.d.content(c.Desired))
// // }
// // // get normalized content for record. target, ttl, mxprio, and specified metadata
// // func (d *Differ) content(r *models.RecordConfig) string {
// // // get the extra values maps to add to the comparison.
// // var allMaps []map[string]string
// // for _, f := range d.extraValues {
// // valueMap := f(r)
// // allMaps = append(allMaps, valueMap)
// // }
// // return r.ToDiffable(allMaps...)
// // }

View file

@ -30,9 +30,55 @@ type Change struct {
Old models.Records Old models.Records
New models.Records // any changed or added records at Key. New models.Records // any changed or added records at Key.
Msgs []string // Human-friendly explanation of what changed Msgs []string // Human-friendly explanation of what changed
MsgsJoined string // strings.Join(Msgs, "\n")
MsgsByKey map[models.RecordKey][]string // Messages for a given key MsgsByKey map[models.RecordKey][]string // Messages for a given key
} }
/*
General instructions:
changes, err := diff2.ByRecord(existing, dc, nil)
//changes, err := diff2.ByRecordSet(existing, dc, nil)
//changes, err := diff2.ByLabel(existing, dc, nil)
if err != nil {
return nil, err
}
var corrections []*models.Correction
for _, change := range changes {
switch change.Type {
case diff2.CREATE:
corr = &models.Correction{
Msg: change.MsgsJoined,
F: func() error {
return c.createRecord(FILL IN)
},
}
case diff2.CHANGE:
corr = &models.Correction{
Msg: change.MsgsJoined,
F: func() error {
return c.modifyRecord(FILL IN)
},
}
case diff2.DELETE:
corr = &models.Correction{
Msg: change.MsgsJoined,
F: func() error {
return c.deleteRecord(FILL IN)
},
}
}
corrections = append(corrections, corr)
}
return corrections, nil
}
*/
// ByRecordSet takes two lists of records (existing and desired) and // ByRecordSet takes two lists of records (existing and desired) and
// returns instructions for turning existing into desired. // returns instructions for turning existing into desired.
// //
@ -143,18 +189,6 @@ func ByZone(existing models.Records, dc *models.DomainConfig, compFunc Comparabl
return justMsgs(instructions), len(instructions) != 0, nil return justMsgs(instructions), len(instructions) != 0, nil
} }
/*
nil, nil :
nil, nonzero : nil, true, nil
nonzero, nil : msgs, true, nil
nonzero, nonzero :
existing: changes : return msgs, true, nil
existing: no changes : return nil, false, nil
not existing: no changes: return nil, false, nil
not existing: changes : return nil, true, nil
*/
func (c Change) String() string { func (c Change) String() string {
var buf bytes.Buffer var buf bytes.Buffer
b := &buf b := &buf

View file

@ -55,16 +55,20 @@ func (n *namedotcomProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
models.PostProcessRecords(actual) models.PostProcessRecords(actual)
var corrections []*models.Correction var corrections []*models.Correction
if !diff2.EnableDiff2 || true { // Remove "|| true" when diff2 version arrives
var create, del, mod diff.Changeset
if !diff2.EnableDiff2 {
differ := diff.New(dc) differ := diff.New(dc)
_, create, del, mod, err := differ.IncrementalDiff(actual) _, create, del, mod, err = differ.IncrementalDiff(actual)
} else {
differ := diff.NewCompat(dc)
_, create, del, mod, err = differ.IncrementalDiff(actual)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
corrections := []*models.Correction{}
for _, d := range del { for _, d := range del {
rec := d.Existing.Original.(*namecom.Record) rec := d.Existing.Original.(*namecom.Record)
c := &models.Correction{Msg: d.String(), F: func() error { return n.deleteRecord(rec.ID, dc.Name) }} c := &models.Correction{Msg: d.String(), F: func() error { return n.deleteRecord(rec.ID, dc.Name) }}
@ -87,10 +91,6 @@ func (n *namedotcomProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m
}} }}
corrections = append(corrections, c) corrections = append(corrections, c)
} }
return corrections, nil
}
// Insert Future diff2 version here.
return corrections, nil return corrections, nil
} }