dnscontrol/providers/bunnydns/convert.go
2024-01-06 09:19:40 -05:00

161 lines
3.7 KiB
Go

package bunnydns
import (
"fmt"
"github.com/StackExchange/dnscontrol/v4/models"
"github.com/miekg/dns/dnsutil"
"golang.org/x/exp/slices"
"strings"
)
var fqdnTypes = []recordType{recordTypeCNAME, recordTypeMX, recordTypeNS, recordTypePTR, recordTypeSRV}
func fromRecordConfig(rc *models.RecordConfig) (*record, error) {
r := record{
Type: recordTypeFromString(rc.Type),
Name: rc.GetLabel(),
Value: rc.GetTargetField(),
TTL: rc.TTL,
}
// While Bunny DNS does not use trailing dots, it still accepts and even preserves them for certain record types.
// To avoid confusion, any trailing dots are removed from the record value.
if slices.Contains(fqdnTypes, r.Type) && strings.HasSuffix(r.Value, ".") {
r.Value = strings.TrimSuffix(r.Value, ".")
}
switch r.Type {
case recordTypeNS:
if r.Name == "" {
r.TTL = 0
}
case recordTypeSRV:
r.Priority = rc.SrvPriority
r.Weight = rc.SrvWeight
r.Port = rc.SrvPort
case recordTypeCAA:
r.Flags = rc.CaaFlag
r.Tag = rc.CaaTag
case recordTypeMX:
r.Priority = rc.MxPreference
}
return &r, nil
}
func toRecordConfig(domain string, r *record) (*models.RecordConfig, error) {
rc := models.RecordConfig{
Type: recordTypeToString(r.Type),
TTL: r.TTL,
Original: r,
}
rc.SetLabel(r.Name, domain)
// Bunny DNS always operates with fully-qualified names and does not use any trailing dots.
// If a record already contains a trailing dot, which the provider UI also accepts, the record value is left as-is.
recordValue := r.Value
if slices.Contains(fqdnTypes, r.Type) && !strings.HasSuffix(r.Value, ".") {
recordValue = dnsutil.AddOrigin(r.Value+".", domain)
}
var err error
switch rc.Type {
case "CAA":
err = rc.SetTargetCAA(r.Flags, r.Tag, recordValue)
case "MX":
err = rc.SetTargetMX(r.Priority, recordValue)
case "SRV":
err = rc.SetTargetSRV(r.Priority, r.Weight, r.Port, recordValue)
default:
err = rc.PopulateFromStringFunc(rc.Type, recordValue, domain, nil)
}
if err != nil {
return nil, err
}
return &rc, nil
}
type recordType int
const (
recordTypeA recordType = 0
recordTypeAAAA recordType = 1
recordTypeCNAME recordType = 2
recordTypeTXT recordType = 3
recordTypeMX recordType = 4
recordTypeRedirect recordType = 5
recordTypeFlatten recordType = 6
recordTypePullZone recordType = 7
recordTypeSRV recordType = 8
recordTypeCAA recordType = 9
recordTypePTR recordType = 10
recordTypeScript recordType = 11
recordTypeNS recordType = 12
)
func recordTypeFromString(t string) recordType {
switch t {
case "A":
return recordTypeA
case "AAAA":
return recordTypeAAAA
case "CNAME":
return recordTypeCNAME
case "TXT":
return recordTypeTXT
case "MX":
return recordTypeMX
case "REDIRECT":
return recordTypeRedirect
case "FLATTEN":
return recordTypeFlatten
case "PULL_ZONE":
return recordTypePullZone
case "SRV":
return recordTypeSRV
case "CAA":
return recordTypeCAA
case "PTR":
return recordTypePTR
case "SCRIPT":
return recordTypeScript
case "NS":
return recordTypeNS
default:
panic(fmt.Errorf("BUNNY_DNS: rtype %v unimplemented", t))
}
}
func recordTypeToString(t recordType) string {
switch t {
case recordTypeA:
return "A"
case recordTypeAAAA:
return "AAAA"
case recordTypeCNAME:
return "CNAME"
case recordTypeTXT:
return "TXT"
case recordTypeMX:
return "MX"
case recordTypeRedirect:
return "REDIRECT"
case recordTypeFlatten:
return "FLATTEN"
case recordTypePullZone:
return "PULL_ZONE"
case recordTypeSRV:
return "SRV"
case recordTypeCAA:
return "CAA"
case recordTypePTR:
return "PTR"
case recordTypeScript:
return "SCRIPT"
case recordTypeNS:
return "NS"
default:
panic(fmt.Errorf("BUNNY_DNS: native rtype %v unimplemented", t))
}
}