diff --git a/integrationTest/integration_test.go b/integrationTest/integration_test.go index 2f56ac0f6..9682bca91 100644 --- a/integrationTest/integration_test.go +++ b/integrationTest/integration_test.go @@ -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 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("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", diff --git a/integrationTest/readme.md b/integrationTest/readme.md index 2189ef1d7..490462740 100644 --- a/integrationTest/readme.md +++ b/integrationTest/readme.md @@ -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 variables. Be careful not to check this script into Git since it 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 +``` diff --git a/pkg/diff/diff2compat.go b/pkg/diff/diff2compat.go new file mode 100644 index 000000000..c43e2bde3 --- /dev/null +++ b/pkg/diff/diff2compat.go @@ -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 +} diff --git a/pkg/diff2/analyze.go b/pkg/diff2/analyze.go index 6df621e71..9a6fd597b 100644 --- a/pkg/diff2/analyze.go +++ b/pkg/diff2/analyze.go @@ -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}, )) diff --git a/pkg/diff2/analyze_test.go b/pkg/diff2/analyze_test.go index cba206146..b0992377f 100644 --- a/pkg/diff2/analyze_test.go +++ b/pkg/diff2/analyze_test.go @@ -9,7 +9,7 @@ import ( "github.com/kylelemons/godebug/diff" ) -var testDataAA1234 = makeRec("laba", "A", "1.2.3.4") // [0] +var testDataAA1234 = makeRec("laba", "A", "1.2.3.4") // [0] var testDataAA5678 = makeRec("laba", "A", "5.6.7.8") // var testDataAA1234ttl700 = makeRecTTL("laba", "A", "1.2.3.4", 700) // var testDataAA5678ttl700 = makeRecTTL("laba", "A", "5.6.7.8", 700) // @@ -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 testDataApexMX22bbb = makeRec("", "MX", "22 bbb") -var d0tc = mkTargetConfig(testDataAA1234clone) - func makeChange(v Verb, l, t string, old, new models.Records, msgs []string) Change { c := Change{ Type: v, @@ -425,6 +423,7 @@ func mkTargetConfigMap(x ...*models.RecordConfig) map[string]*targetConfig { } func Test_diffTargets(t *testing.T) { + type args struct { existing []targetConfig desired []targetConfig @@ -435,6 +434,24 @@ func Test_diffTargets(t *testing.T) { 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", args: args{ @@ -530,15 +547,26 @@ func Test_removeCommon(t *testing.T) { want []targetConfig want1 []targetConfig }{ + { name: "same", args: args{ - existing: d0tc, - desired: d0tc, + existing: mkTargetConfig(testDataAA1234clone), + desired: mkTargetConfig(testDataAA1234clone), }, want: []targetConfig{}, want1: []targetConfig{}, }, + + { + name: "disjoint", + args: args{ + existing: mkTargetConfig(testDataAA1234), + desired: mkTargetConfig(testDataAA5678), + }, + want: mkTargetConfig(testDataAA1234), + want1: mkTargetConfig(testDataAA5678), + }, } for _, tt := range tests { 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) + } + }) + } +} diff --git a/pkg/diff2/compareconfig.go b/pkg/diff2/compareconfig.go index 368f352f9..b9a24bfa7 100644 --- a/pkg/diff2/compareconfig.go +++ b/pkg/diff2/compareconfig.go @@ -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)) if storeInExisting { 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 { 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 E/D: %v/%v\n", len(td.existingRecs), len(td.desiredRecs)) diff --git a/pkg/diff2/compat.go b/pkg/diff2/compat.go new file mode 100644 index 000000000..9e67a76de --- /dev/null +++ b/pkg/diff2/compat.go @@ -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...) +// // } diff --git a/pkg/diff2/diff2.go b/pkg/diff2/diff2.go index a3c9baa35..f5d5bd847 100644 --- a/pkg/diff2/diff2.go +++ b/pkg/diff2/diff2.go @@ -26,13 +26,59 @@ type ChangeList []Change type Change struct { Type Verb // Add, Change, Delete - Key models.RecordKey // .Key.Type is "" unless using ByRecordSet - Old models.Records - New models.Records // any changed or added records at Key. - Msgs []string // Human-friendly explanation of what changed - MsgsByKey map[models.RecordKey][]string // Messages for a given key + Key models.RecordKey // .Key.Type is "" unless using ByRecordSet + Old models.Records + New models.Records // any changed or added records at Key. + Msgs []string // Human-friendly explanation of what changed + MsgsJoined string // strings.Join(Msgs, "\n") + 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 // 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 } -/* -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 { var buf bytes.Buffer b := &buf diff --git a/providers/namedotcom/records.go b/providers/namedotcom/records.go index f3d6e24f8..e1e7a5024 100644 --- a/providers/namedotcom/records.go +++ b/providers/namedotcom/records.go @@ -55,42 +55,42 @@ func (n *namedotcomProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*m models.PostProcessRecords(actual) 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) - _, create, del, mod, err := differ.IncrementalDiff(actual) - if err != nil { - return nil, err - } - - corrections := []*models.Correction{} - - for _, d := range del { - rec := d.Existing.Original.(*namecom.Record) - c := &models.Correction{Msg: d.String(), F: func() error { return n.deleteRecord(rec.ID, dc.Name) }} - corrections = append(corrections, c) - } - for _, cre := range create { - rec := cre.Desired - c := &models.Correction{Msg: cre.String(), F: func() error { return n.createRecord(rec, dc.Name) }} - corrections = append(corrections, c) - } - for _, chng := range mod { - old := chng.Existing.Original.(*namecom.Record) - new := chng.Desired - c := &models.Correction{Msg: chng.String(), F: func() error { - err := n.deleteRecord(old.ID, dc.Name) - if err != nil { - return err - } - return n.createRecord(new, dc.Name) - }} - corrections = append(corrections, c) - } - return corrections, nil + _, create, del, mod, err = differ.IncrementalDiff(actual) + } else { + differ := diff.NewCompat(dc) + _, create, del, mod, err = differ.IncrementalDiff(actual) + } + if err != nil { + return nil, err } - // Insert Future diff2 version here. + for _, d := range del { + rec := d.Existing.Original.(*namecom.Record) + c := &models.Correction{Msg: d.String(), F: func() error { return n.deleteRecord(rec.ID, dc.Name) }} + corrections = append(corrections, c) + } + for _, cre := range create { + rec := cre.Desired + c := &models.Correction{Msg: cre.String(), F: func() error { return n.createRecord(rec, dc.Name) }} + corrections = append(corrections, c) + } + for _, chng := range mod { + old := chng.Existing.Original.(*namecom.Record) + new := chng.Desired + c := &models.Correction{Msg: chng.String(), F: func() error { + err := n.deleteRecord(old.ID, dc.Name) + if err != nil { + return err + } + return n.createRecord(new, dc.Name) + }} + corrections = append(corrections, c) + } return corrections, nil }