mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-09-20 06:46:19 +08:00
REFACTOR: Add a backwards compatible interface to diff2 (#1870)
This commit is contained in:
parent
801aae725b
commit
397ce107e5
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
88
pkg/diff/diff2compat.go
Normal file
88
pkg/diff/diff2compat.go
Normal 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
|
||||
}
|
|
@ -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},
|
||||
))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
85
pkg/diff2/compat.go
Normal file
85
pkg/diff2/compat.go
Normal 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...)
|
||||
// // }
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue