mirror of
				https://github.com/StackExchange/dnscontrol.git
				synced 2025-11-04 20:28:40 +08:00 
			
		
		
		
	REFACTOR: Add a backwards compatible interface to diff2 (#1870)
This commit is contained in:
		
							parent
							
								
									801aae725b
								
							
						
					
					
						commit
						397ce107e5
					
				
					 9 changed files with 476 additions and 67 deletions
				
			
		| 
						 | 
					@ -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",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
									
								
							
							
						
						
									
										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 {
 | 
					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},
 | 
				
			||||||
		))
 | 
							))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import (
 | 
				
			||||||
	"github.com/kylelemons/godebug/diff"
 | 
						"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 testDataAA5678 = makeRec("laba", "A", "5.6.7.8")               //
 | 
				
			||||||
var testDataAA1234ttl700 = makeRecTTL("laba", "A", "1.2.3.4", 700) //
 | 
					var testDataAA1234ttl700 = makeRecTTL("laba", "A", "1.2.3.4", 700) //
 | 
				
			||||||
var testDataAA5678ttl700 = makeRecTTL("laba", "A", "5.6.7.8", 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 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)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
									
								
							
							
						
						
									
										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 Change struct {
 | 
				
			||||||
	Type Verb // Add, Change, Delete
 | 
						Type Verb // Add, Change, Delete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Key       models.RecordKey // .Key.Type is "" unless using ByRecordSet
 | 
						Key        models.RecordKey // .Key.Type is "" unless using ByRecordSet
 | 
				
			||||||
	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
 | 
				
			||||||
	MsgsByKey map[models.RecordKey][]string // Messages for a given key
 | 
						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
 | 
					// 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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,42 +55,42 @@ 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)
 | 
				
			||||||
		if err != nil {
 | 
						} else {
 | 
				
			||||||
			return nil, err
 | 
							differ := diff.NewCompat(dc)
 | 
				
			||||||
		}
 | 
							_, create, del, mod, err = differ.IncrementalDiff(actual)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
		corrections := []*models.Correction{}
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
		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
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 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
 | 
						return corrections, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue