dnscontrol/providers/msdns/corrections.go
Tom Limoncelli 60470a3886
BUG: Some DNS zones are downloaded twice (#2120)
Signed-off-by: Amelia Aronsohn <squirrel@wearing.black>
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
Co-authored-by: Grégoire Henry <hnrgrgr@users.noreply.github.com>
Co-authored-by: Amelia Aronsohn <squirrel@wearing.black>
Co-authored-by: Kai Schwarz <kschwarz@hexonet.net>
Co-authored-by: Asif Nawaz <asif.nawaz@centralnic.com>
Co-authored-by: imlonghao <git@imlonghao.com>
Co-authored-by: Will Power <1619102+willpower232@users.noreply.github.com>
2023-04-14 15:22:23 -04:00

142 lines
4.3 KiB
Go

package msdns
import (
"fmt"
"github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
"github.com/StackExchange/dnscontrol/v3/pkg/txtutil"
)
// 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) {
// Normalize
models.PostProcessRecords(foundRecords)
txtutil.SplitSingleLongTxt(dc.Records) // Autosplit long TXT records
var corrections []*models.Correction
if !diff2.EnableDiff2 {
differ := diff.New(dc)
_, creates, dels, modifications, err := differ.IncrementalDiff(foundRecords)
if err != nil {
return nil, err
}
// Generate changes.
for _, del := range dels {
corrections = append(corrections, client.deleteRec(client.dnsserver, dc.Name, del))
}
for _, cre := range creates {
corrections = append(corrections, client.createRec(client.dnsserver, dc.Name, cre)...)
}
for _, m := range modifications {
corrections = append(corrections, client.modifyRec(client.dnsserver, dc.Name, m))
}
return corrections, nil
}
changes, err := diff2.ByRecord(foundRecords, dc, nil)
if err != nil {
return nil, err
}
var corr *models.Correction
for _, change := range changes {
msgsJoined := change.MsgsJoined
switch change.Type {
case diff2.REPORT:
corr = &models.Correction{Msg: msgsJoined}
case diff2.CREATE:
newrec := change.New[0]
corr = &models.Correction{
Msg: msgsJoined,
F: func() error {
return client.createOneRecord(client.dnsserver, dc.Name, newrec)
},
}
case diff2.CHANGE:
oldrec := change.Old[0]
newrec := change.New[0]
var f func(dnsserver string, zonename string, oldrec *models.RecordConfig, newrec *models.RecordConfig) error
if change.HintOnlyTTL && change.HintRecordSetLen1 {
// If we're only changing the TTL, and there is exactly one
// record of type oldrec.Type at this label, then we can do the
// TTL change in one command instead of deleting and re-creating
// the record.
f = client.modifyRecordTTL
} else {
f = client.modifyOneRecord
}
corr = &models.Correction{
Msg: msgsJoined,
F: func() error {
return f(client.dnsserver, dc.Name, oldrec, newrec)
},
}
case diff2.DELETE:
oldrec := change.Old[0]
corr = &models.Correction{
Msg: msgsJoined,
F: func() error {
return client.deleteOneRecord(client.dnsserver, dc.Name, oldrec)
},
}
default:
panic(fmt.Sprintf("unhandled change.Type %s", change.Type))
}
corrections = append(corrections, corr)
}
return corrections, nil
}
func (client *msdnsProvider) deleteOneRecord(dnsserver, zonename string, oldrec *models.RecordConfig) error {
return client.shell.RecordDelete(dnsserver, zonename, oldrec)
}
func (client *msdnsProvider) createOneRecord(dnsserver, zonename string, newrec *models.RecordConfig) error {
return client.shell.RecordCreate(dnsserver, zonename, newrec)
}
func (client *msdnsProvider) modifyOneRecord(dnsserver, zonename string, oldrec, newrec *models.RecordConfig) error {
return client.shell.RecordModify(dnsserver, zonename, oldrec, newrec)
}
func (client *msdnsProvider) modifyRecordTTL(dnsserver, zonename string, oldrec, newrec *models.RecordConfig) error {
return client.shell.RecordModifyTTL(dnsserver, zonename, oldrec, newrec.TTL)
}
func (client *msdnsProvider) deleteRec(dnsserver, domainname string, cor diff.Correlation) *models.Correction {
rec := cor.Existing
return &models.Correction{
Msg: cor.String(),
F: func() error {
return client.shell.RecordDelete(dnsserver, domainname, rec)
},
}
}
func (client *msdnsProvider) createRec(dnsserver, domainname string, cre diff.Correlation) []*models.Correction {
rec := cre.Desired
arr := []*models.Correction{{
Msg: cre.String(),
F: func() error {
return client.shell.RecordCreate(dnsserver, domainname, rec)
},
}}
return arr
}
func (client *msdnsProvider) modifyRec(dnsserver, domainname string, m diff.Correlation) *models.Correction {
old, rec := m.Existing, m.Desired
return &models.Correction{
Msg: m.String(),
F: func() error {
return client.shell.RecordModify(dnsserver, domainname, old, rec)
},
}
}