mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-04-18 02:00:32 +08:00
Refactor in preparation to unexport RecordConfig.{Name,NameFQDN,Target} (#337)
* Preparing for the unexport of Name/NameFQDN/Target * Cleanups
This commit is contained in:
parent
cd58d26545
commit
a7eba97ada
37 changed files with 298 additions and 270 deletions
integrationTest
models
pkg
providers
activedir
bind
cloudflare
diff
digitalocean
dnsimple
gandi
gcloud
linode
namecheap
namedotcom
octodns/octoyaml
ovh
softlayer
vultr
|
@ -107,9 +107,11 @@ func runTests(t *testing.T, prv providers.DNSServiceProvider, domainName string,
|
|||
dom, _ := dc.Copy()
|
||||
for _, r := range tst.Records {
|
||||
rc := models.RecordConfig(*r)
|
||||
rc.NameFQDN = dnsutil.AddOrigin(rc.Name, domainName)
|
||||
if strings.Contains(rc.Target, "**current-domain**") {
|
||||
rc.Target = strings.Replace(rc.Target, "**current-domain**", domainName, 1) + "."
|
||||
if strings.Contains(rc.GetTargetField(), "**current-domain**") {
|
||||
rc.SetTarget(strings.Replace(rc.GetTargetField(), "**current-domain**", domainName, 1) + ".")
|
||||
}
|
||||
if strings.Contains(rc.GetLabelFQDN(), "**current-domain**") {
|
||||
rc.SetLabelFromFQDN(strings.Replace(rc.GetLabelFQDN(), "**current-domain**", domainName, 1), domainName)
|
||||
}
|
||||
dom.Records = append(dom.Records, &rc)
|
||||
}
|
||||
|
@ -205,6 +207,19 @@ type TestCase struct {
|
|||
|
||||
type rec models.RecordConfig
|
||||
|
||||
func (r *rec) GetLabel() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r *rec) SetLabel(label, domain string) {
|
||||
r.Name = label
|
||||
r.NameFQDN = dnsutil.AddOrigin(label, "**current-domain**")
|
||||
}
|
||||
|
||||
func (r *rec) SetTarget(target string) {
|
||||
r.Target = target
|
||||
}
|
||||
|
||||
func a(name, target string) *rec {
|
||||
return makeRec(name, target, "A")
|
||||
}
|
||||
|
@ -273,24 +288,25 @@ func tlsa(name string, usage, selector, matchingtype uint8, target string) *rec
|
|||
r.TlsaUsage = usage
|
||||
r.TlsaSelector = selector
|
||||
r.TlsaMatchingType = matchingtype
|
||||
r.Target = target
|
||||
return r
|
||||
}
|
||||
|
||||
func ignore(name string) *rec {
|
||||
return &rec{
|
||||
Name: name,
|
||||
r := &rec{
|
||||
Type: "IGNORE",
|
||||
}
|
||||
r.SetLabel(name, "**current-domain**")
|
||||
return r
|
||||
}
|
||||
|
||||
func makeRec(name, target, typ string) *rec {
|
||||
return &rec{
|
||||
Name: name,
|
||||
Type: typ,
|
||||
Target: target,
|
||||
TTL: 300,
|
||||
r := &rec{
|
||||
Type: typ,
|
||||
TTL: 300,
|
||||
}
|
||||
r.SetLabel(name, "**current-domain**")
|
||||
r.SetTarget(target)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *rec) ttl(t uint32) *rec {
|
||||
|
@ -303,7 +319,7 @@ func tc(desc string, recs ...*rec) *TestCase {
|
|||
var ignored []string
|
||||
for _, r := range recs {
|
||||
if r.Type == "IGNORE" {
|
||||
ignored = append(ignored, r.Name)
|
||||
ignored = append(ignored, r.GetLabel())
|
||||
} else {
|
||||
records = append(records, r)
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ func TestRR(t *testing.T) {
|
|||
experiment := RecordConfig{
|
||||
Type: "A",
|
||||
Name: "foo",
|
||||
NameFQDN: "foo.example.com",
|
||||
Target: "1.2.3.4",
|
||||
TTL: 0,
|
||||
NameFQDN: "foo.example.com",
|
||||
MxPreference: 0,
|
||||
}
|
||||
expected := "foo.example.com.\t300\tIN\tA\t1.2.3.4"
|
||||
|
@ -40,9 +40,9 @@ func TestRR(t *testing.T) {
|
|||
experiment = RecordConfig{
|
||||
Type: "CAA",
|
||||
Name: "@",
|
||||
NameFQDN: "example.com",
|
||||
Target: "mailto:test@example.com",
|
||||
TTL: 300,
|
||||
NameFQDN: "example.com",
|
||||
CaaTag: "iodef",
|
||||
CaaFlag: 1,
|
||||
}
|
||||
|
@ -55,9 +55,9 @@ func TestRR(t *testing.T) {
|
|||
experiment = RecordConfig{
|
||||
Type: "TLSA",
|
||||
Name: "@",
|
||||
NameFQDN: "_443._tcp.example.com",
|
||||
Target: "abcdef0123456789",
|
||||
TTL: 300,
|
||||
NameFQDN: "_443._tcp.example.com",
|
||||
TlsaUsage: 0,
|
||||
TlsaSelector: 0,
|
||||
TlsaMatchingType: 1,
|
||||
|
@ -74,17 +74,17 @@ func TestDowncase(t *testing.T) {
|
|||
&RecordConfig{Type: "MX", Name: "lower", Target: "targetmx"},
|
||||
&RecordConfig{Type: "MX", Name: "UPPER", Target: "TARGETMX"},
|
||||
}}
|
||||
Downcase(dc.Records)
|
||||
downcase(dc.Records)
|
||||
if !dc.HasRecordTypeName("MX", "lower") {
|
||||
t.Errorf("%v: expected (%v) got (%v)\n", dc.Records, false, true)
|
||||
}
|
||||
if !dc.HasRecordTypeName("MX", "upper") {
|
||||
t.Errorf("%v: expected (%v) got (%v)\n", dc.Records, false, true)
|
||||
}
|
||||
if dc.Records[0].Target != "targetmx" {
|
||||
t.Errorf("%v: target0 expected (%v) got (%v)\n", dc.Records, "targetmx", dc.Records[0].Target)
|
||||
if dc.Records[0].GetTargetField() != "targetmx" {
|
||||
t.Errorf("%v: target0 expected (%v) got (%v)\n", dc.Records, "targetmx", dc.Records[0].GetTargetField())
|
||||
}
|
||||
if dc.Records[1].Target != "targetmx" {
|
||||
t.Errorf("%v: target1 expected (%v) got (%v)\n", dc.Records, "targetmx", dc.Records[1].Target)
|
||||
if dc.Records[1].GetTargetField() != "targetmx" {
|
||||
t.Errorf("%v: target1 expected (%v) got (%v)\n", dc.Records, "targetmx", dc.Records[1].GetTargetField())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ func (dc *DomainConfig) Copy() (*DomainConfig, error) {
|
|||
// HasRecordTypeName returns True if there is a record with this rtype and name.
|
||||
func (dc *DomainConfig) HasRecordTypeName(rtype, name string) bool {
|
||||
for _, r := range dc.Records {
|
||||
if r.Type == rtype && r.Name == name {
|
||||
if r.Type == rtype && r.GetLabel() == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -73,19 +73,17 @@ func (dc *DomainConfig) Filter(f func(r *RecordConfig) bool) {
|
|||
// - NameFQDN
|
||||
// - Target (CNAME and MX only)
|
||||
func (dc *DomainConfig) Punycode() error {
|
||||
var err error
|
||||
for _, rec := range dc.Records {
|
||||
rec.Name, err = idna.ToASCII(rec.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rec.NameFQDN, err = idna.ToASCII(rec.NameFQDN)
|
||||
t, err := idna.ToASCII(rec.GetLabelFQDN())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rec.SetLabelFromFQDN(t, dc.Name)
|
||||
switch rec.Type { // #rtype_variations
|
||||
case "ALIAS", "MX", "NS", "CNAME", "PTR", "SRV", "URL", "URL301", "FRAME", "R53_ALIAS":
|
||||
rec.Target, err = idna.ToASCII(rec.Target)
|
||||
// These rtypes are hostnames, therefore need to be converted (unlike, for example, an AAAA record)
|
||||
t, err := idna.ToASCII(rec.GetTargetField())
|
||||
rec.SetTarget(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -120,6 +120,14 @@ func (rc *RecordConfig) SetLabel(short, origin string) {
|
|||
}
|
||||
}
|
||||
|
||||
// UnsafeSetLabelNull sets the label to "". Normally the FQDN is denoted by .Name being
|
||||
// "@" however this can be used to violate that assertion. It should only be used
|
||||
// on copies of a RecordConfig that is being used for non-standard things like
|
||||
// Marshalling yaml.
|
||||
func (rc *RecordConfig) UnsafeSetLabelNull() {
|
||||
rc.Name = ""
|
||||
}
|
||||
|
||||
// SetLabelFromFQDN sets the .Name/.NameFQDN fields given a FQDN and origin.
|
||||
// fqdn may have a trailing "." but it is not required.
|
||||
// origin may not have a trailing dot.
|
||||
|
@ -268,11 +276,11 @@ func (r Records) GroupedByLabel() ([]string, map[string]Records) {
|
|||
|
||||
// PostProcessRecords does any post-processing of the downloaded DNS records.
|
||||
func PostProcessRecords(recs []*RecordConfig) {
|
||||
Downcase(recs)
|
||||
downcase(recs)
|
||||
}
|
||||
|
||||
// Downcase converts all labels and targets to lowercase in a list of RecordConfig.
|
||||
func Downcase(recs []*RecordConfig) {
|
||||
func downcase(recs []*RecordConfig) {
|
||||
for _, r := range recs {
|
||||
r.Name = strings.ToLower(r.Name)
|
||||
r.NameFQDN = strings.ToLower(r.NameFQDN)
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
func (rc *RecordConfig) SetTargetCAA(flag uint8, tag string, target string) error {
|
||||
rc.CaaTag = tag
|
||||
rc.CaaFlag = flag
|
||||
rc.Target = target
|
||||
rc.SetTarget(target)
|
||||
if rc.Type == "" {
|
||||
rc.Type = "CAA"
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
// SetTargetMX sets the MX fields.
|
||||
func (rc *RecordConfig) SetTargetMX(pref uint16, target string) error {
|
||||
rc.MxPreference = pref
|
||||
rc.Target = target
|
||||
rc.SetTarget(target)
|
||||
if rc.Type == "" {
|
||||
rc.Type = "MX"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ func (rc *RecordConfig) SetTargetSRV(priority, weight, port uint16, target strin
|
|||
rc.SrvPriority = priority
|
||||
rc.SrvWeight = weight
|
||||
rc.SrvPort = port
|
||||
rc.Target = target
|
||||
rc.SetTarget(target)
|
||||
if rc.Type == "" {
|
||||
rc.Type = "SRV"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ func (rc *RecordConfig) SetTargetTLSA(usage, selector, matchingtype uint8, targe
|
|||
rc.TlsaUsage = usage
|
||||
rc.TlsaSelector = selector
|
||||
rc.TlsaMatchingType = matchingtype
|
||||
rc.Target = target
|
||||
rc.SetTarget(target)
|
||||
if rc.Type == "" {
|
||||
rc.Type = "TLSA"
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package models
|
|||
|
||||
// SetTargetTXT sets the TXT fields when there is 1 string.
|
||||
func (rc *RecordConfig) SetTargetTXT(s string) error {
|
||||
rc.Target = s
|
||||
rc.SetTarget(s)
|
||||
rc.TxtStrings = []string{s}
|
||||
if rc.Type == "" {
|
||||
rc.Type = "TXT"
|
||||
|
@ -15,7 +15,7 @@ func (rc *RecordConfig) SetTargetTXT(s string) error {
|
|||
|
||||
// SetTargetTXTs sets the TXT fields when there are many strings.
|
||||
func (rc *RecordConfig) SetTargetTXTs(s []string) error {
|
||||
rc.Target = s[0]
|
||||
rc.SetTarget(s[0])
|
||||
rc.TxtStrings = s
|
||||
if rc.Type == "" {
|
||||
rc.Type = "TXT"
|
||||
|
|
|
@ -109,11 +109,11 @@ func (rc *RecordConfig) SetTarget(target string) error {
|
|||
// SetTargetIP sets the target to an IP, verifying this is an appropriate rtype.
|
||||
func (rc *RecordConfig) SetTargetIP(ip net.IP) error {
|
||||
// TODO(tlim): Verify the rtype is appropriate for an IP.
|
||||
rc.Target = ip.String()
|
||||
rc.SetTarget(ip.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
// // SetTargetFQDN sets the target to an IP, verifying this is an appropriate rtype.
|
||||
// // SetTargetFQDN sets the target to a string, verifying this is an appropriate rtype.
|
||||
// func (rc *RecordConfig) SetTargetFQDN(target string) error {
|
||||
// // TODO(tlim): Verify the rtype is appropriate for an hostname.
|
||||
// rc.Target = target
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
)
|
||||
|
||||
// DetermineNameservers will find all nameservers we should use for a domain. It follows the following rules:
|
||||
|
@ -52,15 +51,16 @@ func AddNSRecords(dc *models.DomainConfig) {
|
|||
for _, ns := range dc.Nameservers {
|
||||
rc := &models.RecordConfig{
|
||||
Type: "NS",
|
||||
Name: "@",
|
||||
Target: ns.Name,
|
||||
Metadata: map[string]string{},
|
||||
TTL: ttl,
|
||||
}
|
||||
if !strings.HasSuffix(rc.Target, ".") {
|
||||
rc.Target += "."
|
||||
rc.SetLabel("@", dc.Name)
|
||||
t := ns.Name
|
||||
if !strings.HasSuffix(t, ".") {
|
||||
rc.SetTarget(t + ".")
|
||||
}
|
||||
rc.NameFQDN = dnsutil.AddOrigin(rc.Name, dc.Name)
|
||||
rc.SetTarget(t)
|
||||
|
||||
dc.Records = append(dc.Records, rc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package normalize
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
|
@ -27,13 +26,13 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
|
|||
return []error{err}
|
||||
}
|
||||
}
|
||||
rec, err = spflib.Parse(txt.Target, cache)
|
||||
rec, err = spflib.Parse(txt.GetTargetField(), cache)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if flatten, ok := txt.Metadata["flatten"]; ok && strings.HasPrefix(txt.Target, "v=spf1") {
|
||||
if flatten, ok := txt.Metadata["flatten"]; ok && strings.HasPrefix(txt.GetTargetField(), "v=spf1") {
|
||||
rec = rec.Flatten(flatten)
|
||||
err = txt.SetTargetTXT(rec.TXT())
|
||||
if err != nil {
|
||||
|
@ -44,7 +43,7 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
|
|||
// now split if needed
|
||||
if split, ok := txt.Metadata["split"]; ok {
|
||||
if !strings.Contains(split, "%d") {
|
||||
errs = append(errs, Warning{errors.Errorf("Split format `%s` in `%s` is not proper format (should have %%d in it)", split, txt.NameFQDN)})
|
||||
errs = append(errs, Warning{errors.Errorf("Split format `%s` in `%s` is not proper format (should have %%d in it)", split, txt.GetLabelFQDN())})
|
||||
continue
|
||||
}
|
||||
recs := rec.TXTSplit(split + "." + domain.Name)
|
||||
|
@ -54,8 +53,7 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
|
|||
} else {
|
||||
cp, _ := txt.Copy()
|
||||
cp.SetTargetTXT(v)
|
||||
cp.NameFQDN = k
|
||||
cp.Name = dnsutil.TrimDomainName(k, domain.Name)
|
||||
cp.SetLabelFromFQDN(k, domain.Name)
|
||||
domain.Records = append(domain.Records, cp)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,12 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/models"
|
||||
)
|
||||
|
||||
func makeRC(label, domain, target string, rc models.RecordConfig) *models.RecordConfig {
|
||||
rc.SetLabel(label, domain)
|
||||
rc.SetTarget(target)
|
||||
return &rc
|
||||
}
|
||||
|
||||
func TestImportTransform(t *testing.T) {
|
||||
|
||||
const transformDouble = "0.0.0.0~1.1.1.1~~9.0.0.0,10.0.0.0"
|
||||
|
@ -13,15 +19,15 @@ func TestImportTransform(t *testing.T) {
|
|||
src := &models.DomainConfig{
|
||||
Name: "stackexchange.com",
|
||||
Records: []*models.RecordConfig{
|
||||
{Type: "A", Name: "*", NameFQDN: "*.stackexchange.com", Target: "0.0.2.2"},
|
||||
{Type: "A", Name: "www", NameFQDN: "www.stackexchange.com", Target: "0.0.1.1"},
|
||||
makeRC("*", "stackexchange.com", "0.0.2.2", models.RecordConfig{Type: "A"}),
|
||||
makeRC("www", "stackexchange.com", "0.0.1.1", models.RecordConfig{Type: "A"}),
|
||||
},
|
||||
}
|
||||
dst := &models.DomainConfig{
|
||||
Name: "internal",
|
||||
Records: []*models.RecordConfig{
|
||||
{Type: "A", Name: "*.stackexchange.com", NameFQDN: "*.stackexchange.com.internal", Target: "0.0.3.3", Metadata: map[string]string{"transform_table": transformSingle}},
|
||||
{Type: "IMPORT_TRANSFORM", Name: "@", NameFQDN: "internal", Target: "stackexchange.com", Metadata: map[string]string{"transform_table": transformDouble}},
|
||||
makeRC("*.stackexchange.com", "*.stackexchange.com.internal", "0.0.3.3", models.RecordConfig{Type: "A", Metadata: map[string]string{"transform_table": transformSingle}}),
|
||||
makeRC("@", "internal", "stackexchange.com", models.RecordConfig{Type: "IMPORT_TRANSFORM", Metadata: map[string]string{"transform_table": transformDouble}}),
|
||||
},
|
||||
}
|
||||
cfg := &models.DNSConfig{
|
||||
|
|
|
@ -66,7 +66,7 @@ func validateRecordTypes(rec *models.RecordConfig, domain string, pTypes []strin
|
|||
if !ok {
|
||||
cType := providers.GetCustomRecordType(rec.Type)
|
||||
if cType == nil {
|
||||
return errors.Errorf("Unsupported record type (%v) domain=%v name=%v", rec.Type, domain, rec.Name)
|
||||
return errors.Errorf("Unsupported record type (%v) domain=%v name=%v", rec.Type, domain, rec.GetLabel())
|
||||
}
|
||||
for _, providerType := range pTypes {
|
||||
if providerType != cType.Provider {
|
||||
|
@ -125,11 +125,11 @@ func checkLabel(label string, rType string, domain string, meta map[string]strin
|
|||
|
||||
// checkTargets returns true if rec.Target is valid for the rec.Type.
|
||||
func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
|
||||
label := rec.Name
|
||||
target := rec.Target
|
||||
label := rec.GetLabel()
|
||||
target := rec.GetTargetField()
|
||||
check := func(e error) {
|
||||
if e != nil {
|
||||
err := errors.Errorf("In %s %s.%s: %s", rec.Type, rec.Name, domain, e.Error())
|
||||
err := errors.Errorf("In %s %s.%s: %s", rec.Type, rec.GetLabel(), domain, e.Error())
|
||||
if _, ok := e.(Warning); ok {
|
||||
err = Warning{err}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
|
|||
return
|
||||
}
|
||||
errs = append(errs, errors.Errorf("checkTargets: Unimplemented record type (%v) domain=%v name=%v",
|
||||
rec.Type, domain, rec.Name))
|
||||
rec.Type, domain, rec.GetLabel()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -189,13 +189,13 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
|
|||
// 4. For As, change the target as described the transforms.
|
||||
|
||||
for _, rec := range srcDomain.Records {
|
||||
if dstDomain.HasRecordTypeName(rec.Type, rec.NameFQDN) {
|
||||
if dstDomain.HasRecordTypeName(rec.Type, rec.GetLabelFQDN()) {
|
||||
continue
|
||||
}
|
||||
newRec := func() *models.RecordConfig {
|
||||
rec2, _ := rec.Copy()
|
||||
rec2.Name = rec2.NameFQDN
|
||||
rec2.NameFQDN = dnsutil.AddOrigin(rec2.Name, dstDomain.Name)
|
||||
newlabel := rec2.GetLabelFQDN()
|
||||
rec2.SetLabelFromFQDN(newlabel, dstDomain.Name)
|
||||
if ttl != 0 {
|
||||
rec2.TTL = ttl
|
||||
}
|
||||
|
@ -203,25 +203,25 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
|
|||
}
|
||||
switch rec.Type { // #rtype_variations
|
||||
case "A":
|
||||
trs, err := transform.TransformIPToList(net.ParseIP(rec.Target), transforms)
|
||||
trs, err := transform.TransformIPToList(net.ParseIP(rec.GetTargetField()), transforms)
|
||||
if err != nil {
|
||||
return errors.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.Target, transforms, err)
|
||||
return errors.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.GetTargetField(), transforms, err)
|
||||
}
|
||||
for _, tr := range trs {
|
||||
r := newRec()
|
||||
r.Target = tr.String()
|
||||
r.SetTarget(tr.String())
|
||||
dstDomain.Records = append(dstDomain.Records, r)
|
||||
}
|
||||
case "CNAME":
|
||||
r := newRec()
|
||||
r.Target = transformCNAME(r.Target, srcDomain.Name, dstDomain.Name)
|
||||
r.SetTarget(transformCNAME(r.GetTargetField(), srcDomain.Name, dstDomain.Name))
|
||||
dstDomain.Records = append(dstDomain.Records, r)
|
||||
case "MX", "NS", "SRV", "TXT", "CAA", "TLSA":
|
||||
// Not imported.
|
||||
continue
|
||||
default:
|
||||
return errors.Errorf("import_transform: Unimplemented record type %v (%v)",
|
||||
rec.Type, rec.Name)
|
||||
rec.Type, rec.GetLabel())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -276,7 +276,7 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
|
|||
if err := validateRecordTypes(rec, domain.Name, pTypes); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if err := checkLabel(rec.Name, rec.Type, domain.Name, rec.Metadata); err != nil {
|
||||
if err := checkLabel(rec.GetLabel(), rec.Type, domain.Name, rec.Metadata); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if errs2 := checkTargets(rec, domain.Name); errs2 != nil {
|
||||
|
@ -285,14 +285,16 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
|
|||
|
||||
// Canonicalize Targets.
|
||||
if rec.Type == "CNAME" || rec.Type == "MX" || rec.Type == "NS" {
|
||||
rec.Target = dnsutil.AddOrigin(rec.Target, domain.Name+".")
|
||||
rec.SetTarget(dnsutil.AddOrigin(rec.GetTargetField(), domain.Name+"."))
|
||||
} else if rec.Type == "A" || rec.Type == "AAAA" {
|
||||
rec.Target = net.ParseIP(rec.Target).String()
|
||||
rec.SetTarget(net.ParseIP(rec.GetTargetField()).String())
|
||||
} else if rec.Type == "PTR" {
|
||||
var err error
|
||||
if rec.Name, err = transform.PtrNameMagic(rec.Name, domain.Name); err != nil {
|
||||
var name string
|
||||
if name, err = transform.PtrNameMagic(rec.GetLabel(), domain.Name); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
rec.SetLabel(name, domain.Name)
|
||||
} else if rec.Type == "CAA" {
|
||||
if rec.CaaTag != "issue" && rec.CaaTag != "issuewild" && rec.CaaTag != "iodef" {
|
||||
errs = append(errs, errors.Errorf("CAA tag %s is invalid", rec.CaaTag))
|
||||
|
@ -300,26 +302,26 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
|
|||
} else if rec.Type == "TLSA" {
|
||||
if rec.TlsaUsage < 0 || rec.TlsaUsage > 3 {
|
||||
errs = append(errs, errors.Errorf("TLSA Usage %d is invalid in record %s (domain %s)",
|
||||
rec.TlsaUsage, rec.Name, domain.Name))
|
||||
rec.TlsaUsage, rec.GetLabel(), domain.Name))
|
||||
}
|
||||
if rec.TlsaSelector < 0 || rec.TlsaSelector > 1 {
|
||||
errs = append(errs, errors.Errorf("TLSA Selector %d is invalid in record %s (domain %s)",
|
||||
rec.TlsaSelector, rec.Name, domain.Name))
|
||||
rec.TlsaSelector, rec.GetLabel(), domain.Name))
|
||||
}
|
||||
if rec.TlsaMatchingType < 0 || rec.TlsaMatchingType > 2 {
|
||||
errs = append(errs, errors.Errorf("TLSA MatchingType %d is invalid in record %s (domain %s)",
|
||||
rec.TlsaMatchingType, rec.Name, domain.Name))
|
||||
rec.TlsaMatchingType, rec.GetLabel(), domain.Name))
|
||||
}
|
||||
} else if rec.Type == "TXT" && len(txtMultiDissenters) != 0 && len(rec.TxtStrings) > 1 {
|
||||
// There are providers that don't support TXTMulti yet there is
|
||||
// a TXT record with multiple strings:
|
||||
errs = append(errs,
|
||||
errors.Errorf("TXT records with multiple strings (label %v domain: %v) not supported by %s",
|
||||
rec.Name, domain.Name, strings.Join(txtMultiDissenters, ",")))
|
||||
rec.GetLabel(), domain.Name, strings.Join(txtMultiDissenters, ",")))
|
||||
}
|
||||
|
||||
// Populate FQDN:
|
||||
rec.NameFQDN = dnsutil.AddOrigin(rec.Name, domain.Name)
|
||||
//rec.NameFQDN = dnsutil.AddOrigin(rec.GetLabel(), domain.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +339,7 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
|
|||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
err = importTransform(config.FindDomain(rec.Target), domain, table, rec.TTL)
|
||||
err = importTransform(config.FindDomain(rec.GetTargetField()), domain, table, rec.TTL)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
@ -375,15 +377,15 @@ func checkCNAMEs(dc *models.DomainConfig) (errs []error) {
|
|||
cnames := map[string]bool{}
|
||||
for _, r := range dc.Records {
|
||||
if r.Type == "CNAME" {
|
||||
if cnames[r.Name] {
|
||||
errs = append(errs, errors.Errorf("Cannot have multiple CNAMEs with same name: %s", r.NameFQDN))
|
||||
if cnames[r.GetLabel()] {
|
||||
errs = append(errs, errors.Errorf("Cannot have multiple CNAMEs with same name: %s", r.GetLabelFQDN()))
|
||||
}
|
||||
cnames[r.Name] = true
|
||||
cnames[r.GetLabel()] = true
|
||||
}
|
||||
}
|
||||
for _, r := range dc.Records {
|
||||
if cnames[r.Name] && r.Type != "CNAME" {
|
||||
errs = append(errs, errors.Errorf("Cannot have CNAME and %s record with same name: %s", r.Type, r.NameFQDN))
|
||||
if cnames[r.GetLabel()] && r.Type != "CNAME" {
|
||||
errs = append(errs, errors.Errorf("Cannot have CNAME and %s record with same name: %s", r.Type, r.GetLabelFQDN()))
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -433,21 +435,21 @@ func applyRecordTransforms(domain *models.DomainConfig) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip := net.ParseIP(rec.Target) // ip already validated above
|
||||
newIPs, err := transform.TransformIPToList(net.ParseIP(rec.Target), table)
|
||||
ip := net.ParseIP(rec.GetTargetField()) // ip already validated above
|
||||
newIPs, err := transform.TransformIPToList(net.ParseIP(rec.GetTargetField()), table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i, newIP := range newIPs {
|
||||
if i == 0 && !newIP.Equal(ip) {
|
||||
rec.Target = newIP.String() // replace target of first record if different
|
||||
rec.SetTarget(newIP.String()) // replace target of first record if different
|
||||
} else if i > 0 {
|
||||
// any additional ips need identical records with the alternate ip added to the domain
|
||||
copy, err := rec.Copy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy.Target = newIP.String()
|
||||
copy.SetTarget(newIP.String())
|
||||
domain.Records = append(domain.Records, copy)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,12 +113,14 @@ func Test_transform_cname(t *testing.T) {
|
|||
|
||||
func TestNSAtRoot(t *testing.T) {
|
||||
// do not allow ns records for @
|
||||
rec := &models.RecordConfig{Name: "test", Type: "NS", Target: "ns1.name.com."}
|
||||
rec := &models.RecordConfig{Type: "NS"}
|
||||
rec.SetLabel("test", "foo.com")
|
||||
rec.SetTarget("ns1.name.com.")
|
||||
errs := checkTargets(rec, "foo.com")
|
||||
if len(errs) > 0 {
|
||||
t.Error("Expect no error with ns record on subdomain")
|
||||
}
|
||||
rec.Name = "@"
|
||||
rec.SetLabel("@", "foo.com")
|
||||
errs = checkTargets(rec, "foo.com")
|
||||
if len(errs) != 1 {
|
||||
t.Error("Expect error with ns record on @")
|
||||
|
@ -138,7 +140,7 @@ func TestTransforms(t *testing.T) {
|
|||
for i, test := range tests {
|
||||
dc := &models.DomainConfig{
|
||||
Records: []*models.RecordConfig{
|
||||
{Type: "A", Target: test.givenIP, Metadata: map[string]string{"transform": transform}},
|
||||
makeRC("f", "example.tld", test.givenIP, models.RecordConfig{Type: "A", Metadata: map[string]string{"transform": transform}}),
|
||||
},
|
||||
}
|
||||
err := applyRecordTransforms(dc)
|
||||
|
@ -151,8 +153,8 @@ func TestTransforms(t *testing.T) {
|
|||
continue
|
||||
}
|
||||
for r, rec := range dc.Records {
|
||||
if rec.Target != test.expectedRecords[r] {
|
||||
t.Errorf("test %d at index %d: records don't match. Expect %s but found %s.", i, r, test.expectedRecords[r], rec.Target)
|
||||
if rec.GetTargetField() != test.expectedRecords[r] {
|
||||
t.Errorf("test %d at index %d: records don't match. Expect %s but found %s.", i, r, test.expectedRecords[r], rec.GetTargetField())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +162,9 @@ func TestTransforms(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCNAMEMutex(t *testing.T) {
|
||||
var recA = &models.RecordConfig{Type: "CNAME", Name: "foo", NameFQDN: "foo.example.com", Target: "example.com."}
|
||||
var recA = &models.RecordConfig{Type: "CNAME"}
|
||||
recA.SetLabel("foo", "foo.example.com")
|
||||
recA.SetTarget("example.com.")
|
||||
tests := []struct {
|
||||
rType string
|
||||
name string
|
||||
|
@ -173,7 +177,9 @@ func TestCNAMEMutex(t *testing.T) {
|
|||
}
|
||||
for _, tst := range tests {
|
||||
t.Run(fmt.Sprintf("%s %s", tst.rType, tst.name), func(t *testing.T) {
|
||||
var recB = &models.RecordConfig{Type: tst.rType, Name: tst.name, NameFQDN: tst.name + ".example.com", Target: "example2.com."}
|
||||
var recB = &models.RecordConfig{Type: tst.rType}
|
||||
recB.SetLabel(tst.name, "example.com")
|
||||
recB.SetTarget("example2.com.")
|
||||
dc := &models.DomainConfig{
|
||||
Name: "example.com",
|
||||
Records: []*models.RecordConfig{recA, recB},
|
||||
|
@ -196,7 +202,7 @@ func TestCAAValidation(t *testing.T) {
|
|||
Name: "example.com",
|
||||
RegistrarName: "BIND",
|
||||
Records: []*models.RecordConfig{
|
||||
{Name: "@", NameFQDN: "example.com", Type: "CAA", CaaTag: "invalid", Target: "example.com"},
|
||||
makeRC("@", "example.com", "example.com", models.RecordConfig{Type: "CAA", CaaTag: "invalid"}),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -214,7 +220,8 @@ func TestTLSAValidation(t *testing.T) {
|
|||
Name: "_443._tcp.example.com",
|
||||
RegistrarName: "BIND",
|
||||
Records: []*models.RecordConfig{
|
||||
{Name: "_443._tcp", NameFQDN: "_443._tcp._443._tcp.example.com", Type: "TLSA", TlsaUsage: 4, TlsaSelector: 1, TlsaMatchingType: 1, Target: "abcdef0"},
|
||||
makeRC("_443._tcp", "_443._tcp.example.com", "abcdef0", models.RecordConfig{
|
||||
Type: "TLSA", TlsaUsage: 4, TlsaSelector: 1, TlsaMatchingType: 1}),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/TomOnTime/utfutil"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -35,7 +34,7 @@ func (c *adProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Co
|
|||
|
||||
dc.Filter(func(r *models.RecordConfig) bool {
|
||||
if r.Type != "A" && r.Type != "CNAME" {
|
||||
log.Printf("WARNING: Active Directory only manages A and CNAME records. Won't consider %s %s", r.Type, r.NameFQDN)
|
||||
log.Printf("WARNING: Active Directory only manages A and CNAME records. Won't consider %s %s", r.Type, r.GetLabelFQDN())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
@ -162,18 +161,16 @@ func (c *adProvider) getExistingRecords(domainname string) ([]*models.RecordConf
|
|||
}
|
||||
|
||||
func (r *RecordConfigJson) unpackRecord(origin string) *models.RecordConfig {
|
||||
rc := models.RecordConfig{}
|
||||
|
||||
rc.Name = strings.ToLower(r.Name)
|
||||
rc.NameFQDN = dnsutil.AddOrigin(rc.Name, origin)
|
||||
rc.Type = r.Type
|
||||
rc.TTL = r.TTL
|
||||
|
||||
switch rc.Type { // #rtype_variations
|
||||
case "A":
|
||||
rc.Target = r.Data
|
||||
rc := models.RecordConfig{
|
||||
Type: r.Type,
|
||||
TTL: r.TTL,
|
||||
}
|
||||
rc.SetLabel(r.Name, origin)
|
||||
switch rtype := rc.Type; rtype { // #rtype_variations
|
||||
case "A", "AAAA":
|
||||
rc.SetTarget(r.Data)
|
||||
case "CNAME":
|
||||
rc.Target = strings.ToLower(r.Data)
|
||||
rc.SetTarget(strings.ToLower(r.Data))
|
||||
case "NS", "SOA":
|
||||
return nil
|
||||
default:
|
||||
|
@ -197,12 +194,12 @@ Get-DnsServerResourceRecord -ComputerName REPLACE_WITH_COMPUTER_NAME -ZoneName $
|
|||
|
||||
// generatePowerShellCreate generates PowerShell commands to ADD a record.
|
||||
func (c *adProvider) generatePowerShellCreate(domainname string, rec *models.RecordConfig) string {
|
||||
content := rec.Target
|
||||
content := rec.GetTargetField()
|
||||
text := "\r\n" // Skip a line.
|
||||
text += fmt.Sprintf("Add-DnsServerResourceRecord%s", rec.Type)
|
||||
text += fmt.Sprintf(` -ComputerName "%s"`, c.adServer)
|
||||
text += fmt.Sprintf(` -ZoneName "%s"`, domainname)
|
||||
text += fmt.Sprintf(` -Name "%s"`, rec.Name)
|
||||
text += fmt.Sprintf(` -Name "%s"`, rec.GetLabel())
|
||||
text += fmt.Sprintf(` -TimeToLive $(New-TimeSpan -Seconds %d)`, rec.TTL)
|
||||
switch rec.Type { // #rtype_variations
|
||||
case "CNAME":
|
||||
|
@ -210,9 +207,10 @@ func (c *adProvider) generatePowerShellCreate(domainname string, rec *models.Rec
|
|||
case "A":
|
||||
text += fmt.Sprintf(` -IPv4Address "%s"`, content)
|
||||
case "NS":
|
||||
text = fmt.Sprintf("\r\n"+`echo "Skipping NS update (%v %v)"`+"\r\n", rec.Name, rec.Target)
|
||||
text = fmt.Sprintf("\r\n"+`echo "Skipping NS update (%v %v)"`+"\r\n", rec.GetLabel(), rec.GetTargetDebug())
|
||||
default:
|
||||
panic(errors.Errorf("generatePowerShellCreate() does not yet handle recType=%s recName=%#v content=%#v)", rec.Type, rec.Name, content))
|
||||
panic(errors.Errorf("generatePowerShellCreate() does not yet handle recType=%s recName=%#v content=%#v)",
|
||||
rec.Type, rec.GetLabel(), content))
|
||||
// We panic so that we quickly find any switch statements
|
||||
// that have not been updated for a new RR type.
|
||||
}
|
||||
|
@ -286,7 +284,7 @@ func (c *adProvider) generatePowerShellDelete(domainname, recName, recType, cont
|
|||
func (c *adProvider) createRec(domainname string, rec *models.RecordConfig) []*models.Correction {
|
||||
arr := []*models.Correction{
|
||||
{
|
||||
Msg: fmt.Sprintf("CREATE record: %s %s ttl(%d) %s", rec.Name, rec.Type, rec.TTL, rec.Target),
|
||||
Msg: fmt.Sprintf("CREATE record: %s %s ttl(%d) %s", rec.GetLabel(), rec.Type, rec.TTL, rec.GetTargetField()),
|
||||
F: func() error {
|
||||
return c.powerShellDoCommand(c.generatePowerShellCreate(domainname, rec), true)
|
||||
}},
|
||||
|
@ -299,16 +297,16 @@ func (c *adProvider) modifyRec(domainname string, m diff.Correlation) *models.Co
|
|||
return &models.Correction{
|
||||
Msg: m.String(),
|
||||
F: func() error {
|
||||
return c.powerShellDoCommand(c.generatePowerShellModify(domainname, rec.Name, rec.Type, old.Target, rec.Target, old.TTL, rec.TTL), true)
|
||||
return c.powerShellDoCommand(c.generatePowerShellModify(domainname, rec.GetLabel(), rec.Type, old.GetTargetField(), rec.GetTargetField(), old.TTL, rec.TTL), true)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *adProvider) deleteRec(domainname string, rec *models.RecordConfig) *models.Correction {
|
||||
return &models.Correction{
|
||||
Msg: fmt.Sprintf("DELETE record: %s %s ttl(%d) %s", rec.Name, rec.Type, rec.TTL, rec.Target),
|
||||
Msg: fmt.Sprintf("DELETE record: %s %s ttl(%d) %s", rec.GetLabel(), rec.Type, rec.TTL, rec.GetTargetField()),
|
||||
F: func() error {
|
||||
return c.powerShellDoCommand(c.generatePowerShellDelete(domainname, rec.Name, rec.Type, rec.Target), true)
|
||||
return c.powerShellDoCommand(c.generatePowerShellDelete(domainname, rec.GetLabel(), rec.Type, rec.GetTargetField()), true)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,12 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/models"
|
||||
)
|
||||
|
||||
func makeRC(label, domain, target string, rc models.RecordConfig) *models.RecordConfig {
|
||||
rc.SetLabel(label, domain)
|
||||
rc.SetTarget(target)
|
||||
return &rc
|
||||
}
|
||||
|
||||
func TestGetExistingRecords(t *testing.T) {
|
||||
|
||||
cf := &adProvider{}
|
||||
|
@ -17,11 +23,11 @@ func TestGetExistingRecords(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
expected := []*models.RecordConfig{
|
||||
{Name: "@", NameFQDN: "test2", Type: "A", TTL: 600, Target: "10.166.2.11"},
|
||||
//{Name: "_msdcs", NameFQDN: "_msdcs.test2", Type: "NS", TTL: 300, Target: "other_record"}, // Will be filtered.
|
||||
{Name: "co-devsearch02", NameFQDN: "co-devsearch02.test2", Type: "A", TTL: 3600, Target: "10.8.2.64"},
|
||||
{Name: "co-devservice01", NameFQDN: "co-devservice01.test2", Type: "A", TTL: 1200, Target: "10.8.2.48"}, // Downcased.
|
||||
{Name: "yum", NameFQDN: "yum.test2", Type: "A", TTL: 3600, Target: "10.8.0.59"},
|
||||
makeRC("@", "test2", "10.166.2.11", models.RecordConfig{Type: "A", TTL: 600}),
|
||||
//makeRC("_msdcs", "test2", "other_record", models.RecordConfig{Type: "NS", TTL: 300}), // Will be filtered.
|
||||
makeRC("co-devsearch02", "test2", "10.8.2.64", models.RecordConfig{Type: "A", TTL: 3600}),
|
||||
makeRC("co-devservice01", "test2", "10.8.2.48", models.RecordConfig{Type: "A", TTL: 1200}), // Downcased.
|
||||
makeRC("yum", "test2", "10.8.0.59", models.RecordConfig{Type: "A", TTL: 3600}),
|
||||
}
|
||||
|
||||
actualS := ""
|
||||
|
|
|
@ -127,7 +127,7 @@ func rrToRecord(rr dns.RR, origin string, replaceSerial uint32) (models.RecordCo
|
|||
}
|
||||
newSerial = v.Serial
|
||||
//if (dnsutil.TrimDomainName(rc.Name, origin+".") == "@") && replaceSerial != 0 {
|
||||
if rc.Name == "@" && replaceSerial != 0 {
|
||||
if rc.GetLabel() == "@" && replaceSerial != 0 {
|
||||
newSerial = replaceSerial
|
||||
}
|
||||
panicInvalid(rc.SetTarget(
|
||||
|
|
|
@ -16,14 +16,25 @@ func newDomainConfig() *models.DomainConfig {
|
|||
}
|
||||
}
|
||||
|
||||
func makeRCmeta(meta map[string]string) *models.RecordConfig {
|
||||
rc := models.RecordConfig{
|
||||
Type: "A",
|
||||
Metadata: meta,
|
||||
}
|
||||
rc.SetLabel("foo", "example.tld")
|
||||
rc.SetTarget("1.2.3.4")
|
||||
return &rc
|
||||
}
|
||||
|
||||
func TestPreprocess_BoolValidation(t *testing.T) {
|
||||
cf := &CloudflareApi{}
|
||||
|
||||
domain := newDomainConfig()
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{metaProxy: "on"}})
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{metaProxy: "fUll"}})
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{}})
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{metaProxy: "Off"}})
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{metaProxy: "off"}})
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{metaProxy: "on"}))
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{metaProxy: "fUll"}))
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{}))
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{metaProxy: "Off"}))
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{metaProxy: "off"}))
|
||||
err := cf.preprocessConfig(domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -51,9 +62,9 @@ func TestPreprocess_DefaultProxy(t *testing.T) {
|
|||
cf := &CloudflareApi{}
|
||||
domain := newDomainConfig()
|
||||
domain.Metadata[metaProxyDefault] = "full"
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{metaProxy: "on"}})
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{metaProxy: "off"}})
|
||||
domain.Records = append(domain.Records, &models.RecordConfig{Type: "A", Target: "1.2.3.4", Metadata: map[string]string{}})
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{metaProxy: "on"}))
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{metaProxy: "off"}))
|
||||
domain.Records = append(domain.Records, makeRCmeta(map[string]string{}))
|
||||
err := cf.preprocessConfig(domain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -97,7 +108,8 @@ func TestIpRewriting(t *testing.T) {
|
|||
NewBases: []net.IP{net.ParseIP("255.255.255.0")},
|
||||
NewIPs: nil}}
|
||||
for _, tst := range tests {
|
||||
rec := &models.RecordConfig{Type: "A", Target: tst.Given, Metadata: map[string]string{metaProxy: tst.Proxy}}
|
||||
rec := &models.RecordConfig{Type: "A", Metadata: map[string]string{metaProxy: tst.Proxy}}
|
||||
rec.SetTarget(tst.Given)
|
||||
domain.Records = append(domain.Records, rec)
|
||||
}
|
||||
err := cf.preprocessConfig(domain)
|
||||
|
@ -106,8 +118,8 @@ func TestIpRewriting(t *testing.T) {
|
|||
}
|
||||
for i, tst := range tests {
|
||||
rec := domain.Records[i]
|
||||
if rec.Target != tst.Expected {
|
||||
t.Fatalf("At index %d, expected target of %s, but found %s.", i, tst.Expected, rec.Target)
|
||||
if rec.GetTargetField() != tst.Expected {
|
||||
t.Fatalf("At index %d, expected target of %s, but found %s.", i, tst.Expected, rec.GetTargetField())
|
||||
}
|
||||
if tst.Proxy == "full" && tst.Given != tst.Expected && rec.Metadata[metaOriginalIP] != tst.Given {
|
||||
t.Fatalf("At index %d, expected original_ip to be set", i)
|
||||
|
|
|
@ -77,7 +77,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr
|
|||
if d.matchIgnored(e.GetLabel()) {
|
||||
log.Printf("Ignoring record %s %s due to IGNORE", e.GetLabel(), e.Type)
|
||||
} else {
|
||||
k := key{e.NameFQDN, e.Type}
|
||||
k := key{e.GetLabelFQDN(), e.Type}
|
||||
existingByNameAndType[k] = append(existingByNameAndType[k], e)
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr
|
|||
if d.matchIgnored(dr.GetLabel()) {
|
||||
panic(fmt.Sprintf("Trying to update/add IGNOREd record: %s %s", dr.GetLabel(), dr.Type))
|
||||
} else {
|
||||
k := key{dr.NameFQDN, dr.Type}
|
||||
k := key{dr.GetLabelFQDN(), dr.Type}
|
||||
desiredByNameAndType[k] = append(desiredByNameAndType[k], dr)
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr
|
|||
for i := len(existingRecords) - 1; i >= 0; i-- {
|
||||
ex := existingRecords[i]
|
||||
for j, de := range desiredRecords {
|
||||
if de.Target == ex.Target {
|
||||
if de.GetTargetField() == ex.GetTargetField() {
|
||||
// they're either identical or should be a modification of each other (ttl or metadata changes)
|
||||
if d.content(de) == d.content(ex) {
|
||||
unchanged = append(unchanged, Correlation{d, ex, de})
|
||||
|
@ -197,12 +197,12 @@ func (d *differ) ChangedGroups(existing []*models.RecordConfig) map[models.Recor
|
|||
|
||||
func (c Correlation) String() string {
|
||||
if c.Existing == nil {
|
||||
return fmt.Sprintf("CREATE %s %s %s", c.Desired.Type, c.Desired.NameFQDN, c.d.content(c.Desired))
|
||||
return fmt.Sprintf("CREATE %s %s %s", c.Desired.Type, c.Desired.GetLabelFQDN(), c.d.content(c.Desired))
|
||||
}
|
||||
if c.Desired == nil {
|
||||
return fmt.Sprintf("DELETE %s %s %s", c.Existing.Type, c.Existing.NameFQDN, c.d.content(c.Existing))
|
||||
return fmt.Sprintf("DELETE %s %s %s", c.Existing.Type, c.Existing.GetLabelFQDN(), c.d.content(c.Existing))
|
||||
}
|
||||
return fmt.Sprintf("MODIFY %s %s: (%s) -> (%s)", c.Existing.Type, c.Existing.NameFQDN, c.d.content(c.Existing), c.d.content(c.Desired))
|
||||
return fmt.Sprintf("MODIFY %s %s: (%s) -> (%s)", c.Existing.Type, c.Existing.GetLabelFQDN(), c.d.content(c.Existing), c.d.content(c.Desired))
|
||||
}
|
||||
|
||||
func sortedKeys(m map[string]*models.RecordConfig) []string {
|
||||
|
|
|
@ -7,20 +7,19 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
)
|
||||
|
||||
func myRecord(s string) *models.RecordConfig {
|
||||
parts := strings.Split(s, " ")
|
||||
ttl, _ := strconv.ParseUint(parts[2], 10, 32)
|
||||
return &models.RecordConfig{
|
||||
Name: parts[0],
|
||||
NameFQDN: dnsutil.AddOrigin(parts[0], "example.com"),
|
||||
r := &models.RecordConfig{
|
||||
Type: parts[1],
|
||||
TTL: uint32(ttl),
|
||||
Target: parts[3],
|
||||
Metadata: map[string]string{},
|
||||
}
|
||||
r.SetLabel(parts[0], "example.com")
|
||||
r.SetTarget(parts[3])
|
||||
return r
|
||||
}
|
||||
|
||||
func TestAdditionsOnly(t *testing.T) {
|
||||
|
|
|
@ -203,7 +203,6 @@ func toRc(dc *models.DomainConfig, r *godo.DomainRecord) *models.RecordConfig {
|
|||
|
||||
t := &models.RecordConfig{
|
||||
Type: r.Type,
|
||||
Target: target,
|
||||
TTL: uint32(r.TTL),
|
||||
MxPreference: uint16(r.Priority),
|
||||
SrvPriority: uint16(r.Priority),
|
||||
|
@ -212,6 +211,7 @@ func toRc(dc *models.DomainConfig, r *godo.DomainRecord) *models.RecordConfig {
|
|||
Original: r,
|
||||
}
|
||||
t.SetLabelFromFQDN(name, dc.Name)
|
||||
t.SetTarget(target)
|
||||
switch rtype := r.Type; rtype {
|
||||
case "TXT":
|
||||
t.SetTargetTXTString(target)
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
dnsimpleapi "github.com/dnsimple/dnsimple-go/dnsimple"
|
||||
|
@ -281,7 +280,7 @@ func (c *DnsimpleApi) createRecordFunc(rc *models.RecordConfig, domainName strin
|
|||
return err
|
||||
}
|
||||
record := dnsimpleapi.ZoneRecord{
|
||||
Name: dnsutil.TrimDomainName(rc.NameFQDN, domainName),
|
||||
Name: rc.GetLabel(),
|
||||
Type: rc.Type,
|
||||
Content: rc.GetTargetCombined(),
|
||||
TTL: int(rc.TTL),
|
||||
|
@ -327,7 +326,7 @@ func (c *DnsimpleApi) updateRecordFunc(old *dnsimpleapi.ZoneRecord, rc *models.R
|
|||
}
|
||||
|
||||
record := dnsimpleapi.ZoneRecord{
|
||||
Name: dnsutil.TrimDomainName(rc.NameFQDN, domainName),
|
||||
Name: rc.GetLabel(),
|
||||
Type: rc.Type,
|
||||
Content: rc.GetTargetCombined(),
|
||||
TTL: int(rc.TTL),
|
||||
|
@ -374,7 +373,7 @@ func removeOtherNS(dc *models.DomainConfig) {
|
|||
for _, rec := range dc.Records {
|
||||
if rec.Type == "NS" {
|
||||
// apex NS inside dnsimple are expected.
|
||||
if rec.NameFQDN == dc.Name && strings.HasSuffix(rec.GetTargetField(), ".dnsimple.com.") {
|
||||
if rec.GetLabelFQDN() == dc.Name && strings.HasSuffix(rec.GetTargetField(), ".dnsimple.com.") {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Warning: dnsimple.com does not allow NS records to be modified. %s will not be added.\n", rec.GetTargetField())
|
||||
|
|
|
@ -99,11 +99,11 @@ func (c *GandiApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Corr
|
|||
return nil, errors.Errorf("ERROR: Gandi does not support TTLs > 30 days (TTL=%d)", rec.TTL)
|
||||
}
|
||||
if rec.Type == "TXT" {
|
||||
rec.Target = "\"" + rec.Target + "\"" // FIXME(tlim): Should do proper quoting.
|
||||
rec.SetTarget("\"" + rec.GetTargetField() + "\"") // FIXME(tlim): Should do proper quoting.
|
||||
}
|
||||
if rec.Type == "NS" && rec.GetLabel() == "@" {
|
||||
if !strings.HasSuffix(rec.Target, ".gandi.net.") {
|
||||
log.Printf("WARNING: Gandi does not support changing apex NS records. %s will not be added.", rec.Target)
|
||||
if !strings.HasSuffix(rec.GetTargetField(), ".gandi.net.") {
|
||||
log.Printf("WARNING: Gandi does not support changing apex NS records. %s will not be added.", rec.GetTargetField())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -223,31 +223,31 @@ func (c *liveClient) recordsToInfo(records models.Records) (models.Records, []*g
|
|||
|
||||
for _, rec := range records {
|
||||
if rec.TTL < 300 {
|
||||
log.Printf("WARNING: Gandi does not support ttls < 300. %s will not be set to %d.", rec.NameFQDN, rec.TTL)
|
||||
log.Printf("WARNING: Gandi does not support ttls < 300. %s will not be set to %d.", rec.GetLabelFQDN(), rec.TTL)
|
||||
rec.TTL = 300
|
||||
}
|
||||
if rec.TTL > 2592000 {
|
||||
return nil, nil, errors.Errorf("ERROR: Gandi does not support TTLs > 30 days (TTL=%d)", rec.TTL)
|
||||
}
|
||||
if rec.Type == "NS" && rec.Name == "@" {
|
||||
if !strings.HasSuffix(rec.Target, ".gandi.net.") {
|
||||
log.Printf("WARNING: Gandi does not support changing apex NS records. %s will not be added.", rec.Target)
|
||||
if rec.Type == "NS" && rec.GetLabel() == "@" {
|
||||
if !strings.HasSuffix(rec.GetTargetField(), ".gandi.net.") {
|
||||
log.Printf("WARNING: Gandi does not support changing apex NS records. %s will not be added.", rec.GetTargetField())
|
||||
}
|
||||
continue
|
||||
}
|
||||
r, ok := recordSets[rec.Name][rec.Type]
|
||||
r, ok := recordSets[rec.GetLabel()][rec.Type]
|
||||
if !ok {
|
||||
_, ok := recordSets[rec.Name]
|
||||
_, ok := recordSets[rec.GetLabel()]
|
||||
if !ok {
|
||||
recordSets[rec.Name] = map[string]*gandiliverecord.Info{}
|
||||
recordSets[rec.GetLabel()] = map[string]*gandiliverecord.Info{}
|
||||
}
|
||||
r = &gandiliverecord.Info{
|
||||
Type: rec.Type,
|
||||
Name: rec.Name,
|
||||
Name: rec.GetLabel(),
|
||||
TTL: int64(rec.TTL),
|
||||
}
|
||||
recordInfos = append(recordInfos, r)
|
||||
recordSets[rec.Name][rec.Type] = r
|
||||
recordSets[rec.GetLabel()][rec.Type] = r
|
||||
} else {
|
||||
if r.TTL != int64(rec.TTL) {
|
||||
log.Printf(
|
||||
|
|
|
@ -8,6 +8,11 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func makeRC(label, domain, target string, rc models.RecordConfig) *models.RecordConfig {
|
||||
rc.SetLabel(label, domain)
|
||||
rc.SetTarget(target)
|
||||
return &rc
|
||||
}
|
||||
func TestRecordConfigFromInfo(t *testing.T) {
|
||||
|
||||
for _, data := range []struct {
|
||||
|
@ -22,20 +27,14 @@ func TestRecordConfigFromInfo(t *testing.T) {
|
|||
Values: []string{"127.0.0.1", "127.1.0.1"},
|
||||
},
|
||||
[]*models.RecordConfig{
|
||||
{
|
||||
NameFQDN: "www.example.com",
|
||||
Name: "www",
|
||||
Type: "A",
|
||||
Target: "127.0.0.1",
|
||||
TTL: 500,
|
||||
},
|
||||
{
|
||||
NameFQDN: "www.example.com",
|
||||
Name: "www",
|
||||
Type: "A",
|
||||
Target: "127.1.0.1",
|
||||
TTL: 500,
|
||||
},
|
||||
makeRC("www", "example.com", "127.0.0.1", models.RecordConfig{
|
||||
Type: "A",
|
||||
TTL: 500,
|
||||
}),
|
||||
makeRC("www", "example.com", "127.1.0.1", models.RecordConfig{
|
||||
Type: "A",
|
||||
TTL: 500,
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -46,14 +45,11 @@ func TestRecordConfigFromInfo(t *testing.T) {
|
|||
Values: []string{"\"test 2\"", "\"test message test message test message\""},
|
||||
},
|
||||
[]*models.RecordConfig{
|
||||
{
|
||||
NameFQDN: "www.example.com",
|
||||
Name: "www",
|
||||
makeRC("www", "example.com", "test 2", models.RecordConfig{
|
||||
Type: "TXT",
|
||||
Target: "test 2",
|
||||
TxtStrings: []string{"test 2", "test message test message test message"},
|
||||
TTL: 500,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -65,24 +61,18 @@ func TestRecordConfigFromInfo(t *testing.T) {
|
|||
Values: []string{"0 issue \"www.certinomis.com\"", "0 issuewild \"buypass.com\""},
|
||||
},
|
||||
[]*models.RecordConfig{
|
||||
{
|
||||
NameFQDN: "www.example.com",
|
||||
Name: "www",
|
||||
Type: "CAA",
|
||||
Target: "www.certinomis.com",
|
||||
CaaFlag: 0,
|
||||
CaaTag: "issue",
|
||||
TTL: 500,
|
||||
},
|
||||
{
|
||||
NameFQDN: "www.example.com",
|
||||
Name: "www",
|
||||
Type: "CAA",
|
||||
Target: "buypass.com",
|
||||
CaaFlag: 0,
|
||||
CaaTag: "issuewild",
|
||||
TTL: 500,
|
||||
},
|
||||
makeRC("www", "example.com", "www.certinomis.com", models.RecordConfig{
|
||||
Type: "CAA",
|
||||
CaaFlag: 0,
|
||||
CaaTag: "issue",
|
||||
TTL: 500,
|
||||
}),
|
||||
makeRC("www", "example.com", "buypass.com", models.RecordConfig{
|
||||
Type: "CAA",
|
||||
CaaFlag: 0,
|
||||
CaaTag: "issuewild",
|
||||
TTL: 500,
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -93,16 +83,13 @@ func TestRecordConfigFromInfo(t *testing.T) {
|
|||
Values: []string{"20 0 5060 backupbox.example.com."},
|
||||
},
|
||||
[]*models.RecordConfig{
|
||||
{
|
||||
NameFQDN: "test.example.com",
|
||||
Name: "test",
|
||||
makeRC("test", "example.com", "backupbox.example.com.", models.RecordConfig{
|
||||
Type: "SRV",
|
||||
Target: "backupbox.example.com.",
|
||||
SrvPriority: 20,
|
||||
SrvWeight: 0,
|
||||
SrvPort: 5060,
|
||||
TTL: 500,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -113,22 +100,16 @@ func TestRecordConfigFromInfo(t *testing.T) {
|
|||
Values: []string{"50 fb.mail.gandi.net.", "10 spool.mail.gandi.net."},
|
||||
},
|
||||
[]*models.RecordConfig{
|
||||
{
|
||||
NameFQDN: "mail.example.com",
|
||||
Name: "mail",
|
||||
makeRC("mail", "example.com", "fb.mail.gandi.net.", models.RecordConfig{
|
||||
Type: "MX",
|
||||
MxPreference: 50,
|
||||
Target: "fb.mail.gandi.net.",
|
||||
TTL: 500,
|
||||
},
|
||||
{
|
||||
NameFQDN: "mail.example.com",
|
||||
Name: "mail",
|
||||
}),
|
||||
makeRC("mail", "example.com", "spool.mail.gandi.net.", models.RecordConfig{
|
||||
Type: "MX",
|
||||
MxPreference: 10,
|
||||
Target: "spool.mail.gandi.net.",
|
||||
TTL: 500,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
|
|
@ -104,7 +104,7 @@ func keyFor(r *gdns.ResourceRecordSet) key {
|
|||
return key{Type: r.Type, Name: r.Name}
|
||||
}
|
||||
func keyForRec(r *models.RecordConfig) key {
|
||||
return key{Type: r.Type, Name: r.NameFQDN + "."}
|
||||
return key{Type: r.Type, Name: r.GetLabelFQDN() + "."}
|
||||
}
|
||||
|
||||
func (g *gcloud) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||
|
|
|
@ -136,10 +136,10 @@ func (api *LinodeApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models.C
|
|||
// https://github.com/linode/manager/blob/edd99dc4e1be5ab8190f243c3dbf8b830716255e/src/constants.js#L184
|
||||
for _, name := range defaultNameServerNames {
|
||||
rc := &models.RecordConfig{
|
||||
NameFQDN: dc.Name,
|
||||
Type: "NS",
|
||||
Original: &domainRecord{},
|
||||
}
|
||||
rc.SetLabelFromFQDN(dc.Name, dc.Name)
|
||||
rc.SetTarget(name)
|
||||
|
||||
existingRecords = append(existingRecords, rc)
|
||||
|
@ -249,7 +249,7 @@ func toRc(dc *models.DomainConfig, r *domainRecord) *models.RecordConfig {
|
|||
func toReq(dc *models.DomainConfig, rc *models.RecordConfig) (*recordEditRequest, error) {
|
||||
req := &recordEditRequest{
|
||||
Type: rc.Type,
|
||||
Name: dnsutil.TrimDomainName(rc.NameFQDN, dc.Name),
|
||||
Name: rc.GetLabel(),
|
||||
Target: rc.GetTargetField(),
|
||||
TTL: int(rc.TTL),
|
||||
Priority: 0,
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
nc "github.com/billputer/go-namecheap"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -125,9 +124,9 @@ func (n *Namecheap) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Cor
|
|||
|
||||
// namecheap does not allow setting @ NS with basic DNS
|
||||
dc.Filter(func(r *models.RecordConfig) bool {
|
||||
if r.Type == "NS" && r.Name == "@" {
|
||||
if !strings.HasSuffix(r.Target, "registrar-servers.com.") {
|
||||
fmt.Println("\n", r.Target, "Namecheap does not support changing apex NS records. Skipping.")
|
||||
if r.Type == "NS" && r.GetLabel() == "@" {
|
||||
if !strings.HasSuffix(r.GetTargetField(), "registrar-servers.com.") {
|
||||
fmt.Println("\n", r.GetTargetField(), "Namecheap does not support changing apex NS records. Skipping.")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -150,13 +149,13 @@ func (n *Namecheap) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Cor
|
|||
continue
|
||||
}
|
||||
rec := &models.RecordConfig{
|
||||
NameFQDN: dnsutil.AddOrigin(r.Name, dc.Name),
|
||||
Type: r.Type,
|
||||
Target: r.Address,
|
||||
TTL: uint32(r.TTL),
|
||||
MxPreference: uint16(r.MXPref),
|
||||
Original: r,
|
||||
}
|
||||
rec.SetLabel(r.Name, dc.Name)
|
||||
rec.SetTarget(r.Address)
|
||||
actual = append(actual, rec)
|
||||
}
|
||||
|
||||
|
@ -204,12 +203,11 @@ func (n *Namecheap) generateRecords(dc *models.DomainConfig) error {
|
|||
|
||||
id := 1
|
||||
for _, r := range dc.Records {
|
||||
name := dnsutil.TrimDomainName(r.NameFQDN, dc.Name)
|
||||
rec := nc.DomainDNSHost{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Name: r.GetLabel(),
|
||||
Type: r.Type,
|
||||
Address: r.Target,
|
||||
Address: r.GetTargetField(),
|
||||
MXPref: int(r.MxPreference),
|
||||
TTL: int(r.TTL),
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import (
|
|||
"github.com/namedotcom/go/namecom"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
)
|
||||
|
@ -76,7 +74,7 @@ func (n *NameCom) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Corre
|
|||
func checkNSModifications(dc *models.DomainConfig) {
|
||||
newList := make([]*models.RecordConfig, 0, len(dc.Records))
|
||||
for _, rec := range dc.Records {
|
||||
if rec.Type == "NS" && rec.NameFQDN == dc.Name {
|
||||
if rec.Type == "NS" && rec.GetLabel() == "@" {
|
||||
continue // Apex NS records are automatically created for the domain's nameservers and cannot be managed otherwise via the name.com API.
|
||||
}
|
||||
newList = append(newList, rec)
|
||||
|
@ -147,9 +145,9 @@ func (n *NameCom) getRecords(domain string) ([]*namecom.Record, error) {
|
|||
func (n *NameCom) createRecord(rc *models.RecordConfig, domain string) error {
|
||||
record := &namecom.Record{
|
||||
DomainName: domain,
|
||||
Host: dnsutil.TrimDomainName(rc.NameFQDN, domain),
|
||||
Host: rc.GetLabel(),
|
||||
Type: rc.Type,
|
||||
Answer: rc.Target,
|
||||
Answer: rc.GetTargetField(),
|
||||
TTL: rc.TTL,
|
||||
Priority: uint32(rc.MxPreference),
|
||||
}
|
||||
|
@ -159,7 +157,7 @@ func (n *NameCom) createRecord(rc *models.RecordConfig, domain string) error {
|
|||
case "TXT":
|
||||
record.Answer = encodeTxt(rc.TxtStrings)
|
||||
case "SRV":
|
||||
record.Answer = fmt.Sprintf("%d %d %v", rc.SrvWeight, rc.SrvPort, rc.Target)
|
||||
record.Answer = fmt.Sprintf("%d %d %v", rc.SrvWeight, rc.SrvPort, rc.GetTargetField())
|
||||
record.Priority = uint32(rc.SrvPriority)
|
||||
default:
|
||||
panic(fmt.Sprintf("createRecord rtype %v unimplemented", rc.Type))
|
||||
|
|
|
@ -178,7 +178,7 @@ func parseLeaf(results models.Records, k string, v interface{}, origin string) (
|
|||
case "port": // SRV
|
||||
newRc.SrvPort = uint16(v4.(int))
|
||||
case "value": // MX
|
||||
newRc.Target = v4.(string)
|
||||
newRc.SetTarget(v4.(string))
|
||||
}
|
||||
}
|
||||
//fmt.Printf("parseLeaf: append %v\n", newRc)
|
||||
|
|
|
@ -56,7 +56,9 @@ func TestYamlWrite(t *testing.T) {
|
|||
m.AddFunc("json", minjson.Minify)
|
||||
|
||||
t.Run(f.Name(), func(t *testing.T) {
|
||||
content, err := ioutil.ReadFile(filepath.Join(testDir, f.Name()))
|
||||
fname := filepath.Join(testDir, f.Name())
|
||||
fmt.Printf("Filename: %v\n", fname)
|
||||
content, err := ioutil.ReadFile(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -48,14 +48,14 @@ func (z *genYamlData) Less(i, j int) bool {
|
|||
case "NS", "TXT", "TLSA":
|
||||
// pass through.
|
||||
case "A":
|
||||
ta2, tb2 := net.ParseIP(a.Target), net.ParseIP(b.Target)
|
||||
ta2, tb2 := net.ParseIP(a.GetTargetField()), net.ParseIP(b.GetTargetField())
|
||||
ipa, ipb := ta2.To4(), tb2.To4()
|
||||
if ipa == nil || ipb == nil {
|
||||
log.Fatalf("should not happen: IPs are not 4 bytes: %#v %#v", ta2, tb2)
|
||||
}
|
||||
return bytes.Compare(ipa, ipb) == -1
|
||||
case "AAAA":
|
||||
ta2, tb2 := net.ParseIP(a.Target), net.ParseIP(b.Target)
|
||||
ta2, tb2 := net.ParseIP(a.GetTargetField()), net.ParseIP(b.GetTargetField())
|
||||
ipa, ipb := ta2.To16(), tb2.To16()
|
||||
return bytes.Compare(ipa, ipb) == -1
|
||||
case "MX":
|
||||
|
@ -75,7 +75,7 @@ func (z *genYamlData) Less(i, j int) bool {
|
|||
return pa < pb
|
||||
}
|
||||
case "PTR":
|
||||
pa, pb := a.Target, b.Target
|
||||
pa, pb := a.GetTargetField(), b.GetTargetField()
|
||||
if pa != pb {
|
||||
return pa < pb
|
||||
}
|
||||
|
|
|
@ -28,8 +28,9 @@ func WriteYaml(w io.Writer, records models.Records, origin string) error {
|
|||
recsCopy = append(recsCopy, r)
|
||||
}
|
||||
for _, r := range recsCopy {
|
||||
if r.Name == "@" {
|
||||
r.Name = ""
|
||||
if r.GetLabel() == "@" {
|
||||
//r.Name = ""
|
||||
r.UnsafeSetLabelNull()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +157,7 @@ func sameType(records models.Records) bool {
|
|||
func oneLabel(records models.Records) yaml.MapItem {
|
||||
item := yaml.MapItem{
|
||||
// a yaml.MapItem is a YAML map that retains the key order.
|
||||
Key: records[0].Name,
|
||||
Key: records[0].GetLabel(),
|
||||
}
|
||||
// Special case labels with a single record:
|
||||
if len(records) == 1 {
|
||||
|
|
|
@ -112,7 +112,7 @@ func (c *ovhProvider) deleteRecordFunc(id int64, fqdn string) func() error {
|
|||
func (c *ovhProvider) createRecordFunc(rc *models.RecordConfig, fqdn string) func() error {
|
||||
return func() error {
|
||||
record := Record{
|
||||
SubDomain: dnsutil.TrimDomainName(rc.NameFQDN, fqdn),
|
||||
SubDomain: dnsutil.TrimDomainName(rc.GetLabelFQDN(), fqdn),
|
||||
FieldType: rc.Type,
|
||||
Target: rc.GetTargetCombined(),
|
||||
TTL: rc.TTL,
|
||||
|
@ -130,7 +130,7 @@ func (c *ovhProvider) createRecordFunc(rc *models.RecordConfig, fqdn string) fun
|
|||
func (c *ovhProvider) updateRecordFunc(old *Record, rc *models.RecordConfig, fqdn string) func() error {
|
||||
return func() error {
|
||||
record := Record{
|
||||
SubDomain: dnsutil.TrimDomainName(rc.NameFQDN, fqdn),
|
||||
SubDomain: rc.GetLabel(),
|
||||
FieldType: rc.Type,
|
||||
Target: rc.GetTargetCombined(),
|
||||
TTL: rc.TTL,
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/softlayer/softlayer-go/datatypes"
|
||||
|
@ -129,10 +128,10 @@ func (s *SoftLayer) getExistingRecords(domain *datatypes.Dns_Domain) ([]*models.
|
|||
|
||||
recConfig := &models.RecordConfig{
|
||||
Type: recType,
|
||||
Target: *record.Data,
|
||||
TTL: uint32(*record.Ttl),
|
||||
Original: record,
|
||||
}
|
||||
recConfig.SetTarget(*record.Data)
|
||||
|
||||
switch recType {
|
||||
case "SRV":
|
||||
|
@ -153,21 +152,16 @@ func (s *SoftLayer) getExistingRecords(domain *datatypes.Dns_Domain) ([]*models.
|
|||
if record.Service != nil {
|
||||
service = *record.Service
|
||||
}
|
||||
|
||||
recConfig.Name = fmt.Sprintf("%s.%s", service, strings.ToLower(protocol))
|
||||
|
||||
recConfig.SetLabel(fmt.Sprintf("%s.%s", service, strings.ToLower(protocol)), *domain.Name)
|
||||
case "MX":
|
||||
if record.MxPriority != nil {
|
||||
recConfig.MxPreference = uint16(*record.MxPriority)
|
||||
}
|
||||
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
recConfig.Name = *record.Host
|
||||
recConfig.SetLabel(*record.Host, *domain.Name)
|
||||
}
|
||||
|
||||
recConfig.NameFQDN = dnsutil.AddOrigin(recConfig.Name, *domain.Name)
|
||||
actual = append(actual, recConfig)
|
||||
}
|
||||
|
||||
|
@ -180,7 +174,7 @@ func (s *SoftLayer) getExistingRecords(domain *datatypes.Dns_Domain) ([]*models.
|
|||
func (s *SoftLayer) createRecordFunc(desired *models.RecordConfig, domain *datatypes.Dns_Domain) func() error {
|
||||
var ttl, preference, domainID int = int(desired.TTL), int(desired.MxPreference), *domain.Id
|
||||
var weight, priority, port int = int(desired.SrvWeight), int(desired.SrvPriority), int(desired.SrvPort)
|
||||
var host, data, newType string = desired.Name, desired.Target, desired.Type
|
||||
var host, data, newType string = desired.GetLabel(), desired.GetTargetField(), desired.Type
|
||||
var err error
|
||||
|
||||
srvRegexp := regexp.MustCompile(`^_(?P<Service>\w+)\.\_(?P<Protocol>\w+)$`)
|
||||
|
@ -260,13 +254,15 @@ func (s *SoftLayer) updateRecordFunc(existing *datatypes.Dns_Domain_ResourceReco
|
|||
service := services.GetDnsDomainResourceRecordMxTypeService(s.Session)
|
||||
updated := datatypes.Dns_Domain_ResourceRecord_MxType{}
|
||||
|
||||
if desired.Name != *existing.Host {
|
||||
updated.Host = &desired.Name
|
||||
label := desired.GetLabel()
|
||||
if label != *existing.Host {
|
||||
updated.Host = &label
|
||||
changes = true
|
||||
}
|
||||
|
||||
if desired.Target != *existing.Data {
|
||||
updated.Data = &desired.Target
|
||||
target := desired.GetTargetField()
|
||||
if target != *existing.Data {
|
||||
updated.Data = &target
|
||||
changes = true
|
||||
}
|
||||
|
||||
|
@ -290,13 +286,15 @@ func (s *SoftLayer) updateRecordFunc(existing *datatypes.Dns_Domain_ResourceReco
|
|||
service := services.GetDnsDomainResourceRecordSrvTypeService(s.Session)
|
||||
updated := datatypes.Dns_Domain_ResourceRecord_SrvType{}
|
||||
|
||||
if desired.Name != *existing.Host {
|
||||
updated.Host = &desired.Name
|
||||
label := desired.GetLabel()
|
||||
if label != *existing.Host {
|
||||
updated.Host = &label
|
||||
changes = true
|
||||
}
|
||||
|
||||
if desired.Target != *existing.Data {
|
||||
updated.Data = &desired.Target
|
||||
target := desired.GetTargetField()
|
||||
if target != *existing.Data {
|
||||
updated.Data = &target
|
||||
changes = true
|
||||
}
|
||||
|
||||
|
@ -333,13 +331,15 @@ func (s *SoftLayer) updateRecordFunc(existing *datatypes.Dns_Domain_ResourceReco
|
|||
service := services.GetDnsDomainResourceRecordService(s.Session)
|
||||
updated := datatypes.Dns_Domain_ResourceRecord{}
|
||||
|
||||
if desired.Name != *existing.Host {
|
||||
updated.Host = &desired.Name
|
||||
label := desired.GetLabel()
|
||||
if label != *existing.Host {
|
||||
updated.Host = &label
|
||||
changes = true
|
||||
}
|
||||
|
||||
if desired.Target != *existing.Data {
|
||||
updated.Data = &desired.Target
|
||||
target := desired.GetTargetField()
|
||||
if target != *existing.Data {
|
||||
updated.Data = &target
|
||||
changes = true
|
||||
}
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ func toRecordConfig(dc *models.DomainConfig, r *vultr.DNSRecord) (*models.Record
|
|||
|
||||
// toVultrRecord converts a RecordConfig converted by toRecordConfig back to a Vultr DNSRecord #rtype_variations
|
||||
func toVultrRecord(dc *models.DomainConfig, rc *models.RecordConfig) *vultr.DNSRecord {
|
||||
name := dnsutil.TrimDomainName(rc.NameFQDN, dc.Name)
|
||||
name := rc.GetLabel()
|
||||
// Vultr uses a blank string to represent the apex domain
|
||||
if name == "@" {
|
||||
name = ""
|
||||
|
@ -267,17 +267,16 @@ func toVultrRecord(dc *models.DomainConfig, rc *models.RecordConfig) *vultr.DNSR
|
|||
TTL: int(rc.TTL),
|
||||
Priority: priority,
|
||||
}
|
||||
|
||||
if rc.Type == "SRV" {
|
||||
target := rc.Target
|
||||
switch rtype := rc.Type; rtype { // #rtype_variations
|
||||
case "SRV":
|
||||
target := rc.GetTargetField()
|
||||
if strings.HasSuffix(target, ".") {
|
||||
target = target[:len(target)-1]
|
||||
}
|
||||
r.Data = fmt.Sprintf("%v %v %s", rc.SrvWeight, rc.SrvPort, target)
|
||||
}
|
||||
|
||||
if rc.Type == "CAA" {
|
||||
case "CAA":
|
||||
r.Data = fmt.Sprintf(`%v %s "%s"`, rc.CaaFlag, rc.CaaTag, rc.GetTargetField())
|
||||
default:
|
||||
}
|
||||
|
||||
return r
|
||||
|
|
Loading…
Add table
Reference in a new issue