mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-12-09 21:55:57 +08:00
wip!
This commit is contained in:
parent
633c9ecacc
commit
4b7da682a4
6 changed files with 197 additions and 108 deletions
|
|
@ -107,9 +107,13 @@ type RecordConfig struct {
|
|||
FieldsAsRaw []string // Fields as received from the dnsconfig.js file.
|
||||
FieldsAsUnicode []string // fields with IDN fields converted to Unicode.
|
||||
|
||||
// Legacy fields we hope to remove someday
|
||||
|
||||
SubDomain string `json:"subdomain,omitempty"`
|
||||
|
||||
// Cloudflare-specific fields:
|
||||
// When these are used, .target is set to a human-readable version (only to be used for display purposes).
|
||||
//CloudflareRedirect *CloudflareSingleRedirectConfig `json:"cloudflareapi_redirect,omitempty"`
|
||||
CloudflareRedirect *CloudflareSingleRedirectConfig `json:"cloudflareapi_redirect,omitempty"`
|
||||
|
||||
Metadata map[string]string `json:"meta,omitempty"` // Metadata added to record via dnsconfig.js
|
||||
FilePos string `json:"filepos"` // filename:line:char source
|
||||
|
|
@ -166,7 +170,14 @@ type RecordConfig struct {
|
|||
UnknownTypeName string `json:"unknown_type_name,omitempty"`
|
||||
}
|
||||
|
||||
// func NewRecordConfig(argsRaw):
|
||||
func NewRecordConfig(rtype string, ttl uint32, argsRaw []string) *RecordConfig {
|
||||
rc := &RecordConfig{
|
||||
Type: rtype,
|
||||
TTL: ttl,
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
// .Type = type
|
||||
// .TTL = ttl
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func (rc *RecordConfig) SetTargetCAA(flag uint8, tag string, target string) erro
|
|||
// Per: https://www.iana.org/assignments/pkix-parameters/pkix-parameters.xhtml#caa-properties excluding reserved tags
|
||||
allowedTags := []string{"issue", "issuewild", "iodef", "contactemail", "contactphone", "issuemail", "issuevmc"}
|
||||
if !slices.Contains(allowedTags, tag) {
|
||||
return fmt.Errorf("CAA tag (%v) is not one of the valid types.", tag)
|
||||
return fmt.Errorf("CAA tag (%v) is not one of the valid types", tag)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -333,16 +333,16 @@ var AKAMAICDN = recordBuilder('AKAMAICDN');
|
|||
|
||||
// AKAMAITLC(name, answer_type, target, recordModifiers...)
|
||||
var AKAMAITLC = recordBuilder('AKAMAITLC', {
|
||||
args: [
|
||||
['name', _.isString],
|
||||
['answer_type', function(value) { return _.isString(value) && ['DUAL', 'A', 'AAAA'].indexOf(value) !== -1; }],
|
||||
['target', _.isString],
|
||||
],
|
||||
transform: function (record, args, modifier) {
|
||||
record.name = args.name;
|
||||
record.answer_type = args.answer_type;
|
||||
record.target = args.target;
|
||||
},
|
||||
args: [
|
||||
['name', _.isString],
|
||||
['answer_type', function (value) { return _.isString(value) && ['DUAL', 'A', 'AAAA'].indexOf(value) !== -1; }],
|
||||
['target', _.isString],
|
||||
],
|
||||
transform: function (record, args, modifier) {
|
||||
record.name = args.name;
|
||||
record.answer_type = args.answer_type;
|
||||
record.target = args.target;
|
||||
},
|
||||
});
|
||||
|
||||
// ALIAS(name,target, recordModifiers...)
|
||||
|
|
@ -683,20 +683,20 @@ var TXT = recordBuilder('TXT', {
|
|||
});
|
||||
|
||||
var LUA = recordBuilder('LUA', {
|
||||
args: [
|
||||
['name', _.isString],
|
||||
['rtype', _.isString],
|
||||
['target', isStringOrArray],
|
||||
],
|
||||
transform: function (record, args, modifiers) {
|
||||
record.name = args.name;
|
||||
record.luartype = args.rtype.toUpperCase();
|
||||
if (_.isString(args.target)) {
|
||||
record.target = args.target;
|
||||
} else {
|
||||
record.target = args.target.join('');
|
||||
}
|
||||
},
|
||||
args: [
|
||||
['name', _.isString],
|
||||
['rtype', _.isString],
|
||||
['target', isStringOrArray],
|
||||
],
|
||||
transform: function (record, args, modifiers) {
|
||||
record.name = args.name;
|
||||
record.luartype = args.rtype.toUpperCase();
|
||||
if (_.isString(args.target)) {
|
||||
record.target = args.target;
|
||||
} else {
|
||||
record.target = args.target.join('');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Parses coordinates of the form 41°24'12.2"N 2°10'26.5"E
|
||||
|
|
@ -858,15 +858,15 @@ function locStringBuilder(record, args) {
|
|||
(args.alt < -100000
|
||||
? -100000
|
||||
: args.alt > 42849672.95
|
||||
? 42849672.95
|
||||
: args.alt.toString()) + 'm';
|
||||
? 42849672.95
|
||||
: args.alt.toString()) + 'm';
|
||||
precisionbuffer +=
|
||||
' ' +
|
||||
(args.siz > 90000000
|
||||
? 90000000
|
||||
: args.siz < 0
|
||||
? 0
|
||||
: args.siz.toString()) +
|
||||
? 0
|
||||
: args.siz.toString()) +
|
||||
'm';
|
||||
precisionbuffer +=
|
||||
' ' +
|
||||
|
|
@ -906,8 +906,8 @@ function locDMSBuilder(record, args) {
|
|||
record.localtitude > 4294967295
|
||||
? 4294967295
|
||||
: record.localtitude < 0
|
||||
? 0
|
||||
: record.localtitude;
|
||||
? 0
|
||||
: record.localtitude;
|
||||
// Size
|
||||
record.locsize = getENotationInt(args.siz);
|
||||
// Horizontal Precision
|
||||
|
|
@ -1785,7 +1785,7 @@ function CAA_BUILDER(value) {
|
|||
throw 'CAA_BUILDER requires at least one entry at issue, issuewild, issuevmc or issuemail';
|
||||
}
|
||||
|
||||
var CAA_TTL = function () {};
|
||||
var CAA_TTL = function () { };
|
||||
if (value.ttl) {
|
||||
CAA_TTL = TTL(value.ttl);
|
||||
}
|
||||
|
|
@ -1802,7 +1802,7 @@ function CAA_BUILDER(value) {
|
|||
}
|
||||
|
||||
if (value.issue) {
|
||||
var flag = function () {};
|
||||
var flag = function () { };
|
||||
if (value.issue_critical) {
|
||||
flag = CAA_CRITICAL;
|
||||
}
|
||||
|
|
@ -1811,7 +1811,7 @@ function CAA_BUILDER(value) {
|
|||
}
|
||||
|
||||
if (value.issuewild) {
|
||||
var flag = function () {};
|
||||
var flag = function () { };
|
||||
if (value.issuewild_critical) {
|
||||
flag = CAA_CRITICAL;
|
||||
}
|
||||
|
|
@ -1822,7 +1822,7 @@ function CAA_BUILDER(value) {
|
|||
}
|
||||
|
||||
if (value.issuevmc) {
|
||||
var flag = function () {};
|
||||
var flag = function () { };
|
||||
if (value.issuevmc_critical) {
|
||||
flag = CAA_CRITICAL;
|
||||
}
|
||||
|
|
@ -1833,7 +1833,7 @@ function CAA_BUILDER(value) {
|
|||
}
|
||||
|
||||
if (value.issuemail) {
|
||||
var flag = function () {};
|
||||
var flag = function () { };
|
||||
if (value.issuemail_critical) {
|
||||
flag = CAA_CRITICAL;
|
||||
}
|
||||
|
|
@ -2052,7 +2052,7 @@ function DKIM_BUILDER(value) {
|
|||
}
|
||||
|
||||
// Handle TTL
|
||||
var DKIM_TTL = value.ttl ? TTL(value.ttl) : function () {};
|
||||
var DKIM_TTL = value.ttl ? TTL(value.ttl) : function () { };
|
||||
|
||||
return TXT(fullLabel, record.join('; '), DKIM_TTL);
|
||||
}
|
||||
|
|
@ -2284,20 +2284,20 @@ function M365_BUILDER(name, value) {
|
|||
CNAME(
|
||||
'selector1._domainkey',
|
||||
'selector1-' +
|
||||
value.domainGUID +
|
||||
'._domainkey.' +
|
||||
value.initialDomain +
|
||||
'.'
|
||||
value.domainGUID +
|
||||
'._domainkey.' +
|
||||
value.initialDomain +
|
||||
'.'
|
||||
)
|
||||
);
|
||||
r.push(
|
||||
CNAME(
|
||||
'selector2._domainkey',
|
||||
'selector2-' +
|
||||
value.domainGUID +
|
||||
'._domainkey.' +
|
||||
value.initialDomain +
|
||||
'.'
|
||||
value.domainGUID +
|
||||
'._domainkey.' +
|
||||
value.initialDomain +
|
||||
'.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -2477,3 +2477,4 @@ function rawrecordBuilder(type) {
|
|||
|
||||
// CLOUDFLAREAPI:
|
||||
var CF_SINGLE_REDIRECT = rawrecordBuilder('CLOUDFLAREAPI_SINGLE_REDIRECT');
|
||||
var RP = rawrecordBuilder('RP');
|
||||
|
|
|
|||
|
|
@ -1,21 +1,43 @@
|
|||
package rtypecontrol
|
||||
|
||||
import "github.com/StackExchange/dnscontrol/v4/providers"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v4/models"
|
||||
"github.com/StackExchange/dnscontrol/v4/providers"
|
||||
)
|
||||
|
||||
// backwards compatibility:
|
||||
var validTypes = map[string]struct{}{}
|
||||
|
||||
func Register(t string) {
|
||||
// Does this already exist?
|
||||
if _, ok := validTypes[t]; ok {
|
||||
panic("rtype %q already registered. Can't register it a second time!")
|
||||
}
|
||||
type RType interface {
|
||||
// Returns the name of the rtype ("A", "MX", etc.)
|
||||
Name() string
|
||||
|
||||
validTypes[t] = struct{}{}
|
||||
// RecordConfig factory. Updates a RecordConfig's fields based on args.
|
||||
FromArgs(*models.RecordConfig, args []any) (*models.RecordConfig, error) //
|
||||
|
||||
providers.RegisterCustomRecordType(t, "", "")
|
||||
// Returns a string representation of the record in RFC1038 format.
|
||||
// AsRFC1038String([]string) (string, error)
|
||||
}
|
||||
|
||||
func IsValid(t string) bool {
|
||||
_, ok := validTypes[t]
|
||||
// Map of registered rtypes.
|
||||
var Iface map[string]RType = map[string]RType{}
|
||||
|
||||
func Register(typeName string, t RType) {
|
||||
name := t.Name()
|
||||
if _, ok := Iface[name]; ok {
|
||||
panic(fmt.Sprintf("rtype %q already registered. Can't register it a second time!", name))
|
||||
}
|
||||
// Store the interface
|
||||
Iface[name] = t
|
||||
|
||||
// For compatibility with legacy systems:
|
||||
providers.RegisterCustomRecordType(name, "", "")
|
||||
|
||||
}
|
||||
|
||||
func IsValid(name string) bool {
|
||||
_, ok := Iface[name]
|
||||
return ok
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
package rtypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v4/models"
|
||||
"github.com/StackExchange/dnscontrol/v4/providers/cloudflare/rtypes/cfsingleredirect"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/rtypecontrol"
|
||||
)
|
||||
|
||||
func PostProcess(domains []*models.DomainConfig) error {
|
||||
|
|
@ -12,37 +10,54 @@ func PostProcess(domains []*models.DomainConfig) error {
|
|||
|
||||
for _, dc := range domains {
|
||||
for _, rawRec := range dc.RawRecords {
|
||||
|
||||
// Create as much of the RecordConfig as we can now. Allow New() to fill in the reset.
|
||||
rec := &models.RecordConfig{
|
||||
Type: rawRec.Type,
|
||||
TTL: rawRec.TTL,
|
||||
Name: rawRec.Args[0].(string),
|
||||
Metadata: map[string]string{},
|
||||
Metadata: stringifyMetas(rawRec.Metas),
|
||||
}
|
||||
//rec.Name, rec.NameRaw, rec.NameUnicode := normalizeName(rawRec.Args[0].(string), dc.Name, dc.SubDomain)
|
||||
//rec.NameFQDN, rec.NameFQDNRaw, rec.NameFQDNUnicode := normalizeNameFQDN(rawRec.Args[0].(string), dc.Name, dc.SubDomain)
|
||||
// Name:
|
||||
// * Convert to lowercase.
|
||||
// * Convert to IDN and UNI.
|
||||
//
|
||||
// IDN: name + subdomain + domain
|
||||
|
||||
// Copy the metadata (convert everything to string)
|
||||
for _, m := range rawRec.Metas {
|
||||
for mk, mv := range m {
|
||||
if v, ok := mv.(string); ok {
|
||||
rec.Metadata[mk] = v // Already a string. No new malloc.
|
||||
} else {
|
||||
rec.Metadata[mk] = fmt.Sprintf("%v", mv)
|
||||
}
|
||||
}
|
||||
}
|
||||
rtypecontrol.Iface[rawRec.Type].FromArgs(rec, rawRec.Args)
|
||||
|
||||
// Call the proper initialize function.
|
||||
// TODO(tlim): Good candidate for an interface or a lookup table.
|
||||
switch rawRec.Type {
|
||||
case "CLOUDFLAREAPI_SINGLE_REDIRECT":
|
||||
err = cfsingleredirect.FromRaw(rec, rawRec.Args)
|
||||
rec.SetLabel("@", dc.Name)
|
||||
// rec := &models.RecordConfig{
|
||||
// Type: rawRec.Type,
|
||||
// TTL: rawRec.TTL,
|
||||
// Name: rawRec.Args[0].(string),
|
||||
// Metadata: map[string]string{},
|
||||
// }
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unknown rawrec type=%q", rawRec.Type)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s (%q, %q) record error: %w", rawRec.Type, rec.Name, dc.Name, err)
|
||||
}
|
||||
// // Copy the metadata (convert everything to string)
|
||||
// for _, m := range rawRec.Metas {
|
||||
// for mk, mv := range m {
|
||||
// if v, ok := mv.(string); ok {
|
||||
// rec.Metadata[mk] = v // Already a string. No new malloc.
|
||||
// } else {
|
||||
// rec.Metadata[mk] = fmt.Sprintf("%v", mv)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Call the proper initialize function.
|
||||
// // TODO(tlim): Good candidate for an interface or a lookup table.
|
||||
// switch rawRec.Type {
|
||||
// case "CLOUDFLAREAPI_SINGLE_REDIRECT":
|
||||
// err = cfsingleredirect.FromRaw(rec, rawRec.Args)
|
||||
// rec.SetLabel("@", dc.Name)
|
||||
|
||||
// default:
|
||||
// err = fmt.Errorf("unknown rawrec type=%q", rawRec.Type)
|
||||
// }
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("%s (%q, %q) record error: %w", rawRec.Type, rec.Name, dc.Name, err)
|
||||
// }
|
||||
|
||||
// Free memeory:
|
||||
clear(rawRec.Args)
|
||||
|
|
|
|||
|
|
@ -1,37 +1,77 @@
|
|||
package cfsingleredirect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v4/models"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/rtypecontrol"
|
||||
)
|
||||
|
||||
// SINGLEREDIRECT is the string name for this rType.
|
||||
const SINGLEREDIRECT = "CLOUDFLAREAPI_SINGLE_REDIRECT"
|
||||
// "github.com/StackExchange/dnscontrol/v4/models"
|
||||
// "github.com/StackExchange/dnscontrol/v4/pkg/rtypecontrol"
|
||||
|
||||
func init() {
|
||||
rtypecontrol.Register(SINGLEREDIRECT)
|
||||
rtypecontrol.Register(SingleRedirect{})
|
||||
}
|
||||
|
||||
// FromRaw convert RecordConfig using data from a RawRecordConfig's parameters.
|
||||
func FromRaw(rc *models.RecordConfig, items []any) error {
|
||||
// Validate types.
|
||||
if err := rtypecontrol.PaveArgs(items, "siss"); err != nil {
|
||||
return err
|
||||
}
|
||||
type SingleRedirect struct{}
|
||||
|
||||
// Unpack the args:
|
||||
var name, when, then string
|
||||
var code uint16
|
||||
|
||||
name = items[0].(string)
|
||||
code = items[1].(uint16)
|
||||
if code != 301 && code != 302 && code != 303 && code != 307 && code != 308 {
|
||||
return fmt.Errorf("%s: code (%03d) is not 301,302,303,307,308", rc.FilePos, code)
|
||||
}
|
||||
when = items[2].(string)
|
||||
then = items[3].(string)
|
||||
|
||||
return makeSingleRedirectFromRawRec(rc, code, name, when, then)
|
||||
func (handle *SingleRedirect) Name() string {
|
||||
return "CLOUDFLAREAPI_SINGLE_REDIRECT"
|
||||
}
|
||||
|
||||
// func MakeSingleRedirect() SingleRedirect { return SingleRedirect{} }
|
||||
func (handle *SingleRedirect) FromArgs([]any) (*models.RecordConfig, error) {
|
||||
rec := &models.RecordConfig{
|
||||
Type: handle.Name(),
|
||||
TTL: ttl,
|
||||
|
||||
//FilePos = FixFilePos(handle.FilePos)
|
||||
}
|
||||
return rec, nil
|
||||
}
|
||||
// // Validate types.
|
||||
// if err := rtypecontrol.PaveArgs(items, "siss"); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // Unpack the args:
|
||||
// var name, when, then string
|
||||
// var code uint16
|
||||
|
||||
// name = items[0].(string)
|
||||
// code = items[1].(uint16)
|
||||
// if code != 301 && code != 302 && code != 303 && code != 307 && code != 308 {
|
||||
// return fmt.Errorf("%s: code (%03d) is not 301,302,303,307,308", rc.FilePos, code)
|
||||
// }
|
||||
// when = items[2].(string)
|
||||
// then = items[3].(string)
|
||||
|
||||
// return makeSingleRedirectFromRawRec(rc, code, name, when, then)
|
||||
return &models.RecordConfig{}, nil
|
||||
}
|
||||
|
||||
//func (handle *SingleRedirect) IDNFields(argsRaw) (argsIDN, argsUnicode, error) {}
|
||||
//func (handle *SingleRedirect) AsRFC1038String(*models.RecordConfig) string {}
|
||||
//func (handle *SingleRedirect) CopyToLegacyFields(*models.RecordConfig) {}
|
||||
//func (handle *SingleRedirect) CopyFromLegacyFields(*models.RecordConfig) {}
|
||||
|
||||
// // FromRaw convert RecordConfig using data from a RawRecordConfig's parameters.
|
||||
// func FromRaw(rc *models.RecordConfig, items []any) error {
|
||||
// // Validate types.
|
||||
// if err := rtypecontrol.PaveArgs(items, "siss"); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // Unpack the args:
|
||||
// var name, when, then string
|
||||
// var code uint16
|
||||
|
||||
// name = items[0].(string)
|
||||
// code = items[1].(uint16)
|
||||
// if code != 301 && code != 302 && code != 303 && code != 307 && code != 308 {
|
||||
// return fmt.Errorf("%s: code (%03d) is not 301,302,303,307,308", rc.FilePos, code)
|
||||
// }
|
||||
// when = items[2].(string)
|
||||
// then = items[3].(string)
|
||||
|
||||
// return makeSingleRedirectFromRawRec(rc, code, name, when, then)
|
||||
// }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue