Bugfix: Providers with batched updates might not report the correct number of changes (#3108)

This commit is contained in:
Tom Limoncelli 2024-09-16 12:20:30 -04:00 committed by GitHub
parent 6e2cfb5d3b
commit 06ba3cce77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
64 changed files with 393 additions and 356 deletions

View file

@ -96,7 +96,7 @@ jobs:
if: github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main' if: github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: golang:1.22 image: golang:1.23
needs: needs:
- integration-test-providers - integration-test-providers
env: env:

View file

@ -42,7 +42,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ^1.22 go-version: ^1.23
# Stringer is needed because .goreleaser includes "go generate ./..." # Stringer is needed because .goreleaser includes "go generate ./..."
- name: Install stringer - name: Install stringer

View file

@ -240,7 +240,7 @@ func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, repor
out.StartDNSProvider(provider.Name, skip) out.StartDNSProvider(provider.Name, skip)
if !skip { if !skip {
corrections := zone.GetCorrections(provider.Name) corrections := zone.GetCorrections(provider.Name)
numActions := countActions(corrections) numActions := zone.GetChangeCount(provider.Name)
totalCorrections += numActions totalCorrections += numActions
out.EndProvider2(provider.Name, numActions) out.EndProvider2(provider.Name, numActions)
reportItems = append(reportItems, genReportItem(zone.Name, corrections, provider.Name)) reportItems = append(reportItems, genReportItem(zone.Name, corrections, provider.Name))
@ -253,7 +253,7 @@ func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, repor
out.StartRegistrar(zone.RegistrarName, !skip) out.StartRegistrar(zone.RegistrarName, !skip)
if skip { if skip {
corrections := zone.GetCorrections(zone.RegistrarInstance.Name) corrections := zone.GetCorrections(zone.RegistrarInstance.Name)
numActions := countActions(corrections) numActions := zone.GetChangeCount(zone.RegistrarInstance.Name)
out.EndProvider2(zone.RegistrarName, numActions) out.EndProvider2(zone.RegistrarName, numActions)
totalCorrections += numActions totalCorrections += numActions
reportItems = append(reportItems, genReportItem(zone.Name, corrections, zone.RegistrarName)) reportItems = append(reportItems, genReportItem(zone.Name, corrections, zone.RegistrarName))
@ -281,15 +281,15 @@ func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, repor
return nil return nil
} }
func countActions(corrections []*models.Correction) int { //func countActions(corrections []*models.Correction) int {
r := 0 // r := 0
for _, c := range corrections { // for _, c := range corrections {
if c.F != nil { // if c.F != nil {
r++ // r++
} // }
} // }
return r // return r
} //}
func whichZonesToProcess(domains []*models.DomainConfig, filter string) []*models.DomainConfig { func whichZonesToProcess(domains []*models.DomainConfig, filter string) []*models.DomainConfig {
if filter == "" || filter == "all" { if filter == "" || filter == "all" {
@ -364,7 +364,7 @@ func optimizeOrder(zones []*models.DomainConfig) []*models.DomainConfig {
func oneZone(zone *models.DomainConfig, args PPreviewArgs, zc *zoneCache) { func oneZone(zone *models.DomainConfig, args PPreviewArgs, zc *zoneCache) {
// Fix the parent zone's delegation: (if able/needed) // Fix the parent zone's delegation: (if able/needed)
//zone.NameserversMutex.Lock() //zone.NameserversMutex.Lock()
delegationCorrections := generateDelegationCorrections(zone, zone.DNSProviderInstances, zone.RegistrarInstance) delegationCorrections, dcCount := generateDelegationCorrections(zone, zone.DNSProviderInstances, zone.RegistrarInstance)
//zone.NameserversMutex.Unlock() //zone.NameserversMutex.Unlock()
// Loop over the (selected) providers configured for that zone: // Loop over the (selected) providers configured for that zone:
@ -378,13 +378,15 @@ func oneZone(zone *models.DomainConfig, args PPreviewArgs, zc *zoneCache) {
} }
// Update the zone's records at the provider: // Update the zone's records at the provider:
zoneCor, rep := generateZoneCorrections(zone, provider) zoneCor, rep, actualChangeCount := generateZoneCorrections(zone, provider)
zone.StoreCorrections(provider.Name, rep) zone.StoreCorrections(provider.Name, rep)
zone.StoreCorrections(provider.Name, zoneCor) zone.StoreCorrections(provider.Name, zoneCor)
zone.IncrementChangeCount(provider.Name, actualChangeCount)
} }
// Do the delegation corrections after the zones are updated. // Do the delegation corrections after the zones are updated.
zone.StoreCorrections(zone.RegistrarInstance.Name, delegationCorrections) zone.StoreCorrections(zone.RegistrarInstance.Name, delegationCorrections)
zone.IncrementChangeCount(zone.RegistrarInstance.Name, dcCount)
} }
func whichProvidersToProcess(providers []*models.DNSProviderInstance, filter string) []*models.DNSProviderInstance { func whichProvidersToProcess(providers []*models.DNSProviderInstance, filter string) []*models.DNSProviderInstance {
@ -533,32 +535,32 @@ func generatePopulateCorrections(provider *models.DNSProviderInstance, zoneName
}} }}
} }
func generateZoneCorrections(zone *models.DomainConfig, provider *models.DNSProviderInstance) ([]*models.Correction, []*models.Correction) { func generateZoneCorrections(zone *models.DomainConfig, provider *models.DNSProviderInstance) ([]*models.Correction, []*models.Correction, int) {
reports, zoneCorrections, err := zonerecs.CorrectZoneRecords(provider.Driver, zone) reports, zoneCorrections, actualChangeCount, err := zonerecs.CorrectZoneRecords(provider.Driver, zone)
if err != nil { if err != nil {
return []*models.Correction{{Msg: fmt.Sprintf("Domain %q provider %s Error: %s", zone.Name, provider.Name, err)}}, nil return []*models.Correction{{Msg: fmt.Sprintf("Domain %q provider %s Error: %s", zone.Name, provider.Name, err)}}, nil, 0
} }
return zoneCorrections, reports return zoneCorrections, reports, actualChangeCount
} }
func generateDelegationCorrections(zone *models.DomainConfig, providers []*models.DNSProviderInstance, _ *models.RegistrarInstance) []*models.Correction { func generateDelegationCorrections(zone *models.DomainConfig, providers []*models.DNSProviderInstance, _ *models.RegistrarInstance) ([]*models.Correction, int) {
//fmt.Printf("DEBUG: generateDelegationCorrections start zone=%q nsList = %v\n", zone.Name, zone.Nameservers) //fmt.Printf("DEBUG: generateDelegationCorrections start zone=%q nsList = %v\n", zone.Name, zone.Nameservers)
nsList, err := nameservers.DetermineNameserversForProviders(zone, providers, true) nsList, err := nameservers.DetermineNameserversForProviders(zone, providers, true)
if err != nil { if err != nil {
return msg(fmt.Sprintf("DtermineNS: zone %q; Error: %s", zone.Name, err)) return msg(fmt.Sprintf("DetermineNS: zone %q; Error: %s", zone.Name, err)), 0
} }
zone.Nameservers = nsList zone.Nameservers = nsList
nameservers.AddNSRecords(zone) nameservers.AddNSRecords(zone)
if len(zone.Nameservers) == 0 && zone.Metadata["no_ns"] != "true" { if len(zone.Nameservers) == 0 && zone.Metadata["no_ns"] != "true" {
return []*models.Correction{{Msg: fmt.Sprintf("No nameservers declared for domain %q; skipping registrar. Add {no_ns:'true'} to force", zone.Name)}} return []*models.Correction{{Msg: fmt.Sprintf("No nameservers declared for domain %q; skipping registrar. Add {no_ns:'true'} to force", zone.Name)}}, 0
} }
corrections, err := zone.RegistrarInstance.Driver.GetRegistrarCorrections(zone) corrections, err := zone.RegistrarInstance.Driver.GetRegistrarCorrections(zone)
if err != nil { if err != nil {
return msg(fmt.Sprintf("zone %q; Rprovider %q; Error: %s", zone.Name, zone.RegistrarInstance.Name, err)) return msg(fmt.Sprintf("zone %q; Rprovider %q; Error: %s", zone.Name, zone.RegistrarInstance.Name, err)), 0
} }
return corrections return corrections, len(corrections)
} }
func msg(s string) []*models.Correction { func msg(s string) []*models.Correction {

View file

@ -247,17 +247,17 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI, report
continue continue
} }
reports, corrections, err := zonerecs.CorrectZoneRecords(provider.Driver, domain) reports, corrections, actualChangeCount, err := zonerecs.CorrectZoneRecords(provider.Driver, domain)
out.EndProvider(provider.Name, len(corrections), err) out.EndProvider(provider.Name, actualChangeCount, err)
if err != nil { if err != nil {
anyErrors = true anyErrors = true
return return
} }
totalCorrections += len(corrections) totalCorrections += actualChangeCount
printReports(domain.Name, provider.Name, reports, out, push, notifier) printReports(domain.Name, provider.Name, reports, out, push, notifier)
reportItems = append(reportItems, ReportItem{ reportItems = append(reportItems, ReportItem{
Domain: domain.Name, Domain: domain.Name,
Corrections: len(corrections), Corrections: actualChangeCount,
Provider: provider.Name, Provider: provider.Name,
}) })
anyErrors = printOrRunCorrections(domain.Name, provider.Name, corrections, out, push, interactive, notifier) || anyErrors anyErrors = printOrRunCorrections(domain.Name, provider.Name, corrections, out, push, interactive, notifier) || anyErrors

2
go.mod
View file

@ -1,6 +1,6 @@
module github.com/StackExchange/dnscontrol/v4 module github.com/StackExchange/dnscontrol/v4
go 1.22.1 go 1.23.0
retract v4.8.0 retract v4.8.0

View file

@ -228,13 +228,13 @@ func makeChanges(t *testing.T, prv providers.DNSServiceProvider, dc *models.Doma
} }
// get and run corrections for first time // get and run corrections for first time
_, corrections, err := zonerecs.CorrectZoneRecords(prv, dom) _, corrections, actualChangeCount, err := zonerecs.CorrectZoneRecords(prv, dom)
if err != nil { if err != nil {
t.Fatal(fmt.Errorf("runTests: %w", err)) t.Fatal(fmt.Errorf("runTests: %w", err))
} }
if tst.Changeless { if tst.Changeless {
if count := len(corrections); count != 0 { if actualChangeCount != 0 {
t.Logf("Expected 0 corrections on FIRST run, but found %d.", count) t.Logf("Expected 0 corrections on FIRST run, but found %d.", actualChangeCount)
for i, c := range corrections { for i, c := range corrections {
t.Logf("UNEXPECTED #%d: %s", i, c.Msg) t.Logf("UNEXPECTED #%d: %s", i, c.Msg)
} }
@ -261,12 +261,12 @@ func makeChanges(t *testing.T, prv providers.DNSServiceProvider, dc *models.Doma
} }
// run a second time and expect zero corrections // run a second time and expect zero corrections
_, corrections, err = zonerecs.CorrectZoneRecords(prv, dom2) _, corrections, actualChangeCount, err = zonerecs.CorrectZoneRecords(prv, dom2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if count := len(corrections); count != 0 { if actualChangeCount != 0 {
t.Logf("Expected 0 corrections on second run, but found %d.", count) t.Logf("Expected 0 corrections on second run, but found %d.", actualChangeCount)
for i, c := range corrections { for i, c := range corrections {
t.Logf("UNEXPECTED #%d: %s", i, c.Msg) t.Logf("UNEXPECTED #%d: %s", i, c.Msg)
} }
@ -353,7 +353,7 @@ func TestDualProviders(t *testing.T) {
run := func() { run := func() {
dom, _ := dc.Copy() dom, _ := dc.Copy()
rs, cs, err := zonerecs.CorrectZoneRecords(p, dom) rs, cs, _, err := zonerecs.CorrectZoneRecords(p, dom)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -378,12 +378,12 @@ func TestDualProviders(t *testing.T) {
run() run()
// run again to make sure no corrections // run again to make sure no corrections
t.Log("Running again to ensure stability") t.Log("Running again to ensure stability")
rs, cs, err := zonerecs.CorrectZoneRecords(p, dc) rs, cs, actualChangeCount, err := zonerecs.CorrectZoneRecords(p, dc)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if count := len(cs); count != 0 { if actualChangeCount != 0 {
t.Logf("Expect no corrections on second run, but found %d.", count) t.Logf("Expect no corrections on second run, but found %d.", actualChangeCount)
for i, c := range rs { for i, c := range rs {
t.Logf("INFO#%d:\n%s", i+1, c.Msg) t.Logf("INFO#%d:\n%s", i+1, c.Msg)
} }

View file

@ -52,6 +52,7 @@ type DomainConfig struct {
pendingCorrectionsMutex sync.Mutex // Protect pendingCorrections* pendingCorrectionsMutex sync.Mutex // Protect pendingCorrections*
pendingCorrections map[string]([]*Correction) // Work to be done for each provider pendingCorrections map[string]([]*Correction) // Work to be done for each provider
pendingCorrectionsOrder []string // Call the providers in this order pendingCorrectionsOrder []string // Call the providers in this order
pendingActualChangeCount map[string](int) // Number of changes to report (cumulative)
} }
// GetSplitHorizonNames returns the domain's name, uniquename, and tag. // GetSplitHorizonNames returns the domain's name, uniquename, and tag.
@ -176,3 +177,23 @@ func (dc *DomainConfig) GetCorrections(providerName string) []*Correction {
} }
return nil return nil
} }
// IncrementChangeCount accumulates change count in a thread-safe way.
func (dc *DomainConfig) IncrementChangeCount(providerName string, delta int) {
dc.pendingCorrectionsMutex.Lock()
defer dc.pendingCorrectionsMutex.Unlock()
if dc.pendingActualChangeCount == nil {
// First time storing anything.
dc.pendingActualChangeCount = make(map[string](int))
}
dc.pendingActualChangeCount[providerName] += delta
}
// GetChangeCount accumulates change count in a thread-safe way.
func (dc *DomainConfig) GetChangeCount(providerName string) int {
dc.pendingCorrectionsMutex.Lock()
defer dc.pendingCorrectionsMutex.Unlock()
return dc.pendingActualChangeCount[providerName]
}

View file

@ -4,7 +4,7 @@ package models
type DNSProvider interface { type DNSProvider interface {
GetNameservers(domain string) ([]*Nameserver, error) GetNameservers(domain string) ([]*Nameserver, error)
GetZoneRecords(domain string, meta map[string]string) (Records, error) GetZoneRecords(domain string, meta map[string]string) (Records, error)
GetZoneRecordsCorrections(dc *DomainConfig, existing Records) ([]*Correction, error) GetZoneRecordsCorrections(dc *DomainConfig, existing Records) ([]*Correction, int, error)
} }
// Registrar is an interface for Registrar plug-ins. // Registrar is an interface for Registrar plug-ins.

View file

@ -276,7 +276,7 @@ func (c *certManager) getCorrections(d *models.DomainConfig) ([]*models.Correcti
if err != nil { if err != nil {
return nil, err return nil, err
} }
reports, corrections, err := zonerecs.CorrectZoneRecords(p.Driver, dc) reports, corrections, _, err := zonerecs.CorrectZoneRecords(p.Driver, dc)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -20,10 +20,10 @@ type Changeset []Correlation
// Differ is an interface for computing the difference between two zones. // Differ is an interface for computing the difference between two zones.
type Differ interface { type Differ interface {
// IncrementalDiff performs a diff on a record-by-record basis, and returns a sets for which records need to be created, deleted, or modified. // IncrementalDiff performs a diff on a record-by-record basis, and returns a sets for which records need to be created, deleted, or modified.
IncrementalDiff(existing []*models.RecordConfig) (reportMsgs []string, create, toDelete, modify Changeset, err error) IncrementalDiff(existing []*models.RecordConfig) (reportMsgs []string, create, toDelete, modify Changeset, actualChangeCount int, err error)
// ChangedGroups performs a diff more appropriate for providers with a "RecordSet" model, where all records with the same name and type are grouped. // ChangedGroups performs a diff more appropriate for providers with a "RecordSet" model, where all records with the same name and type are grouped.
// Individual record changes are often not useful in such scenarios. Instead we return a map of record keys to a list of change descriptions within that group. // Individual record changes are often not useful in such scenarios. Instead we return a map of record keys to a list of change descriptions within that group.
ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, []string, error) ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, []string, int, error)
} }
type differ struct { type differ struct {

View file

@ -32,10 +32,10 @@ type differCompat struct {
// IncrementalDiff usees pkg/diff2 to generate output compatible with systems // IncrementalDiff usees pkg/diff2 to generate output compatible with systems
// still using NewCompat(). // still using NewCompat().
func (d *differCompat) IncrementalDiff(existing []*models.RecordConfig) (reportMsgs []string, toCreate, toDelete, toModify Changeset, err error) { func (d *differCompat) IncrementalDiff(existing []*models.RecordConfig) (reportMsgs []string, toCreate, toDelete, toModify Changeset, actualChangeCount int, err error) {
instructions, err := diff2.ByRecord(existing, d.dc, nil) instructions, actualChangeCount, err := diff2.ByRecord(existing, d.dc, nil)
if err != nil { if err != nil {
return nil, nil, nil, nil, err return nil, nil, nil, nil, 0, err
} }
for _, inst := range instructions { for _, inst := range instructions {
@ -71,11 +71,11 @@ func GenerateMessageCorrections(msgs []string) (corrections []*models.Correction
} }
// ChangedGroups provides the same results as IncrementalDiff but grouped by key. // ChangedGroups provides the same results as IncrementalDiff but grouped by key.
func (d *differCompat) ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, []string, error) { func (d *differCompat) ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, []string, int, error) {
changedKeys := map[models.RecordKey][]string{} changedKeys := map[models.RecordKey][]string{}
toReport, toCreate, toDelete, toModify, err := d.IncrementalDiff(existing) toReport, toCreate, toDelete, toModify, actualChangeCount, err := d.IncrementalDiff(existing)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, 0, err
} }
for _, c := range toCreate { for _, c := range toCreate {
changedKeys[c.Desired.Key()] = append(changedKeys[c.Desired.Key()], c.String()) changedKeys[c.Desired.Key()] = append(changedKeys[c.Desired.Key()], c.String())
@ -86,5 +86,5 @@ func (d *differCompat) ChangedGroups(existing []*models.RecordConfig) (map[model
for _, m := range toModify { for _, m := range toModify {
changedKeys[m.Desired.Key()] = append(changedKeys[m.Desired.Key()], m.String()) changedKeys[m.Desired.Key()] = append(changedKeys[m.Desired.Key()], m.String())
} }
return changedKeys, toReport, nil return changedKeys, toReport, actualChangeCount, nil
} }

View file

@ -9,8 +9,9 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
) )
func analyzeByRecordSet(cc *CompareConfig) ChangeList { func analyzeByRecordSet(cc *CompareConfig) (ChangeList, int) {
var instructions ChangeList var instructions ChangeList
var actualChangeCount int
// For each label... // For each label...
for _, lc := range cc.ldata { for _, lc := range cc.ldata {
// for each type at that label... // for each type at that label...
@ -18,7 +19,9 @@ func analyzeByRecordSet(cc *CompareConfig) ChangeList {
// ...if there are changes generate an instruction. // ...if there are changes generate an instruction.
ets := rt.existingTargets ets := rt.existingTargets
dts := rt.desiredTargets dts := rt.desiredTargets
msgs := genmsgs(ets, dts) cs := diffTargets(ets, dts)
actualChangeCount += len(cs)
msgs := justMsgs(cs)
if len(msgs) == 0 { // No differences? if len(msgs) == 0 { // No differences?
// The records at this rset are the same. No work to be done. // The records at this rset are the same. No work to be done.
continue continue
@ -35,11 +38,12 @@ func analyzeByRecordSet(cc *CompareConfig) ChangeList {
instructions = orderByDependencies(instructions) instructions = orderByDependencies(instructions)
return instructions return instructions, actualChangeCount
} }
func analyzeByLabel(cc *CompareConfig) ChangeList { func analyzeByLabel(cc *CompareConfig) (ChangeList, int) {
var instructions ChangeList var instructions ChangeList
var actualChangeCount int
// Accumulate any changes and collect the info needed to generate instructions. // Accumulate any changes and collect the info needed to generate instructions.
for _, lc := range cc.ldata { for _, lc := range cc.ldata {
// for each type at that label... // for each type at that label...
@ -52,7 +56,9 @@ func analyzeByLabel(cc *CompareConfig) ChangeList {
// for each type at that label... // for each type at that label...
ets := rt.existingTargets ets := rt.existingTargets
dts := rt.desiredTargets dts := rt.desiredTargets
msgs := genmsgs(ets, dts) cs := diffTargets(ets, dts)
actualChangeCount += len(cs)
msgs := justMsgs(cs)
k := models.RecordKey{NameFQDN: label, Type: rt.rType} k := models.RecordKey{NameFQDN: label, Type: rt.rType}
msgsByKey[k] = msgs msgsByKey[k] = msgs
accMsgs = append(accMsgs, msgs...) // Accumulate the messages accMsgs = append(accMsgs, msgs...) // Accumulate the messages
@ -79,25 +85,27 @@ func analyzeByLabel(cc *CompareConfig) ChangeList {
instructions = orderByDependencies(instructions) instructions = orderByDependencies(instructions)
return instructions return instructions, actualChangeCount
} }
func analyzeByRecord(cc *CompareConfig) ChangeList { func analyzeByRecord(cc *CompareConfig) (ChangeList, int) {
var instructions ChangeList var instructions ChangeList
var actualChangeCount int
// For each label, for each type at that label, see if there are any changes. // For each label, for each type at that label, see if there are any changes.
for _, lc := range cc.ldata { for _, lc := range cc.ldata {
for _, rt := range lc.tdata { for _, rt := range lc.tdata {
ets := rt.existingTargets ets := rt.existingTargets
dts := rt.desiredTargets dts := rt.desiredTargets
cs := diffTargets(ets, dts) cs := diffTargets(ets, dts)
actualChangeCount += len(cs)
instructions = append(instructions, cs...) instructions = append(instructions, cs...)
} }
} }
instructions = orderByDependencies(instructions) instructions = orderByDependencies(instructions)
return instructions return instructions, actualChangeCount
} }
// FYI: there is no analyzeByZone. diff2.ByZone() calls analyzeByRecords(). // FYI: there is no analyzeByZone. diff2.ByZone() calls analyzeByRecords().
@ -303,10 +311,6 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
return instructions return instructions
} }
func genmsgs(existing, desired []targetConfig) []string {
return justMsgs(diffTargets(existing, desired))
}
func justMsgs(cl ChangeList) []string { func justMsgs(cl ChangeList) []string {
var msgs []string var msgs []string
for _, c := range cl { for _, c := range cl {

View file

@ -127,7 +127,13 @@ func compareCL(t *testing.T, fnname, testname, testpart string, gotcl ChangeList
if d != "" { if d != "" {
t.Errorf("%s()/%s (wantChange%s):\n===got===\n%s\n===want===\n%s\n===diff===\n%s\n===", fnname, testname, testpart, gs, ws, d) t.Errorf("%s()/%s (wantChange%s):\n===got===\n%s\n===want===\n%s\n===diff===\n%s\n===", fnname, testname, testpart, gs, ws, d)
} }
}
func compareACC(t *testing.T, fnname, testname, testpart string, gotacc int, wantacc int) {
t.Helper()
if gotacc != wantacc {
t.Errorf("%s()/%s (wantChange%s):\n===got===\n%v\n===want===\n%v\n", fnname, testname, testpart, gotacc, wantacc)
}
} }
func Test_analyzeByRecordSet(t *testing.T) { func Test_analyzeByRecordSet(t *testing.T) {
@ -150,6 +156,7 @@ func Test_analyzeByRecordSet(t *testing.T) {
wantChangeRec string wantChangeRec string
wantMsgsRec string wantMsgsRec string
wantChangeZone string wantChangeZone string
wantChangeCount int
}{ }{
{ {
@ -159,6 +166,7 @@ func Test_analyzeByRecordSet(t *testing.T) {
existing: models.Records{testDataAA1234}, existing: models.Records{testDataAA1234},
desired: models.Records{testDataAA1234clone}, desired: models.Records{testDataAA1234clone},
}, },
wantChangeCount: 0,
wantMsgs: "", // Empty wantMsgs: "", // Empty
wantChangeRSet: "ChangeList: len=0", wantChangeRSet: "ChangeList: len=0",
wantChangeLabel: "ChangeList: len=0", wantChangeLabel: "ChangeList: len=0",
@ -172,6 +180,7 @@ func Test_analyzeByRecordSet(t *testing.T) {
existing: models.Records{testDataAA1234, testDataAMX10a}, existing: models.Records{testDataAA1234, testDataAMX10a},
desired: models.Records{testDataAA1234clone, testDataAMX20b}, desired: models.Records{testDataAA1234clone, testDataAMX20b},
}, },
wantChangeCount: 1,
wantMsgs: "± MODIFY laba.f.com MX (10 laba.f.com. ttl=300) -> (20 labb.f.com. ttl=300)", wantMsgs: "± MODIFY laba.f.com MX (10 laba.f.com. ttl=300) -> (20 labb.f.com. ttl=300)",
wantChangeRSet: ` wantChangeRSet: `
ChangeList: len=1 ChangeList: len=1
@ -206,6 +215,7 @@ ChangeList: len=1
existing: models.Records{testDataAA1234, testDataApexMX1aaa}, existing: models.Records{testDataAA1234, testDataApexMX1aaa},
desired: models.Records{testDataAA1234clone, testDataApexMX22bbb}, desired: models.Records{testDataAA1234clone, testDataApexMX22bbb},
}, },
wantChangeCount: 1,
wantMsgs: "± MODIFY f.com MX (1 aaa.f.com. ttl=300) -> (22 bbb.f.com. ttl=300)", wantMsgs: "± MODIFY f.com MX (1 aaa.f.com. ttl=300) -> (22 bbb.f.com. ttl=300)",
wantChangeRSet: ` wantChangeRSet: `
ChangeList: len=1 ChangeList: len=1
@ -240,6 +250,7 @@ ChangeList: len=1
existing: models.Records{testDataAA1234, testDataAMX10a}, existing: models.Records{testDataAA1234, testDataAMX10a},
desired: models.Records{testDataAA1234clone, testDataAA12345, testDataAMX20b}, desired: models.Records{testDataAA1234clone, testDataAA12345, testDataAMX20b},
}, },
wantChangeCount: 2,
wantMsgs: ` wantMsgs: `
± MODIFY laba.f.com MX (10 laba.f.com. ttl=300) -> (20 labb.f.com. ttl=300) ± MODIFY laba.f.com MX (10 laba.f.com. ttl=300) -> (20 labb.f.com. ttl=300)
+ CREATE laba.f.com A 1.2.3.5 ttl=300 + CREATE laba.f.com A 1.2.3.5 ttl=300
@ -290,6 +301,7 @@ ChangeList: len=2
existing: models.Records{testDataAA1234, testDataCCa}, existing: models.Records{testDataAA1234, testDataCCa},
desired: models.Records{d13, d3}, desired: models.Records{d13, d3},
}, },
wantChangeCount: 3,
wantMsgs: ` wantMsgs: `
+ CREATE labe.f.com A 10.10.10.95 ttl=300 + CREATE labe.f.com A 10.10.10.95 ttl=300
± MODIFY labc.f.com CNAME (laba.f.com. ttl=300) -> (labe.f.com. ttl=300) ± MODIFY labc.f.com CNAME (laba.f.com. ttl=300) -> (labe.f.com. ttl=300)
@ -352,6 +364,7 @@ ChangeList: len=3
existing: models.Records{testDataAA1234, testDataAMX10a, testDataCCa, testDataEA15, e4, e5, e6, e7, e8, e9, e10, e11}, existing: models.Records{testDataAA1234, testDataAMX10a, testDataCCa, testDataEA15, e4, e5, e6, e7, e8, e9, e10, e11},
desired: models.Records{testDataAA1234clone, testDataAA12345, testDataAMX20b, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12}, desired: models.Records{testDataAA1234clone, testDataAA12345, testDataAMX20b, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12},
}, },
wantChangeCount: 11,
wantMsgs: ` wantMsgs: `
+ CREATE labf.f.com TXT "foo" ttl=300 + CREATE labf.f.com TXT "foo" ttl=300
± MODIFY labg.f.com NS (labc.f.com. ttl=300) -> (labf.f.com. ttl=300) ± MODIFY labg.f.com NS (labc.f.com. ttl=300) -> (labf.f.com. ttl=300)
@ -525,21 +538,24 @@ ChangeList: len=11
// Therefore we have to run NewCompareConfig() each time. // Therefore we have to run NewCompareConfig() each time.
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cl := analyzeByRecordSet(NewCompareConfig(tt.args.origin, tt.args.existing, tt.args.desired, tt.args.compFn)) cl, actualChangeCount := analyzeByRecordSet(NewCompareConfig(tt.args.origin, tt.args.existing, tt.args.desired, tt.args.compFn))
compareMsgs(t, "analyzeByRecordSet", tt.name, "RSet", cl, tt.wantMsgsRSet, tt.wantMsgs) compareMsgs(t, "analyzeByRecordSet", tt.name, "RSet", cl, tt.wantMsgsRSet, tt.wantMsgs)
compareCL(t, "analyzeByRecordSet", tt.name, "RSet", cl, tt.wantChangeRSet) compareCL(t, "analyzeByRecordSet", tt.name, "RSet", cl, tt.wantChangeRSet)
compareACC(t, "analyzeByRecordSet", tt.name, "ACC", actualChangeCount, tt.wantChangeCount)
}) })
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cl := analyzeByLabel(NewCompareConfig(tt.args.origin, tt.args.existing, tt.args.desired, tt.args.compFn)) cl, actualChangeCount := analyzeByLabel(NewCompareConfig(tt.args.origin, tt.args.existing, tt.args.desired, tt.args.compFn))
compareMsgs(t, "analyzeByLabel", tt.name, "Label", cl, tt.wantMsgsLabel, tt.wantMsgs) compareMsgs(t, "analyzeByLabel", tt.name, "Label", cl, tt.wantMsgsLabel, tt.wantMsgs)
compareCL(t, "analyzeByLabel", tt.name, "Label", cl, tt.wantChangeLabel) compareCL(t, "analyzeByLabel", tt.name, "Label", cl, tt.wantChangeLabel)
compareACC(t, "analyzeByLabel", tt.name, "ACC", actualChangeCount, tt.wantChangeCount)
}) })
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
cl := analyzeByRecord(NewCompareConfig(tt.args.origin, tt.args.existing, tt.args.desired, tt.args.compFn)) cl, actualChangeCount := analyzeByRecord(NewCompareConfig(tt.args.origin, tt.args.existing, tt.args.desired, tt.args.compFn))
compareMsgs(t, "analyzeByRecord", tt.name, "Rec", cl, tt.wantMsgsRec, tt.wantMsgs) compareMsgs(t, "analyzeByRecord", tt.name, "Rec", cl, tt.wantMsgsRec, tt.wantMsgs)
compareCL(t, "analyzeByRecord", tt.name, "Rec", cl, tt.wantChangeRec) compareCL(t, "analyzeByRecord", tt.name, "Rec", cl, tt.wantChangeRec)
compareACC(t, "analyzeByRecord", tt.name, "ACC", actualChangeCount, tt.wantChangeCount)
}) })
// NB(tlim): There is no analyzeByZone(). diff2.ByZone() uses analyzeByRecord(). // NB(tlim): There is no analyzeByZone(). diff2.ByZone() uses analyzeByRecord().

View file

@ -151,7 +151,7 @@ func (c *Change) CreateCorrectionWithMessage(msg string, correctionFunction func
// www.example.com, A, and a list of all the desired IP addresses. // www.example.com, A, and a list of all the desired IP addresses.
// //
// Examples include: AZURE_DNS, GCORE, NS1, ROUTE53 // Examples include: AZURE_DNS, GCORE, NS1, ROUTE53
func ByRecordSet(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, error) { func ByRecordSet(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, int, error) {
return byHelper(analyzeByRecordSet, existing, dc, compFunc) return byHelper(analyzeByRecordSet, existing, dc, compFunc)
} }
@ -163,7 +163,7 @@ func ByRecordSet(existing models.Records, dc *models.DomainConfig, compFunc Comp
// to be served at a particular label, or the label itself is deleted. // to be served at a particular label, or the label itself is deleted.
// //
// Examples include: GANDI_V5 // Examples include: GANDI_V5
func ByLabel(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, error) { func ByLabel(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, int, error) {
return byHelper(analyzeByLabel, existing, dc, compFunc) return byHelper(analyzeByLabel, existing, dc, compFunc)
} }
@ -179,7 +179,7 @@ func ByLabel(existing models.Records, dc *models.DomainConfig, compFunc Comparab
// A delete always has exactly 1 old: .Old[0] // A delete always has exactly 1 old: .Old[0]
// //
// Examples include: CLOUDFLAREAPI, HEDNS, INWX, MSDNS, OVH, PORKBUN, VULTR // Examples include: CLOUDFLAREAPI, HEDNS, INWX, MSDNS, OVH, PORKBUN, VULTR
func ByRecord(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, error) { func ByRecord(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, int, error) {
return byHelper(analyzeByRecord, existing, dc, compFunc) return byHelper(analyzeByRecord, existing, dc, compFunc)
} }
@ -205,23 +205,16 @@ func ByRecord(existing models.Records, dc *models.DomainConfig, compFunc Compara
// } // }
// //
// Example providers include: BIND, AUTODNS // Example providers include: BIND, AUTODNS
func ByZone(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) ([]string, bool, error) { func ByZone(existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) ([]string, bool, int, error) {
// Only return the messages. The caller has the list of records needed to build the new zone. // Only return the messages. The caller has the list of records needed to build the new zone.
instructions, err := byHelper(analyzeByRecord, existing, dc, compFunc) instructions, actualChangeCount, err := byHelper(analyzeByRecord, existing, dc, compFunc)
changes := false return justMsgs(instructions), actualChangeCount > 0, actualChangeCount, err
for i := range instructions {
//fmt.Printf("DEBUG: ByZone #%d: %v\n", i, ii)
if instructions[i].Type != REPORT {
changes = true
}
}
return justMsgs(instructions), changes, err
} }
// //
// byHelper does 90% of the work for the By*() calls. // byHelper does 90% of the work for the By*() calls.
func byHelper(fn func(cc *CompareConfig) ChangeList, existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, error) { func byHelper(fn func(cc *CompareConfig) (ChangeList, int), existing models.Records, dc *models.DomainConfig, compFunc ComparableFunc) (ChangeList, int, error) {
// Process NO_PURGE/ENSURE_ABSENT and IGNORE*(). // Process NO_PURGE/ENSURE_ABSENT and IGNORE*().
desired, msgs, err := handsoff( desired, msgs, err := handsoff(
@ -232,14 +225,14 @@ func byHelper(fn func(cc *CompareConfig) ChangeList, existing models.Records, dc
dc.KeepUnknown, dc.KeepUnknown,
) )
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Regroup existing/desiredd for easy comparison: // Regroup existing/desiredd for easy comparison:
cc := NewCompareConfig(dc.Name, existing, desired, compFunc) cc := NewCompareConfig(dc.Name, existing, desired, compFunc)
// Analyze and generate the instructions: // Analyze and generate the instructions:
instructions := fn(cc) instructions, actualChangeCount := fn(cc)
// If we have msgs, create a change to output them: // If we have msgs, create a change to output them:
if len(msgs) != 0 { if len(msgs) != 0 {
@ -252,5 +245,5 @@ func byHelper(fn func(cc *CompareConfig) ChangeList, existing models.Records, dc
instructions = append([]Change{chg}, instructions...) instructions = append([]Change{chg}, instructions...)
} }
return instructions, nil return instructions, actualChangeCount, nil
} }

View file

@ -7,11 +7,11 @@ import (
// CorrectZoneRecords calls both GetZoneRecords, does any // CorrectZoneRecords calls both GetZoneRecords, does any
// post-processing, and then calls GetZoneRecordsCorrections. The // post-processing, and then calls GetZoneRecordsCorrections. The
// name sucks because all the good names were taken. // name sucks because all the good names were taken.
func CorrectZoneRecords(driver models.DNSProvider, dc *models.DomainConfig) ([]*models.Correction, []*models.Correction, error) { func CorrectZoneRecords(driver models.DNSProvider, dc *models.DomainConfig) ([]*models.Correction, []*models.Correction, int, error) {
existingRecords, err := driver.GetZoneRecords(dc.Name, dc.Metadata) existingRecords, err := driver.GetZoneRecords(dc.Name, dc.Metadata)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, 0, err
} }
// downcase // downcase
@ -26,7 +26,7 @@ func CorrectZoneRecords(driver models.DNSProvider, dc *models.DomainConfig) ([]*
// dc.Records. // dc.Records.
dc, err = dc.Copy() dc, err = dc.Copy()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, 0, err
} }
// punycode // punycode
@ -34,9 +34,9 @@ func CorrectZoneRecords(driver models.DNSProvider, dc *models.DomainConfig) ([]*
// FIXME(tlim) It is a waste to PunyCode every iteration. // FIXME(tlim) It is a waste to PunyCode every iteration.
// This should be moved to where the JavaScript is processed. // This should be moved to where the JavaScript is processed.
everything, err := driver.GetZoneRecordsCorrections(dc, existingRecords) everything, actualChangeCount, err := driver.GetZoneRecordsCorrections(dc, existingRecords)
reports, corrections := splitReportsAndCorrections(everything) reports, corrections := splitReportsAndCorrections(everything)
return reports, corrections, err return reports, corrections, actualChangeCount, err
} }
func splitReportsAndCorrections(everything []*models.Correction) (reports, corrections []*models.Correction) { func splitReportsAndCorrections(everything []*models.Correction) (reports, corrections []*models.Correction) {

View file

@ -107,10 +107,10 @@ func (a *edgeDNSProvider) EnsureZoneExists(domain string) error {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (a *edgeDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (a *edgeDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
keysToUpdate, toReport, err := diff.NewCompat(dc).ChangedGroups(existingRecords) keysToUpdate, toReport, actualChangeCount, err := diff.NewCompat(dc).ChangedGroups(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -180,7 +180,7 @@ func (a *edgeDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
// AutoDnsSec correction // AutoDnsSec correction
existingAutoDNSSecEnabled, err := isAutoDNSSecEnabled(dc.Name) existingAutoDNSSecEnabled, err := isAutoDNSSecEnabled(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
desiredAutoDNSSecEnabled := dc.AutoDNSSEC == "on" desiredAutoDNSSecEnabled := dc.AutoDNSSEC == "on"
@ -205,7 +205,7 @@ func (a *edgeDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
printer.Debugf("autoDNSSecEnable: Disable AutoDnsSec for zone %s\n", dc.Name) printer.Debugf("autoDNSSecEnable: Disable AutoDnsSec for zone %s\n", dc.Name)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// GetNameservers returns the nameservers for a domain. // GetNameservers returns the nameservers for a domain.

View file

@ -71,14 +71,14 @@ func New(settings map[string]string, _ json.RawMessage) (providers.DNSServicePro
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *autoDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *autoDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
domain := dc.Name domain := dc.Name
var corrections []*models.Correction var corrections []*models.Correction
msgs, changed, err := diff2.ByZone(existingRecords, dc, nil) msgs, changed, actualChangeCount, err := diff2.ByZone(existingRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if changed { if changed {
@ -107,7 +107,7 @@ func (api *autoDNSProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, e
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func recordsToNative(recs models.Records) ([]*models.Nameserver, uint32, []*ResourceRecord) { func recordsToNative(recs models.Records) ([]*models.Nameserver, uint32, []*ResourceRecord) {

View file

@ -426,7 +426,7 @@ func hasNSDeletion(changes diff2.ChangeList) bool {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *axfrddnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, error) { func (c *axfrddnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, int, error) {
// Ignoring the SOA, others providers don't manage it either. // Ignoring the SOA, others providers don't manage it either.
if len(foundRecords) >= 1 && foundRecords[0].Type == "SOA" { if len(foundRecords) >= 1 && foundRecords[0].Type == "SOA" {
foundRecords = foundRecords[1:] foundRecords = foundRecords[1:]
@ -466,19 +466,19 @@ func (c *axfrddnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, fo
dummyNs1, err := dns.NewRR(dc.Name + ". IN NS 255.255.255.255") dummyNs1, err := dns.NewRR(dc.Name + ". IN NS 255.255.255.255")
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
dummyNs2, err := dns.NewRR(dc.Name + ". IN NS 255.255.255.255") dummyNs2, err := dns.NewRR(dc.Name + ". IN NS 255.255.255.255")
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
changes, err := diff2.ByRecord(foundRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecord(foundRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if changes == nil { if changes == nil {
return nil, nil return nil, 0, nil
} }
// A DNS server should silently ignore a DDNS update that removes // A DNS server should silently ignore a DDNS update that removes
@ -547,5 +547,5 @@ func (c *axfrddnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, fo
if len(reports) > 0 { if len(reports) > 0 {
returnValue = append(returnValue, c.BuildCorrection(dc, reports, nil)) returnValue = append(returnValue, c.BuildCorrection(dc, reports, nil))
} }
return returnValue, nil return returnValue, actualChangeCount, nil
} }

View file

@ -190,14 +190,14 @@ func (a *azurednsProvider) getExistingRecords(domain string) (models.Records, []
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (a *azurednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (a *azurednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
// Azure is a "ByRecordSet" API. // Azure is a "ByRecordSet" API.
changes, err := diff2.ByRecordSet(existingRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecordSet(existingRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -230,7 +230,7 @@ func (a *azurednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (a *azurednsProvider) recordCreate(zoneName string, reckey models.RecordKey, recs models.Records) error { func (a *azurednsProvider) recordCreate(zoneName string, reckey models.RecordKey, recs models.Records) error {

View file

@ -187,12 +187,12 @@ func (a *azurednsProvider) getExistingRecords(domain string) (models.Records, []
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (a *azurednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (a *azurednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
changes, err := diff2.ByRecordSet(existingRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecordSet(existingRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -225,7 +225,7 @@ func (a *azurednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (a *azurednsProvider) recordCreate(zoneName string, reckey models.RecordKey, recs models.Records) error { func (a *azurednsProvider) recordCreate(zoneName string, reckey models.RecordKey, recs models.Records) error {

View file

@ -217,7 +217,7 @@ func ParseZoneContents(content string, zoneName string, zonefileName string) (mo
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *bindProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, error) { func (c *bindProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
changes := false changes := false
@ -248,12 +248,13 @@ func (c *bindProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundR
var msgs []string var msgs []string
var err error var err error
msgs, changes, err = diff2.ByZone(foundRecords, dc, nil) var actualChangeCount int
msgs, changes, actualChangeCount, err = diff2.ByZone(foundRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if !changes { if !changes {
return nil, nil return nil, 0, nil
} }
msg = strings.Join(msgs, "\n") msg = strings.Join(msgs, "\n")
@ -311,7 +312,7 @@ func (c *bindProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundR
}, },
}) })
return corrections, nil return corrections, actualChangeCount, nil
} }
// preprocessFilename pre-processes a filename we're about to os.Create() // preprocessFilename pre-processes a filename we're about to os.Create()

View file

@ -2,6 +2,7 @@ package bunnydns
import ( import (
"fmt" "fmt"
"github.com/StackExchange/dnscontrol/v4/models" "github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/diff2" "github.com/StackExchange/dnscontrol/v4/pkg/diff2"
"github.com/StackExchange/dnscontrol/v4/pkg/printer" "github.com/StackExchange/dnscontrol/v4/pkg/printer"
@ -53,7 +54,7 @@ func (b *bunnydnsProvider) GetZoneRecords(domain string, meta map[string]string)
return recs, nil return recs, nil
} }
func (b *bunnydnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (b *bunnydnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
// Bunny DNS never returns NS records for the apex domain, so these are artificially added when retrieving records. // Bunny DNS never returns NS records for the apex domain, so these are artificially added when retrieving records.
// As no TTL can be configured or retrieved for these NS records, we set it to 0 to avoid unnecessary updates. // As no TTL can be configured or retrieved for these NS records, we set it to 0 to avoid unnecessary updates.
for _, rc := range dc.Records { for _, rc := range dc.Records {
@ -68,12 +69,12 @@ func (b *bunnydnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
zone, err := b.findZoneByDomain(dc.Name) zone, err := b.findZoneByDomain(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
instructions, err := diff2.ByRecord(existing, dc, nil) instructions, actualChangeCount, err := diff2.ByRecord(existing, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corrections []*models.Correction var corrections []*models.Correction
@ -100,7 +101,7 @@ func (b *bunnydnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (b *bunnydnsProvider) mkCreateCorrection(zoneID int64, newRec *models.RecordConfig, msg string) *models.Correction { func (b *bunnydnsProvider) mkCreateCorrection(zoneID int64, newRec *models.RecordConfig, msg string) *models.Correction {

View file

@ -204,7 +204,7 @@ func (c *cloudflareProvider) getDomainID(name string) (string, error) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
for _, rec := range dc.Records { for _, rec := range dc.Records {
if rec.Type == "ALIAS" { if rec.Type == "ALIAS" {
@ -213,14 +213,14 @@ func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
} }
if err := c.preprocessConfig(dc); err != nil { if err := c.preprocessConfig(dc); err != nil {
return nil, err return nil, 0, err
} }
checkNSModifications(dc) checkNSModifications(dc)
domainID, err := c.getDomainID(dc.Name) domainID, err := c.getDomainID(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, rec := range dc.Records { for _, rec := range dc.Records {
@ -237,9 +237,9 @@ func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
var corrections []*models.Correction var corrections []*models.Correction
// Cloudflare is a "ByRecord" API. // Cloudflare is a "ByRecord" API.
instructions, err := diff2.ByRecord(records, dc, genComparable) instructions, actualChangeCount, err := diff2.ByRecord(records, dc, genComparable)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, inst := range instructions { for _, inst := range instructions {
@ -291,7 +291,7 @@ func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func genComparable(rec *models.RecordConfig) string { func genComparable(rec *models.RecordConfig) string {

View file

@ -114,16 +114,16 @@ func (c *cloudnsProvider) GetNameservers(domain string) ([]*models.Nameserver, e
// } // }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *cloudnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (c *cloudnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
if c.domainIndex == nil { if c.domainIndex == nil {
if err := c.fetchDomainList(); err != nil { if err := c.fetchDomainList(); err != nil {
return nil, err return nil, 0, err
} }
} }
domainID, ok := c.domainIndex[dc.Name] domainID, ok := c.domainIndex[dc.Name]
if !ok { if !ok {
return nil, fmt.Errorf("'%s' not a zone in ClouDNS account", dc.Name) return nil, 0, fmt.Errorf("'%s' not a zone in ClouDNS account", dc.Name)
} }
// Get a list of available TTL values. // Get a list of available TTL values.
@ -134,9 +134,9 @@ func (c *cloudnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
record.TTL = fixTTL(record.TTL) record.TTL = fixTTL(record.TTL)
} }
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -168,7 +168,7 @@ func (c *cloudnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
for _, m := range create { for _, m := range create {
req, err := toReq(m.Desired) req, err := toReq(m.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// ClouDNS does not require the trailing period to be specified when creating an NS record where the A or AAAA record exists in the zone. // ClouDNS does not require the trailing period to be specified when creating an NS record where the A or AAAA record exists in the zone.
@ -203,7 +203,7 @@ func (c *cloudnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
id := m.Existing.Original.(*domainRecord).ID id := m.Existing.Original.(*domainRecord).ID
req, err := toReq(m.Desired) req, err := toReq(m.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// ClouDNS does not require the trailing period to be specified when updating an NS record where the A or AAAA record exists in the zone. // ClouDNS does not require the trailing period to be specified when updating an NS record where the A or AAAA record exists in the zone.
@ -221,7 +221,7 @@ func (c *cloudnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }

View file

@ -75,11 +75,11 @@ func (client *providerClient) GetNameservers(domain string) ([]*models.Nameserve
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (client *providerClient) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, error) { func (client *providerClient) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, int, error) {
toReport, creates, dels, modifications, err := diff.NewCompat(dc).IncrementalDiff(foundRecords) toReport, creates, dels, modifications, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(foundRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -123,7 +123,7 @@ func (client *providerClient) GetZoneRecordsCorrections(dc *models.DomainConfig,
corrections = append(corrections, c) corrections = append(corrections, c)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func makePurge(cor diff.Correlation) zoneResourceRecordEdit { func makePurge(cor diff.Correlation) zoneResourceRecordEdit {

View file

@ -154,10 +154,10 @@ func PrepDesiredRecords(dc *models.DomainConfig, minTTL uint32) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *desecProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (c *desecProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
minTTL, ok, err := c.searchDomainIndex(dc.Name) minTTL, ok, err := c.searchDomainIndex(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if !ok { if !ok {
minTTL = 3600 minTTL = 3600
@ -165,15 +165,15 @@ func (c *desecProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exist
PrepDesiredRecords(dc, minTTL) PrepDesiredRecords(dc, minTTL)
keysToUpdate, toReport, err := diff.NewCompat(dc).ChangedGroups(existing) keysToUpdate, toReport, actualChangeCount, err := diff.NewCompat(dc).ChangedGroups(existing)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
if len(corrections) == 0 && len(keysToUpdate) == 0 { if len(corrections) == 0 && len(keysToUpdate) == 0 {
return nil, nil return nil, 0, nil
} }
desiredRecords := dc.Records.GroupedByKey() desiredRecords := dc.Records.GroupedByKey()
@ -245,7 +245,7 @@ func (c *desecProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exist
// be to just remove the sort. // be to just remove the sort.
//sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) }) //sort.Slice(corrections, func(i, j int) bool { return diff.CorrectionLess(corrections, i, j) })
return corrections, nil return corrections, actualChangeCount, nil
} }
// ListZones return all the zones in the account // ListZones return all the zones in the account

View file

@ -172,12 +172,12 @@ func (api *digitaloceanProvider) GetZoneRecords(domain string, meta map[string]s
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *digitaloceanProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *digitaloceanProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
ctx := context.Background() ctx := context.Background()
toReport, toCreate, toDelete, toModify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, toCreate, toDelete, toModify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -236,7 +236,7 @@ func (api *digitaloceanProvider) GetZoneRecordsCorrections(dc *models.DomainConf
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func getRecords(api *digitaloceanProvider, name string) ([]godo.DomainRecord, error) { func getRecords(api *digitaloceanProvider, name string) ([]godo.DomainRecord, error) {

View file

@ -160,17 +160,17 @@ func (c *dnsimpleProvider) GetZoneRecords(domain string, meta map[string]string)
return cleanedRecords, nil return cleanedRecords, nil
} }
func (c *dnsimpleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (c *dnsimpleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
removeOtherApexNS(dc) removeOtherApexNS(dc)
dnssecFixes, err := c.getDNSSECCorrections(dc) dnssecFixes, err := c.getDNSSECCorrections(dc)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(actual) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(actual)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -202,7 +202,7 @@ func (c *dnsimpleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ac
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func removeApexNS(records models.Records) models.Records { func removeApexNS(records models.Records) models.Records {

View file

@ -103,11 +103,11 @@ func New(settings map[string]string, _ json.RawMessage) (providers.DNSServicePro
// return api.GetZoneRecordsCorrections(dc, existingRecords) // return api.GetZoneRecordsCorrections(dc, existingRecords)
// } // }
func (api *dnsMadeEasyProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *dnsMadeEasyProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
domainName := dc.Name domainName := dc.Name
domain, err := api.findDomain(domainName) domain, err := api.findDomain(domainName)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, rec := range dc.Records { for _, rec := range dc.Records {
@ -120,9 +120,9 @@ func (api *dnsMadeEasyProvider) GetZoneRecordsCorrections(dc *models.DomainConfi
} }
} }
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -186,7 +186,7 @@ func (api *dnsMadeEasyProvider) GetZoneRecordsCorrections(dc *models.DomainConfi
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// EnsureZoneExists creates a zone if it does not exist // EnsureZoneExists creates a zone if it does not exist

View file

@ -25,7 +25,7 @@ func (api *domainNameShopProvider) GetZoneRecords(domain string, meta map[string
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *domainNameShopProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *domainNameShopProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
// Merge TXT strings to one string // Merge TXT strings to one string
for _, rc := range dc.Records { for _, rc := range dc.Records {
@ -39,9 +39,9 @@ func (api *domainNameShopProvider) GetZoneRecordsCorrections(dc *models.DomainCo
record.TTL = fixTTL(record.TTL) record.TTL = fixTTL(record.TTL)
} }
toReport, create, delete, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, delete, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -65,7 +65,7 @@ func (api *domainNameShopProvider) GetZoneRecordsCorrections(dc *models.DomainCo
dnsR, err := api.fromRecordConfig(domainName, r.Desired) dnsR, err := api.fromRecordConfig(domainName, r.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
corr := &models.Correction{ corr := &models.Correction{
@ -81,7 +81,7 @@ func (api *domainNameShopProvider) GetZoneRecordsCorrections(dc *models.DomainCo
dnsR, err := api.fromRecordConfig(domainName, r.Desired) dnsR, err := api.fromRecordConfig(domainName, r.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
dnsR.ID = r.Existing.Original.(*domainNameShopRecord).ID dnsR.ID = r.Existing.Original.(*domainNameShopRecord).ID
@ -94,7 +94,7 @@ func (api *domainNameShopProvider) GetZoneRecordsCorrections(dc *models.DomainCo
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (api *domainNameShopProvider) GetNameservers(domain string) ([]*models.Nameserver, error) { func (api *domainNameShopProvider) GetNameservers(domain string) ([]*models.Nameserver, error) {

View file

@ -187,18 +187,18 @@ func (c *exoscaleProvider) GetZoneRecords(domainName string, meta map[string]str
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *exoscaleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (c *exoscaleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
removeOtherNS(dc) removeOtherNS(dc)
domain, err := c.findDomainByName(dc.Name) domain, err := c.findDomainByName(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
domainID := *domain.ID domainID := *domain.ID
toReport, create, toDelete, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, toDelete, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -228,7 +228,7 @@ func (c *exoscaleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// Returns a function that can be invoked to create a record in a zone. // Returns a function that can be invoked to create a record in a zone.

View file

@ -202,7 +202,7 @@ func PrepDesiredRecords(dc *models.DomainConfig) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (client *gandiv5Provider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (client *gandiv5Provider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
if client.debug { if client.debug {
debugRecords("GenDC input", existing) debugRecords("GenDC input", existing)
@ -214,9 +214,9 @@ func (client *gandiv5Provider) GetZoneRecordsCorrections(dc *models.DomainConfig
// Gandi is a "ByLabel" API with the odd exception that changes must be // Gandi is a "ByLabel" API with the odd exception that changes must be
// done one label:rtype at a time. // done one label:rtype at a time.
instructions, err := diff2.ByLabel(existing, dc, nil) instructions, actualChangeCount, err := diff2.ByLabel(existing, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, inst := range instructions { for _, inst := range instructions {
switch inst.Type { switch inst.Type {
@ -292,7 +292,7 @@ func (client *gandiv5Provider) GetZoneRecordsCorrections(dc *models.DomainConfig
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// debugRecords prints a list of RecordConfig. // debugRecords prints a list of RecordConfig.

View file

@ -241,14 +241,14 @@ func (g *gcloudProvider) getZoneSets(domain string) (models.Records, error) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (g *gcloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (g *gcloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
changes, err := diff2.ByRecordSet(existingRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecordSet(existingRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if len(changes) == 0 { if len(changes) == 0 {
return nil, nil return nil, 0, nil
} }
var corrections []*models.Correction var corrections []*models.Correction
@ -280,7 +280,7 @@ func (g *gcloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
newAdds = nil newAdds = nil
newDels = change.Old[0].Original.(*gdns.ResourceRecordSet) newDels = change.Old[0].Original.(*gdns.ResourceRecordSet)
default: default:
return nil, fmt.Errorf("GCLOUD unhandled change.TYPE %s", change.Type) return nil, 0, fmt.Errorf("GCLOUD unhandled change.TYPE %s", change.Type)
} }
// If the work would overflow the current batch, process what we have so far and start a new batch. // If the work would overflow the current batch, process what we have so far and start a new batch.
@ -308,7 +308,7 @@ func (g *gcloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
// Process the remaining work. // Process the remaining work.
corrections = g.mkCorrection(corrections, accumlatedMsgs, batch, dc.Name) corrections = g.mkCorrection(corrections, accumlatedMsgs, batch, dc.Name)
return corrections, nil return corrections, actualChangeCount, nil
} }
// mkRRSs returns a gdns.ResourceRecordSet using the name, rType, and recs // mkRRSs returns a gdns.ResourceRecordSet using the name, rType, and recs

View file

@ -137,7 +137,7 @@ func generateChangeMsg(updates []string) string {
// a list of functions to call to actually make the desired // a list of functions to call to actually make the desired
// correction, and a message to output to the user when the change is // correction, and a message to output to the user when the change is
// made. // made.
func (c *gcoreProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (c *gcoreProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
// Make delete happen earlier than creates & updates. // Make delete happen earlier than creates & updates.
var corrections []*models.Correction var corrections []*models.Correction
@ -151,9 +151,9 @@ func (c *gcoreProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exist
} }
} }
changes, err := diff2.ByRecordSet(existing, dc, nil) changes, actualChangeCount, err := diff2.ByRecordSet(existing, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -196,7 +196,7 @@ func (c *gcoreProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exist
dnssecEnabled, err := c.dnssdkGetDNSSEC(dc.Name) dnssecEnabled, err := c.dnssdkGetDNSSEC(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if !dnssecEnabled && dc.AutoDNSSEC == "on" { if !dnssecEnabled && dc.AutoDNSSEC == "on" {
@ -221,5 +221,5 @@ func (c *gcoreProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exist
result := append(reports, deletions...) result := append(reports, deletions...)
result = append(result, corrections...) result = append(result, corrections...)
return result, nil return result, actualChangeCount, nil
} }

View file

@ -186,7 +186,7 @@ func (c *hednsProvider) GetNameservers(_ string) ([]*models.Nameserver, error) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *hednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (c *hednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
// Get the SOA record to get the ZoneID, then remove it from the list. // Get the SOA record to get the ZoneID, then remove it from the list.
zoneID := uint64(0) zoneID := uint64(0)
@ -202,10 +202,10 @@ func (c *hednsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, recor
return c.getDiff2DomainCorrections(dc, zoneID, prunedRecords) return c.getDiff2DomainCorrections(dc, zoneID, prunedRecords)
} }
func (c *hednsProvider) getDiff2DomainCorrections(dc *models.DomainConfig, zoneID uint64, records models.Records) ([]*models.Correction, error) { func (c *hednsProvider) getDiff2DomainCorrections(dc *models.DomainConfig, zoneID uint64, records models.Records) ([]*models.Correction, int, error) {
changes, err := diff2.ByRecord(records, dc, nil) changes, actualChangeCount, err := diff2.ByRecord(records, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corrections []*models.Correction var corrections []*models.Correction
@ -243,7 +243,7 @@ func (c *hednsProvider) getDiff2DomainCorrections(dc *models.DomainConfig, zoneI
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// GetZoneRecords returns all the records for the given domain // GetZoneRecords returns all the records for the given domain

View file

@ -74,19 +74,19 @@ func (api *hetznerProvider) EnsureZoneExists(domain string) error {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *hetznerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *hetznerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
domain := dc.Name domain := dc.Name
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
z, err := api.getZone(domain) z, err := api.getZone(domain)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, m := range del { for _, m := range del {
@ -136,7 +136,7 @@ func (api *hetznerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, e
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// GetNameservers returns the nameservers for a domain. // GetNameservers returns the nameservers for a domain.

View file

@ -56,10 +56,10 @@ func (n *HXClient) GetZoneRecords(domain string, meta map[string]string) (models
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *HXClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (n *HXClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
toReport, create, del, mod, err := diff.NewCompat(dc).IncrementalDiff(actual) toReport, create, del, mod, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(actual)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -76,7 +76,7 @@ func (n *HXClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mod
rec := cre.Desired rec := cre.Desired
recordString, err := n.createRecordString(rec, dc.Name) recordString, err := n.createRecordString(rec, dc.Name)
if err != nil { if err != nil {
return corrections, err return corrections, 0, err
} }
params[fmt.Sprintf("ADDRR%d", addrridx)] = recordString params[fmt.Sprintf("ADDRR%d", addrridx)] = recordString
addrridx++ addrridx++
@ -96,7 +96,7 @@ func (n *HXClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mod
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(old) params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(old)
newRecordString, err := n.createRecordString(new, dc.Name) newRecordString, err := n.createRecordString(new, dc.Name)
if err != nil { if err != nil {
return corrections, err return corrections, 0, err
} }
params[fmt.Sprintf("ADDRR%d", addrridx)] = newRecordString params[fmt.Sprintf("ADDRR%d", addrridx)] = newRecordString
addrridx++ addrridx++
@ -113,7 +113,7 @@ func (n *HXClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mod
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func toRecord(r *HXRecord, origin string) *models.RecordConfig { func toRecord(r *HXRecord, origin string) *models.RecordConfig {

View file

@ -123,7 +123,7 @@ func soaToString(s soaValues) string {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
var err error var err error
// TTL must be between (inclusive) 1m and 1y (in fact, a little bit more) // TTL must be between (inclusive) 1m and 1y (in fact, a little bit more)
@ -140,12 +140,12 @@ func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
zone, err := hp.getZone(dc.Name) zone, err := hp.getZone(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
toReport, create, del, mod, err := diff.NewCompat(dc).IncrementalDiff(records) toReport, create, del, mod, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(records)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -225,7 +225,7 @@ func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
if existingAutoDNSSecEnabled && desiredAutoDNSSecEnabled { if existingAutoDNSSecEnabled && desiredAutoDNSSecEnabled {
currentDNSSecOptions, err := hp.getDNSSECOptions(zone.ZoneConfig.ID) currentDNSSecOptions, err := hp.getDNSSECOptions(zone.ZoneConfig.ID)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if !currentDNSSecOptions.PublishKSK { if !currentDNSSecOptions.PublishKSK {
msg = append(msg, "Enabling publishKsk for AutoDNSSec") msg = append(msg, "Enabling publishKsk for AutoDNSSec")
@ -246,7 +246,7 @@ func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
} else if existingAutoDNSSecEnabled && !desiredAutoDNSSecEnabled { } else if existingAutoDNSSecEnabled && !desiredAutoDNSSecEnabled {
currentDNSSecOptions, err := hp.getDNSSECOptions(zone.ZoneConfig.ID) currentDNSSecOptions, err := hp.getDNSSECOptions(zone.ZoneConfig.ID)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
msg = append(msg, "Disable AutoDNSSEC") msg = append(msg, "Disable AutoDNSSEC")
zone.ZoneConfig.DNSSECMode = "off" zone.ZoneConfig.DNSSECMode = "off"
@ -254,7 +254,7 @@ func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
// Remove auto dnssec keys from domain // Remove auto dnssec keys from domain
DomainConfig, err := hp.getDomainConfig(dc.Name) DomainConfig, err := hp.getDomainConfig(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, entry := range DomainConfig.DNSSecEntries { for _, entry := range DomainConfig.DNSSecEntries {
for _, autoDNSKey := range currentDNSSecOptions.Keys { for _, autoDNSKey := range currentDNSSecOptions.Keys {
@ -267,7 +267,7 @@ func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
} }
if !zoneChanged { if !zoneChanged {
return nil, nil return nil, 0, nil
} }
corrections = append(corrections, &models.Correction{ corrections = append(corrections, &models.Correction{
@ -306,7 +306,7 @@ func (hp *hostingdeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
corrections = append(corrections, correction) corrections = append(corrections, correction)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func firstNonZero(items ...uint32) uint32 { func firstNonZero(items ...uint32) uint32 {

View file

@ -45,13 +45,13 @@ func (c *huaweicloudProvider) GetZoneRecords(domain string, meta map[string]stri
// a list of functions to call to actually make the desired // a list of functions to call to actually make the desired
// correction, and a message to output to the user when the change is // correction, and a message to output to the user when the change is
// made. // made.
func (c *huaweicloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (c *huaweicloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
if err := c.getZones(); err != nil { if err := c.getZones(); err != nil {
return nil, err return nil, 0, err
} }
zoneID, ok := c.zoneIDByDomain[dc.Name] zoneID, ok := c.zoneIDByDomain[dc.Name]
if !ok { if !ok {
return nil, fmt.Errorf("zone %s not found", dc.Name) return nil, 0, fmt.Errorf("zone %s not found", dc.Name)
} }
addDefaultMeta(dc.Records) addDefaultMeta(dc.Records)
@ -61,9 +61,9 @@ func (c *huaweicloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
var deletions []*models.Correction var deletions []*models.Correction
var reports []*models.Correction var reports []*models.Correction
changes, err := diff2.ByRecordSet(existing, dc, genComparable) changes, actualChangeCount, err := diff2.ByRecordSet(existing, dc, genComparable)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -133,7 +133,7 @@ func (c *huaweicloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
result := append(reports, deletions...) result := append(reports, deletions...)
result = append(result, corrections...) result = append(result, corrections...)
return result, nil return result, actualChangeCount, nil
} }
func collectRecordsByLineAndWeightAndKey(records models.Records) map[string]models.Records { func collectRecordsByLineAndWeightAndKey(records models.Records) map[string]models.Records {

View file

@ -236,15 +236,15 @@ func checkRecords(records models.Records) error {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *inwxAPI) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, error) { func (api *inwxAPI) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, int, error) {
err := checkRecords(dc.Records) err := checkRecords(dc.Records)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
toReport, create, del, mod, err := diff.NewCompat(dc).IncrementalDiff(foundRecords) toReport, create, del, mod, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(foundRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -272,7 +272,7 @@ func (api *inwxAPI) GetZoneRecordsCorrections(dc *models.DomainConfig, foundReco
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// getDefaultNameservers returns string map with default nameservers based on e.g. sandbox mode. // getDefaultNameservers returns string map with default nameservers based on e.g. sandbox mode.

View file

@ -131,7 +131,7 @@ func (api *linodeProvider) GetZoneRecords(domain string, meta map[string]string)
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *linodeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *linodeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
// Linode doesn't allow selecting an arbitrary TTL, only a set of predefined values // Linode doesn't allow selecting an arbitrary TTL, only a set of predefined values
// We need to make sure we don't change it every time if it is as close as it's going to get // We need to make sure we don't change it every time if it is as close as it's going to get
// The documentation says that it will always round up to the next highest value: 300 -> 300, 301 -> 3600. // The documentation says that it will always round up to the next highest value: 300 -> 300, 301 -> 3600.
@ -142,17 +142,17 @@ func (api *linodeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
if api.domainIndex == nil { if api.domainIndex == nil {
if err := api.fetchDomainList(); err != nil { if err := api.fetchDomainList(); err != nil {
return nil, err return nil, 0, err
} }
} }
domainID, ok := api.domainIndex[dc.Name] domainID, ok := api.domainIndex[dc.Name]
if !ok { if !ok {
return nil, fmt.Errorf("'%s' not a zone in Linode account", dc.Name) return nil, 0, fmt.Errorf("'%s' not a zone in Linode account", dc.Name)
} }
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -174,11 +174,11 @@ func (api *linodeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
for _, m := range create { for _, m := range create {
req, err := toReq(dc, m.Desired) req, err := toReq(dc, m.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
j, err := json.Marshal(req) j, err := json.Marshal(req)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
corr := &models.Correction{ corr := &models.Correction{
Msg: fmt.Sprintf("%s: %s", m.String(), string(j)), Msg: fmt.Sprintf("%s: %s", m.String(), string(j)),
@ -200,11 +200,11 @@ func (api *linodeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
} }
req, err := toReq(dc, m.Desired) req, err := toReq(dc, m.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
j, err := json.Marshal(req) j, err := json.Marshal(req)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
corr := &models.Correction{ corr := &models.Correction{
Msg: fmt.Sprintf("%s, Linode ID: %d: %s", m.String(), id, string(j)), Msg: fmt.Sprintf("%s, Linode ID: %d: %s", m.String(), id, string(j)),
@ -215,7 +215,7 @@ func (api *linodeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (api *linodeProvider) getRecordsForDomain(domainID int, domain string) (models.Records, error) { func (api *linodeProvider) getRecordsForDomain(domainID int, domain string) (models.Records, error) {

View file

@ -270,7 +270,7 @@ func gatherAffectedLabels(groups map[models.RecordKey][]string) (labels map[stri
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *APIClient) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (c *APIClient) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
if c.Debug { if c.Debug {
debugRecords("GenerateZoneRecordsCorrections input:\n", existingRecords) debugRecords("GenerateZoneRecordsCorrections input:\n", existingRecords)
@ -280,16 +280,16 @@ func (c *APIClient) GetZoneRecordsCorrections(dc *models.DomainConfig, existingR
var keysToUpdate map[models.RecordKey][]string var keysToUpdate map[models.RecordKey][]string
differ := diff.NewCompat(dc) differ := diff.NewCompat(dc)
toReport, create, del, modify, err := differ.IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := differ.IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
keysToUpdate, _, err = differ.ChangedGroups(existingRecords) keysToUpdate, _, _, err = differ.ChangedGroups(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, d := range create { for _, d := range create {
@ -365,7 +365,7 @@ func (c *APIClient) GetZoneRecordsCorrections(dc *models.DomainConfig, existingR
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// debugRecords prints a list of RecordConfig. // debugRecords prints a list of RecordConfig.

View file

@ -100,21 +100,21 @@ func (l *luadnsProvider) GetZoneRecords(domain string, meta map[string]string) (
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (l *luadnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (l *luadnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
checkNS(dc) checkNS(dc)
domainID, err := l.getDomainID(dc.Name) domainID, err := l.getDomainID(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corrs []*models.Correction var corrs []*models.Correction
changes, err := diff2.ByRecord(records, dc, nil) changes, actualChangeCount, err := diff2.ByRecord(records, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -133,7 +133,7 @@ func (l *luadnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, reco
} }
corrections = append(corrections, corrs...) corrections = append(corrections, corrs...)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (l *luadnsProvider) makeCreateCorrection(newrec *models.RecordConfig, domainID uint32, msg string) []*models.Correction { func (l *luadnsProvider) makeCreateCorrection(newrec *models.RecordConfig, domainID uint32, msg string) []*models.Correction {

View file

@ -8,14 +8,14 @@ import (
) )
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (client *msdnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, error) { func (client *msdnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, foundRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
models.PostProcessRecords(foundRecords) models.PostProcessRecords(foundRecords)
changes, err := diff2.ByRecord(foundRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecord(foundRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corr *models.Correction var corr *models.Correction
@ -66,7 +66,7 @@ func (client *msdnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (client *msdnsProvider) deleteOneRecord(dnsserver, zonename string, oldrec *models.RecordConfig) error { func (client *msdnsProvider) deleteOneRecord(dnsserver, zonename string, oldrec *models.RecordConfig) error {

View file

@ -114,10 +114,10 @@ func zoneFileToRecords(r io.Reader, origin string) (models.Records, error) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *mythicBeastsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (n *mythicBeastsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
msgs, changes, err := diff2.ByZone(actual, dc, nil) msgs, changes, actualChangeCount, err := diff2.ByZone(actual, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corrections []*models.Correction var corrections []*models.Correction
@ -151,7 +151,7 @@ func (n *mythicBeastsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// GetNameservers returns the nameservers for a domain. // GetNameservers returns the nameservers for a domain.

View file

@ -64,7 +64,7 @@ func newReg(conf map[string]string) (providers.Registrar, error) {
return newProvider(conf, nil) return newProvider(conf, nil)
} }
func newProvider(m map[string]string, metadata json.RawMessage) (*namecheapProvider, error) { func newProvider(m map[string]string, _ json.RawMessage) (*namecheapProvider, error) {
api := &namecheapProvider{} api := &namecheapProvider{}
api.APIUser, api.APIKEY = m["apiuser"], m["apikey"] api.APIUser, api.APIKEY = m["apiuser"], m["apikey"]
if api.APIKEY == "" || api.APIUser == "" { if api.APIKEY == "" || api.APIUser == "" {
@ -236,7 +236,7 @@ func (n *namecheapProvider) GetZoneRecords(domain string, meta map[string]string
// } // }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *namecheapProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (n *namecheapProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
// namecheap does not allow setting @ NS with basic DNS // namecheap does not allow setting @ NS with basic DNS
dc.Filter(func(r *models.RecordConfig) bool { dc.Filter(func(r *models.RecordConfig) bool {
@ -249,9 +249,9 @@ func (n *namecheapProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, a
return true return true
}) })
toReport, create, delete, modify, err := diff.NewCompat(dc).IncrementalDiff(actual) toReport, create, delete, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(actual)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -283,7 +283,7 @@ func (n *namecheapProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, a
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func toRecords(result *nc.DomainDNSGetHostsResult, origin string) ([]*models.RecordConfig, error) { func toRecords(result *nc.DomainDNSGetHostsResult, origin string) ([]*models.RecordConfig, error) {

View file

@ -28,7 +28,7 @@ func (n *namedotcomProvider) GetZoneRecords(domain string, meta map[string]strin
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *namedotcomProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (n *namedotcomProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
checkNSModifications(dc) checkNSModifications(dc)
for _, rec := range dc.Records { for _, rec := range dc.Records {
@ -37,9 +37,9 @@ func (n *namedotcomProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
} }
} }
toReport, create, del, mod, err := diff.NewCompat(dc).IncrementalDiff(actual) toReport, create, del, mod, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(actual)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -67,7 +67,7 @@ func (n *namedotcomProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
corrections = append(corrections, c) corrections = append(corrections, c)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func checkNSModifications(dc *models.DomainConfig) { func checkNSModifications(dc *models.DomainConfig) {

View file

@ -74,7 +74,7 @@ func (api *netcupProvider) GetNameservers(domain string) ([]*models.Nameserver,
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *netcupProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *netcupProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
domain := dc.Name domain := dc.Name
// Setting the TTL is not supported for netcup // Setting the TTL is not supported for netcup
@ -91,9 +91,9 @@ func (api *netcupProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
} }
dc.Records = newRecords dc.Records = newRecords
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -133,5 +133,5 @@ func (api *netcupProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }

View file

@ -160,17 +160,17 @@ func (n *netlifyProvider) ListZones() ([]string, error) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *netlifyProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (n *netlifyProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(records) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(records)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
zone, err := n.getZone(dc.Name) zone, err := n.getZone(dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Deletes first so changing type works etc. // Deletes first so changing type works etc.
@ -214,7 +214,7 @@ func (n *netlifyProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, rec
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func toReq(rc *models.RecordConfig) *dnsRecordCreate { func toReq(rc *models.RecordConfig) *dnsRecordCreate {

View file

@ -198,7 +198,7 @@ func (n *nsone) getDomainCorrectionsDNSSEC(domain, toggleDNSSEC string) *models.
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *nsone) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (n *nsone) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
domain := dc.Name domain := dc.Name
@ -207,9 +207,9 @@ func (n *nsone) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecor
corrections = append(corrections, dnssecCorrections) corrections = append(corrections, dnssecCorrections)
} }
changes, err := diff2.ByRecordSet(existingRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecordSet(existingRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -240,7 +240,7 @@ func (n *nsone) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecor
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (n *nsone) add(recs models.Records, domain string) error { func (n *nsone) add(recs models.Records, domain string) error {

View file

@ -213,7 +213,7 @@ func (o *oracleProvider) GetZoneRecords(zone string, meta map[string]string) (mo
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
var err error var err error
// Ensure we don't emit changes for attempted modification of built-in apex NSs // Ensure we don't emit changes for attempted modification of built-in apex NSs
@ -234,9 +234,9 @@ func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
} }
} }
toReport, create, dels, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, dels, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -258,7 +258,6 @@ func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
createRecords = append(createRecords, rec.Desired) createRecords = append(createRecords, rec.Desired)
desc += rec.String() + "\n" desc += rec.String() + "\n"
} }
desc = desc[:len(desc)-1]
} }
if len(dels) > 0 { if len(dels) > 0 {
@ -266,7 +265,6 @@ func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
deleteRecords = append(deleteRecords, rec.Existing) deleteRecords = append(deleteRecords, rec.Existing)
desc += rec.String() + "\n" desc += rec.String() + "\n"
} }
desc = desc[:len(desc)-1]
} }
if len(modify) > 0 { if len(modify) > 0 {
@ -275,7 +273,6 @@ func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
deleteRecords = append(deleteRecords, rec.Existing) deleteRecords = append(deleteRecords, rec.Existing)
desc += rec.String() + "\n" desc += rec.String() + "\n"
} }
desc = desc[:len(desc)-1]
} }
// There were corrections. Send them as one big batch: // There were corrections. Send them as one big batch:
@ -288,7 +285,7 @@ func (o *oracleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (o *oracleProvider) patch(createRecords, deleteRecords models.Records, domain string) error { func (o *oracleProvider) patch(createRecords, deleteRecords models.Records, domain string) error {

View file

@ -141,11 +141,11 @@ func (c *ovhProvider) GetZoneRecords(domain string, meta map[string]string) (mod
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *ovhProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (c *ovhProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
corrections, err := c.getDiff2DomainCorrections(dc, actual) corrections, actualChangeCount, err := c.getDiff2DomainCorrections(dc, actual)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Only refresh zone if there's a real modification // Only refresh zone if there's a real modification
@ -166,14 +166,14 @@ func (c *ovhProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (c *ovhProvider) getDiff2DomainCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (c *ovhProvider) getDiff2DomainCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
instructions, err := diff2.ByRecord(actual, dc, nil) instructions, actualChangeCount, err := diff2.ByRecord(actual, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, inst := range instructions { for _, inst := range instructions {
@ -200,7 +200,7 @@ func (c *ovhProvider) getDiff2DomainCorrections(dc *models.DomainConfig, actual
panic(fmt.Sprintf("unhandled inst.Type %s", inst.Type)) panic(fmt.Sprintf("unhandled inst.Type %s", inst.Type))
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func nativeToRecord(r *Record, origin string) (*models.RecordConfig, error) { func nativeToRecord(r *Record, origin string) (*models.RecordConfig, error) {

View file

@ -106,15 +106,15 @@ func (api *packetframeProvider) GetZoneRecords(domain string, meta map[string]st
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *packetframeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *packetframeProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
zone, err := api.getZone(dc.Name) zone, err := api.getZone(dc.Name)
if err != nil { if err != nil {
return nil, fmt.Errorf("no such zone %q in Packetframe account", dc.Name) return nil, 0, fmt.Errorf("no such zone %q in Packetframe account", dc.Name)
} }
toReport, create, dels, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, dels, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -122,7 +122,7 @@ func (api *packetframeProvider) GetZoneRecordsCorrections(dc *models.DomainConfi
for _, m := range create { for _, m := range create {
req, err := toReq(zone.ID, m.Desired) req, err := toReq(zone.ID, m.Desired)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
corr := &models.Correction{ corr := &models.Correction{
Msg: m.String(), Msg: m.String(),
@ -168,7 +168,7 @@ func (api *packetframeProvider) GetZoneRecordsCorrections(dc *models.DomainConfi
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func toReq(zoneID string, rc *models.RecordConfig) (*domainRecord, error) { func toReq(zoneID string, rc *models.RecordConfig) (*domainRecord, error) {

View file

@ -102,7 +102,7 @@ func genComparable(rec *models.RecordConfig) string {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (c *porkbunProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (c *porkbunProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
// Block changes to NS records for base domain // Block changes to NS records for base domain
@ -128,9 +128,9 @@ func (c *porkbunProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
} }
} }
changes, err := diff2.ByRecord(existingRecords, dc, genComparable) changes, actualChangeCount, err := diff2.ByRecord(existingRecords, dc, genComparable)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
var corr *models.Correction var corr *models.Correction
@ -140,7 +140,7 @@ func (c *porkbunProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
case diff2.CREATE: case diff2.CREATE:
req, err := toReq(change.New[0]) req, err := toReq(change.New[0])
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
corr = &models.Correction{ corr = &models.Correction{
Msg: change.Msgs[0], Msg: change.Msgs[0],
@ -155,7 +155,7 @@ func (c *porkbunProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
id := change.Old[0].Original.(*domainRecord).ID id := change.Old[0].Original.(*domainRecord).ID
req, err := toReq(change.New[0]) req, err := toReq(change.New[0])
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
corr = &models.Correction{ corr = &models.Correction{
Msg: fmt.Sprintf("%s, porkbun ID: %s", change.Msgs[0], id), Msg: fmt.Sprintf("%s, porkbun ID: %s", change.Msgs[0], id),
@ -183,7 +183,7 @@ func (c *porkbunProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
corrections = append(corrections, corr) corrections = append(corrections, corr)
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format. // GetZoneRecords gets the records of a zone and returns them in RecordConfig format.

View file

@ -11,10 +11,10 @@ import (
"github.com/mittwald/go-powerdns/apis/zones" "github.com/mittwald/go-powerdns/apis/zones"
) )
func (dsp *powerdnsProvider) getDiff2DomainCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (dsp *powerdnsProvider) getDiff2DomainCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
changes, err := diff2.ByRecordSet(existing, dc, nil) changes, actualChangeCount, err := diff2.ByRecordSet(existing, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corrections []*models.Correction var corrections []*models.Correction
@ -75,7 +75,7 @@ func (dsp *powerdnsProvider) getDiff2DomainCorrections(dc *models.DomainConfig,
}, },
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// buildRecordList returns a list of records for the PowerDNS resource record set from a change // buildRecordList returns a list of records for the PowerDNS resource record set from a change

View file

@ -45,20 +45,21 @@ func (dsp *powerdnsProvider) GetZoneRecords(domain string, meta map[string]strin
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (dsp *powerdnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (dsp *powerdnsProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
corrections, err := dsp.getDiff2DomainCorrections(dc, existing) corrections, actualChangeCount, err := dsp.getDiff2DomainCorrections(dc, existing)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// DNSSec corrections // DNSSec corrections
dnssecCorrections, err := dsp.getDNSSECCorrections(dc) dnssecCorrections, err := dsp.getDNSSECCorrections(dc)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
actualChangeCount += len(dnssecCorrections)
return append(corrections, dnssecCorrections...), nil return append(corrections, dnssecCorrections...), actualChangeCount, nil
} }
// EnsureZoneExists creates a zone if it does not exist // EnsureZoneExists creates a zone if it does not exist

View file

@ -171,8 +171,8 @@ func (n None) GetZoneRecords(domain string, meta map[string]string) (models.Reco
} }
// GetZoneRecordsCorrections gets the records of a zone and returns them in RecordConfig format. // GetZoneRecordsCorrections gets the records of a zone and returns them in RecordConfig format.
func (n None) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (n None) GetZoneRecordsCorrections(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
return nil, nil return nil, 0, nil
} }
// GetDomainCorrections returns corrections to update a domain. // GetDomainCorrections returns corrections to update a domain.

View file

@ -106,16 +106,16 @@ func (api *realtimeregisterAPI) GetZoneRecords(domain string, meta map[string]st
return recordConfigs, nil return recordConfigs, nil
} }
func (api *realtimeregisterAPI) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (api *realtimeregisterAPI) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
msgs, changes, err := diff2.ByZone(existing, dc, nil) msgs, changes, actualChangeCount, err := diff2.ByZone(existing, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
var corrections []*models.Correction var corrections []*models.Correction
if !changes { if !changes {
return corrections, nil return corrections, 0, nil
} }
dnssec := api.Zones[dc.Name].Dnssec dnssec := api.Zones[dc.Name].Dnssec
@ -129,6 +129,7 @@ func (api *realtimeregisterAPI) GetZoneRecordsCorrections(dc *models.DomainConfi
return nil return nil
}, },
}) })
actualChangeCount++
} }
if !api.Zones[dc.Name].Dnssec && dc.AutoDNSSEC == "on" { if !api.Zones[dc.Name].Dnssec && dc.AutoDNSSEC == "on" {
@ -140,6 +141,7 @@ func (api *realtimeregisterAPI) GetZoneRecordsCorrections(dc *models.DomainConfi
return nil return nil
}, },
}) })
actualChangeCount++
} }
if changes { if changes {
@ -162,7 +164,7 @@ func (api *realtimeregisterAPI) GetZoneRecordsCorrections(dc *models.DomainConfi
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (api *realtimeregisterAPI) ListZones() ([]string, error) { func (api *realtimeregisterAPI) ListZones() ([]string, error) {

View file

@ -282,10 +282,10 @@ func (r *route53Provider) getZoneRecords(zone r53Types.HostedZone) (models.Recor
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (r *route53Provider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (r *route53Provider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
zone, err := r.getZone(dc) zone, err := r.getZone(dc)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// update zone_id to current zone.id if not specified by the user // update zone_id to current zone.id if not specified by the user
@ -301,9 +301,9 @@ func (r *route53Provider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
// Amazon Route53 is a "ByRecordSet" API. // Amazon Route53 is a "ByRecordSet" API.
// At each label:rtype pair, we either delete all records or UPSERT the desired records. // At each label:rtype pair, we either delete all records or UPSERT the desired records.
instructions, err := diff2.ByRecordSet(existingRecords, dc, nil) instructions, actualChangeCount, err := diff2.ByRecordSet(existingRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
instructions = reorderInstructions(instructions) instructions = reorderInstructions(instructions)
var reports []*models.Correction var reports []*models.Correction
@ -403,10 +403,10 @@ func (r *route53Provider) GetZoneRecordsCorrections(dc *models.DomainConfig, exi
addCorrection(descBatchStr, req) addCorrection(descBatchStr, req)
} }
if err := batcher.Err(); err != nil { if err := batcher.Err(); err != nil {
return nil, err return nil, 0, err
} }
return append(reports, corrections...), nil return append(reports, corrections...), actualChangeCount, nil
} }

View file

@ -29,12 +29,12 @@ func (api *rwthProvider) GetNameservers(domain string) ([]*models.Nameserver, er
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *rwthProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) { func (api *rwthProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
domain := dc.Name domain := dc.Name
toReport, create, del, modify, err := diff.NewCompat(dc).IncrementalDiff(existingRecords) toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -70,5 +70,5 @@ func (api *rwthProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, exis
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }

View file

@ -53,7 +53,7 @@ func (s *sakuracloudProvider) GetZoneRecords(domain string, meta map[string]stri
} }
// GetZoneRecordsCorrections gets the records of a zone and returns them in RecordConfig format. // GetZoneRecordsCorrections gets the records of a zone and returns them in RecordConfig format.
func (s *sakuracloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) { func (s *sakuracloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
// The name servers for the Sakura cloud provider cannot be changed. // The name servers for the Sakura cloud provider cannot be changed.
@ -65,12 +65,12 @@ func (s *sakuracloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
} }
} }
msgs, changes, err := diff2.ByZone(existing, dc, nil) msgs, changes, actualChangeCount, err := diff2.ByZone(existing, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
if !changes { if !changes {
return nil, nil return nil, actualChangeCount, nil
} }
msg := strings.Join(msgs, "\n") msg := strings.Join(msgs, "\n")
@ -87,5 +87,5 @@ func (s *sakuracloudProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
}, },
) )
return corrections, nil return corrections, actualChangeCount, nil
} }

View file

@ -81,15 +81,15 @@ func (s *softlayerProvider) GetZoneRecords(domainName string, meta map[string]st
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (s *softlayerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, error) { func (s *softlayerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
domain, err := s.getDomain(&dc.Name) domain, err := s.getDomain(&dc.Name)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
toReport, create, deletes, modify, err := diff.NewCompat(dc).IncrementalDiff(actual) toReport, create, deletes, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(actual)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
// Start corrections with the reports // Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport) corrections := diff.GenerateMessageCorrections(toReport)
@ -117,7 +117,7 @@ func (s *softlayerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, a
}) })
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (s *softlayerProvider) getDomain(name *string) (*datatypes.Dns_Domain, error) { func (s *softlayerProvider) getDomain(name *string) (*datatypes.Dns_Domain, error) {

View file

@ -114,20 +114,20 @@ func (n *transipProvider) ListZones() ([]string, error) {
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (n *transipProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, curRecords models.Records) ([]*models.Correction, error) { func (n *transipProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, curRecords models.Records) ([]*models.Correction, int, error) {
removeOtherNS(dc) removeOtherNS(dc)
corrections, err := n.getCorrectionsUsingDiff2(dc, curRecords) corrections, actualChangeCount, err := n.getCorrectionsUsingDiff2(dc, curRecords)
return corrections, err return corrections, actualChangeCount, err
} }
func (n *transipProvider) getCorrectionsUsingDiff2(dc *models.DomainConfig, records models.Records) ([]*models.Correction, error) { func (n *transipProvider) getCorrectionsUsingDiff2(dc *models.DomainConfig, records models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
instructions, err := diff2.ByRecordSet(records, dc, nil) instructions, actualChangeCount, err := diff2.ByRecordSet(records, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range instructions { for _, change := range instructions {
@ -136,7 +136,7 @@ func (n *transipProvider) getCorrectionsUsingDiff2(dc *models.DomainConfig, reco
case diff2.DELETE: case diff2.DELETE:
oldEntries, err := recordsToNative(change.Old, true) oldEntries, err := recordsToNative(change.Old, true)
if err != nil { if err != nil {
return corrections, err return corrections, 0, err
} }
correction := change.CreateCorrection( correction := change.CreateCorrection(
wrapChangeFunction( wrapChangeFunction(
@ -149,7 +149,7 @@ func (n *transipProvider) getCorrectionsUsingDiff2(dc *models.DomainConfig, reco
case diff2.CREATE: case diff2.CREATE:
newEntries, err := recordsToNative(change.New, false) newEntries, err := recordsToNative(change.New, false)
if err != nil { if err != nil {
return corrections, err return corrections, 0, err
} }
correction := change.CreateCorrection( correction := change.CreateCorrection(
wrapChangeFunction( wrapChangeFunction(
@ -163,7 +163,7 @@ func (n *transipProvider) getCorrectionsUsingDiff2(dc *models.DomainConfig, reco
if canDirectApplyDNSEntries(change) { if canDirectApplyDNSEntries(change) {
newEntries, err := recordsToNative(change.New, false) newEntries, err := recordsToNative(change.New, false)
if err != nil { if err != nil {
return corrections, err return corrections, 0, err
} }
correction := change.CreateCorrection( correction := change.CreateCorrection(
wrapChangeFunction( wrapChangeFunction(
@ -184,7 +184,7 @@ func (n *transipProvider) getCorrectionsUsingDiff2(dc *models.DomainConfig, reco
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
func (n *transipProvider) recreateRecordSet(dc *models.DomainConfig, change diff2.Change) []*models.Correction { func (n *transipProvider) recreateRecordSet(dc *models.DomainConfig, change diff2.Change) []*models.Correction {

View file

@ -115,7 +115,7 @@ func (api *vultrProvider) GetZoneRecords(domain string, meta map[string]string)
} }
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records. // GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
func (api *vultrProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, curRecords models.Records) ([]*models.Correction, error) { func (api *vultrProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, curRecords models.Records) ([]*models.Correction, int, error) {
var corrections []*models.Correction var corrections []*models.Correction
for _, rec := range dc.Records { for _, rec := range dc.Records {
@ -124,7 +124,7 @@ func (api *vultrProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, cur
// These rtypes are hostnames, therefore need to be converted (unlike, for example, an AAAA record) // These rtypes are hostnames, therefore need to be converted (unlike, for example, an AAAA record)
t, err := idna.ToUnicode(rec.GetTargetField()) t, err := idna.ToUnicode(rec.GetTargetField())
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
rec.SetTarget(t) rec.SetTarget(t)
default: default:
@ -132,10 +132,9 @@ func (api *vultrProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, cur
} }
} }
changes, err := diff2.ByRecord(curRecords, dc, nil) changes, actualChangeCount, err := diff2.ByRecord(curRecords, dc, nil)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
for _, change := range changes { for _, change := range changes {
@ -172,7 +171,7 @@ func (api *vultrProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, cur
} }
} }
return corrections, nil return corrections, actualChangeCount, nil
} }
// GetNameservers gets the Vultr nameservers for a domain // GetNameservers gets the Vultr nameservers for a domain