dnscontrol/providers/powerdns/diff.go
Jan-Philipp Benecke 302a74b935
PowerDNS: Implement diff2 differ and some cleanup (#2194)
Signed-off-by: Jan-Philipp Benecke <jan-philipp@bnck.me>
2023-03-17 10:22:10 -04:00

129 lines
3.8 KiB
Go

package powerdns
import (
"context"
"fmt"
"github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
"github.com/StackExchange/dnscontrol/v3/pkg/diff2"
"github.com/mittwald/go-powerdns/apis/zones"
"strings"
)
func (dsp *powerdnsProvider) getDiff1DomainCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) {
// create record diff by group
keysToUpdate, err := (diff.New(dc)).ChangedGroups(existing)
if err != nil {
return nil, err
}
desiredRecords := dc.Records.GroupedByKey()
var cuCorrections []*models.Correction
var dCorrections []*models.Correction
// add create/update and delete corrections separately
for label, msgs := range keysToUpdate {
labelName := canonical(label.NameFQDN)
labelType := label.Type
msgJoined := strings.Join(msgs, "\n ")
if _, ok := desiredRecords[label]; !ok {
// no record found so delete it
dCorrections = append(dCorrections, &models.Correction{
Msg: msgJoined,
F: func() error {
return dsp.client.Zones().RemoveRecordSetFromZone(context.Background(), dsp.ServerName, dc.Name, labelName, labelType)
},
})
} else {
// record found so create or update it
ttl := desiredRecords[label][0].TTL
var records []zones.Record
for _, recordContent := range desiredRecords[label] {
records = append(records, zones.Record{
Content: recordContent.GetTargetCombined(),
})
}
cuCorrections = append(cuCorrections, &models.Correction{
Msg: msgJoined,
F: func() error {
return dsp.client.Zones().AddRecordSetToZone(context.Background(), dsp.ServerName, dc.Name, zones.ResourceRecordSet{
Name: labelName,
Type: labelType,
TTL: int(ttl),
Records: records,
ChangeType: zones.ChangeTypeReplace,
})
},
})
}
}
// append corrections in the right order
// delete corrections must be run first to avoid correlations with existing RR
var corrections []*models.Correction
corrections = append(corrections, dCorrections...)
corrections = append(corrections, cuCorrections...)
return corrections, nil
}
func (dsp *powerdnsProvider) getDiff2DomainCorrections(dc *models.DomainConfig, existing models.Records) ([]*models.Correction, error) {
changes, err := diff2.ByRecordSet(existing, dc, nil)
if err != nil {
return nil, err
}
var corrections []*models.Correction
for _, change := range changes {
labelName := canonical(change.Key.NameFQDN)
labelType := change.Key.Type
switch change.Type {
case diff2.REPORT:
corrections = append(corrections, &models.Correction{Msg: change.MsgsJoined})
case diff2.CREATE, diff2.CHANGE:
labelTTL := int(change.New[0].TTL)
records := buildRecordList(change)
corrections = append(corrections, &models.Correction{
Msg: change.MsgsJoined,
F: func() error {
return dsp.client.Zones().AddRecordSetToZone(context.Background(), dsp.ServerName, dc.Name, zones.ResourceRecordSet{
Name: labelName,
Type: labelType,
TTL: labelTTL,
Records: records,
ChangeType: zones.ChangeTypeReplace,
})
},
})
case diff2.DELETE:
corrections = append(corrections, &models.Correction{
Msg: change.MsgsJoined,
F: func() error {
return dsp.client.Zones().RemoveRecordSetFromZone(context.Background(), dsp.ServerName, dc.Name, labelName, labelType)
},
})
default:
panic(fmt.Sprintf("unhandled change.Type %s", change.Type))
}
}
return corrections, nil
}
// buildRecordList returns a list of records for the PowerDNS resource record set from a change
func buildRecordList(change diff2.Change) (records []zones.Record) {
for _, recordContent := range change.New {
records = append(records, zones.Record{
Content: recordContent.GetTargetCombined(),
})
}
return
}
func canonical(fqdn string) string {
return fqdn + "."
}