dnscontrol/providers/desec/convert.go
Tom Limoncelli 8dea9edc34
Re-engineer TXT records for simplicity and better compliance (#1063)
TXT records are now handled different.

1. The raw input from dnsconfig.js is passed all the way to the provider. The provider can determine if it can or can't handle such records (auditrecords.go) and processes them internally as such.
2. The CanUseTXTMulti capability is no longer needed.

* DSPs now register a table of functions
* Use audits for txt record variations
* unit tests pass. integration fails.
* fix deepcopy problem
* rename to AuditRecordSupport
* Reduce use of TXTMulti
* Remove CanUseTXTMulti
* fix Test Skip
* fix DO
* fix vultr
* fix NDC
* msdns fixes
* Fix powerdns and cloudflare
* HEDNS: Fix usage of target field to resolve TXT handling (#1067)
* Fix HEXONET

Co-authored-by: Robert Blenkinsopp <robert@blenkinsopp.net>
Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
2021-03-07 13:19:22 -05:00

85 lines
2.3 KiB
Go

package desec
// Convert the provider's native record description to models.RecordConfig.
import (
"fmt"
"strings"
"github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/printer"
)
// nativeToRecord takes a DNS record from deSEC and returns a native RecordConfig struct.
func nativeToRecords(n resourceRecord, origin string) (rcs []*models.RecordConfig) {
// deSEC returns all the values for a given label/rtype pair in each
// resourceRecord. In other words, if there are multiple A
// records for a label, all the IP addresses are listed in
// n.Records rather than having many resourceRecord's.
// We must split them out into individual records, one for each value.
for _, value := range n.Records {
rc := &models.RecordConfig{
TTL: n.TTL,
Original: n,
}
rc.SetLabel(n.Subname, origin)
switch rtype := n.Type; rtype {
case "TXT":
rc.SetTargetTXT(value)
default: // "A", "AAAA", "CAA", "NS", "CNAME", "MX", "PTR", "SRV"
if err := rc.PopulateFromString(rtype, value, origin); err != nil {
panic(fmt.Errorf("unparsable record received from deSEC: %w", err))
}
}
rcs = append(rcs, rc)
}
return rcs
}
func recordsToNative(rcs []*models.RecordConfig, origin string) []resourceRecord {
// Take a list of RecordConfig and return an equivalent list of resourceRecord.
// deSEC requires one resourceRecord for each label:key tuple, therefore we
// might collapse many RecordConfig into one resourceRecord.
var keys = map[models.RecordKey]*resourceRecord{}
var zrs []resourceRecord
for _, r := range rcs {
label := r.GetLabel()
if label == "@" {
label = ""
}
key := r.Key()
if zr, ok := keys[key]; !ok {
// Allocate a new ZoneRecord:
zr := resourceRecord{
Type: r.Type,
TTL: r.TTL,
Subname: label,
Records: []string{r.GetTargetCombined()},
}
if r.Type == "TXT" {
zr.Records = []string{strings.Join(r.TxtStrings, "")}
}
zrs = append(zrs, zr)
//keys[key] = &zr // This didn't work.
keys[key] = &zrs[len(zrs)-1] // This does work. I don't know why.
} else {
zr.Records = append(zr.Records, r.GetTargetCombined())
if r.TTL != zr.TTL {
printer.Warnf("All TTLs for a rrset (%v) must be the same. Using smaller of %v and %v.\n", key, r.TTL, zr.TTL)
if r.TTL < zr.TTL {
zr.TTL = r.TTL
}
}
}
}
return zrs
}