mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
MAINT: Restructuring of the PowerDNS DSP based on the layout of CSCGlobal (#1549)
* Restructure PowerDNS DSP based on layout for CSCGlobal Signed-off-by: Jan-Philipp Benecke <jan-philipp@bnck.me> * Rename api to dsp and make initializer function private Signed-off-by: Jan-Philipp Benecke <jan-philipp@bnck.me> Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
committed by
GitHub
parent
959f721c04
commit
e5de7b5359
146
providers/powerdns/dns.go
Normal file
146
providers/powerdns/dns.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package powerdns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
"github.com/StackExchange/dnscontrol/v3/pkg/diff"
|
||||
"github.com/mittwald/go-powerdns/apis/zones"
|
||||
"github.com/mittwald/go-powerdns/pdnshttp"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetNameservers returns the nameservers for a domain.
|
||||
func (dsp *powerdnsProvider) GetNameservers(string) ([]*models.Nameserver, error) {
|
||||
var r []string
|
||||
for _, j := range dsp.nameservers {
|
||||
r = append(r, j.Name)
|
||||
}
|
||||
return models.ToNameservers(r)
|
||||
}
|
||||
|
||||
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
|
||||
func (dsp *powerdnsProvider) GetZoneRecords(domain string) (models.Records, error) {
|
||||
zone, err := dsp.client.Zones().GetZone(context.Background(), dsp.ServerName, domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curRecords := models.Records{}
|
||||
// loop over grouped records by type, called RRSet
|
||||
for _, rrset := range zone.ResourceRecordSets {
|
||||
if rrset.Type == "SOA" {
|
||||
continue
|
||||
}
|
||||
// loop over single records of this group and create records
|
||||
for _, pdnsRecord := range rrset.Records {
|
||||
r, err := toRecordConfig(domain, pdnsRecord, rrset.TTL, rrset.Name, rrset.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
curRecords = append(curRecords, r)
|
||||
}
|
||||
}
|
||||
|
||||
return curRecords, nil
|
||||
}
|
||||
|
||||
// GetDomainCorrections returns a list of corrections to update a domain.
|
||||
func (dsp *powerdnsProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
var corrections []*models.Correction
|
||||
|
||||
// get current zone records
|
||||
curRecords, err := dsp.GetZoneRecords(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// post-process records
|
||||
if err := dc.Punycode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
models.PostProcessRecords(curRecords)
|
||||
|
||||
// create record diff by group
|
||||
keysToUpdate, err := (diff.New(dc)).ChangedGroups(curRecords)
|
||||
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 := 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
|
||||
corrections = append(corrections, dCorrections...)
|
||||
corrections = append(corrections, cuCorrections...)
|
||||
|
||||
// DNSSec corrections
|
||||
dnssecCorrections, err := dsp.getDNSSECCorrections(dc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
corrections = append(corrections, dnssecCorrections...)
|
||||
|
||||
return corrections, nil
|
||||
}
|
||||
|
||||
// EnsureDomainExists adds a domain to the DNS service if it does not exist
|
||||
func (dsp *powerdnsProvider) EnsureDomainExists(domain string) error {
|
||||
if _, err := dsp.client.Zones().GetZone(context.Background(), dsp.ServerName, domain+"."); err != nil {
|
||||
if e, ok := err.(pdnshttp.ErrUnexpectedStatus); ok {
|
||||
if e.StatusCode != http.StatusNotFound {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else { // domain seems to be there
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := dsp.client.Zones().CreateZone(context.Background(), dsp.ServerName, zones.Zone{
|
||||
Name: domain + ".",
|
||||
Type: zones.ZoneTypeZone,
|
||||
DNSSec: dsp.DNSSecOnCreate,
|
||||
Nameservers: dsp.DefaultNS,
|
||||
})
|
||||
return err
|
||||
}
|
Reference in New Issue
Block a user