mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-02-23 15:12:57 +08:00
136 lines
3.7 KiB
Go
136 lines
3.7 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/StackExchange/dnscontrol/v4/pkg/fieldtypes"
|
|
"github.com/go-acme/lego/v4/log"
|
|
)
|
|
|
|
// RawRecordConfig stores the raw user-input from dnsconfig.js for a DNS Record
|
|
// (A, MX, SRV, etc). This is later processed to become a RecordConfig. NOTE:
|
|
// Only newer rtypes are processed this way. Eventually the legacy types will
|
|
// be converted and removed.
|
|
type RawRecordConfig struct {
|
|
Type string `json:"type"`
|
|
Args []string `json:"args,omitempty"`
|
|
Metadata []map[string]any `json:"metas,omitempty"`
|
|
TTL uint32 `json:"ttl,omitempty"`
|
|
SubDomain string `json:"subdomain,omitempty"`
|
|
|
|
// Override NO_PURGE and delete this record
|
|
EnsureAbsent bool `json:"ensure_absent,omitempty"`
|
|
}
|
|
|
|
// FromRaw converts the RawRecordConfig into a RecordConfig by calling the
|
|
// conversion function provided when the rtype was registered.
|
|
func FromRaw(rc *RecordConfig, origin string, typeName string, args []string, meta map[string]string) error {
|
|
|
|
rt, ok := rtypeDB[typeName]
|
|
if !ok {
|
|
return fmt.Errorf("unknown rtype %q", typeName)
|
|
}
|
|
|
|
return rt.FromRaw(rc, args, meta, origin)
|
|
}
|
|
|
|
// CheckAndFixImport checks the records for any that were created with a
|
|
// provider that has not yet been upgraded. In theory leaving providers in the
|
|
// legacy state should not cause any issues, but it is a good idea to fix them
|
|
// as soon as possible.
|
|
func CheckAndFixImport(recs []*RecordConfig, origin string) bool {
|
|
found := false
|
|
for _, rec := range recs {
|
|
//fmt.Printf("DEBUG: Found record %s %s %v\n", rec.Type, rec.Name, rec)
|
|
// Was this created wrong?
|
|
if IsTypeUpgraded(rec.Type) && rec.Fields == nil {
|
|
found = true
|
|
log.Warnf("LEGACY PROVIDER needs fixing! Created invalid record: %s %s %v\n", rec.Type, rec.Name, rec)
|
|
rec.ImportFromLegacy(origin)
|
|
}
|
|
}
|
|
return found
|
|
}
|
|
|
|
// ImportFromLegacy copies the legacy fields (MxPreference, SrvPort, etc.) to
|
|
// the .Fields structure. It is the reverse of Seal*().
|
|
func (rc *RecordConfig) ImportFromLegacy(origin string) error {
|
|
|
|
if IsTypeLegacy(rc.Type) {
|
|
// Nothing to convert!
|
|
return nil
|
|
}
|
|
|
|
switch rc.Type {
|
|
case "A":
|
|
ip, err := fieldtypes.ParseIPv4(rc.target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return rc.PopulateAFields(ip, nil, origin)
|
|
case "MX":
|
|
return rc.PopulateMXFields(rc.MxPreference, rc.target, nil, origin)
|
|
case "SRV":
|
|
return rc.PopulateSRVFields(rc.SrvPriority, rc.SrvWeight, rc.SrvPort, rc.target, nil, origin)
|
|
}
|
|
panic("Should not happen")
|
|
}
|
|
|
|
// TransformRawRecords converts the RawRecordConfigs from dnsconfig.js into RecordConfig.
|
|
func TransformRawRecords(domains []*DomainConfig) error {
|
|
|
|
for _, dc := range domains {
|
|
|
|
for _, rawRec := range dc.RawRecords {
|
|
|
|
if rawRec.TTL == 0 {
|
|
rawRec.TTL = dc.DefaultTTL
|
|
}
|
|
|
|
rec := &RecordConfig{
|
|
Type: rawRec.Type,
|
|
TTL: rawRec.TTL,
|
|
SubDomain: rawRec.SubDomain,
|
|
Metadata: map[string]string{},
|
|
}
|
|
|
|
// Copy the metadata (convert values to string)
|
|
for _, m := range rawRec.Metadata {
|
|
for mk, mv := range m {
|
|
if v, ok := mv.(string); ok {
|
|
rec.Metadata[mk] = v // Already a string
|
|
} else {
|
|
rec.Metadata[mk] = fmt.Sprintf("%v", mv)
|
|
}
|
|
}
|
|
}
|
|
|
|
rt, ok := rtypeDB[rawRec.Type]
|
|
if !ok {
|
|
return fmt.Errorf("unknown rtype %q", rawRec.Type)
|
|
}
|
|
|
|
err := rt.FromRaw(rec, rawRec.Args, rec.Metadata, dc.Name)
|
|
if err != nil {
|
|
return fmt.Errorf("%s (%q, dom=%q) record error: %w",
|
|
rawRec.Type,
|
|
rec.Name,
|
|
dc.Name,
|
|
err)
|
|
}
|
|
|
|
// Free memeory:
|
|
clear(rawRec.Args)
|
|
rawRec.Args = nil
|
|
|
|
if rawRec.EnsureAbsent {
|
|
dc.EnsureAbsent = append(dc.EnsureAbsent, rec)
|
|
} else {
|
|
dc.Records = append(dc.Records, rec)
|
|
}
|
|
}
|
|
dc.RawRecords = nil
|
|
}
|
|
|
|
return nil
|
|
}
|