1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

PERFORMANCE: Refactor auditrecords.go to loop only once #1570 (#1658)

* stash

* Use rejectif idea

* rename

* wip!

* Convert old systems to new

* fixup!

* fix typo
This commit is contained in:
Tom Limoncelli
2022-08-11 17:24:47 -04:00
committed by GitHub
parent 443b99aa59
commit 31723ad146
52 changed files with 497 additions and 569 deletions

View File

@ -1047,7 +1047,7 @@ func makeTests(t *testing.T) []*TestGroup {
tc("CAA change flag", caa("@", "issuewild", 128, "example.com")), tc("CAA change flag", caa("@", "issuewild", 128, "example.com")),
), ),
testgroup("CAA with ;", testgroup("CAA with ;",
requires(providers.CanUseCAA), not("DIGITALOCEAN"), requires(providers.CanUseCAA),
// Test support of ";" as a value // Test support of ";" as a value
tc("CAA many records", caa("@", "issuewild", 0, ";")), tc("CAA many records", caa("@", "issuewild", 0, ";")),
), ),

View File

@ -485,8 +485,10 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
// be performed. // be performed.
continue continue
} }
if err := providers.AuditRecords(provider.ProviderBase.ProviderType, domain.Records); err != nil { if es := providers.AuditRecords(provider.ProviderBase.ProviderType, domain.Records); len(es) != 0 {
errs = append(errs, fmt.Errorf("%s rejects domain %s: %w", provider.ProviderBase.ProviderType, domain.Name, err)) for _, e := range es {
errs = append(errs, fmt.Errorf("%s rejects domain %s: %w", provider.ProviderBase.ProviderType, domain.Name, e))
}
} }
} }
} }

View File

@ -153,6 +153,7 @@ func (z *ZoneGenData) generateZoneFileHelper(w io.Writer) error {
return nil return nil
} }
// FormatLine formats a zonefile line.
func FormatLine(lengths []int, fields []string) string { func FormatLine(lengths []int, fields []string) string {
c := 0 c := 0
result := "" result := ""

View File

@ -411,7 +411,7 @@ zt.mup IN A 1.2.3.14
zap IN A 1.2.3.15 zap IN A 1.2.3.15
` `
// func formatLine // func FormatLine
func TestFormatLine(t *testing.T) { func TestFormatLine(t *testing.T) {
tests := []struct { tests := []struct {

View File

@ -1,159 +0,0 @@
package recordaudit
import (
"fmt"
"strings"
"github.com/StackExchange/dnscontrol/v3/models"
)
// Keep these in alphabetical order.
// TxtNoBackticks audits TXT records for strings that contain backticks.
func TxtNoBackticks(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() {
for _, txt := range rc.TxtStrings {
if strings.Contains(txt, "`") {
return fmt.Errorf("txtstring contains backtick")
}
}
}
}
return nil
}
// TxtNoSingleQuotes audits TXT records for strings that contain single-quotes.
func TxtNoSingleQuotes(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() {
for _, txt := range rc.TxtStrings {
if strings.Contains(txt, "'") {
return fmt.Errorf("txtstring contains single-quotes")
}
}
}
}
return nil
}
// TxtNoDoubleQuotes audits TXT records for strings that contain doublequotes.
func TxtNoDoubleQuotes(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() {
for _, txt := range rc.TxtStrings {
if strings.Contains(txt, `"`) {
return fmt.Errorf("txtstring contains doublequotes")
}
}
}
}
return nil
}
// TxtNoStringsExactlyLen255 audits TXT records for strings exactly 255 octets long.
// This is rare; you probably want to use TxtNoLongStrings() instead.
func TxtNoStringsExactlyLen255(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() { // TXT and similar:
for _, txt := range rc.TxtStrings {
if len(txt) == 255 {
return fmt.Errorf("txtstring length is 255")
}
}
}
}
return nil
}
// TxtNoStringsLen256orLonger audits TXT records for strings that are >255 octets.
func TxtNoStringsLen256orLonger(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() { // TXT and similar:
for _, txt := range rc.TxtStrings {
if len(txt) > 255 {
return fmt.Errorf("%q txtstring length > 255", rc.GetLabel())
}
}
}
}
return nil
}
// TxtNoMultipleStrings audits TXT records for multiple strings
func TxtNoMultipleStrings(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() { // TXT and similar:
if len(rc.TxtStrings) > 1 {
return fmt.Errorf("multiple strings in one txt")
}
}
}
return nil
}
// TxtNoTrailingSpace audits TXT records for strings that end with space.
func TxtNoTrailingSpace(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() { // TXT and similar:
for _, txt := range rc.TxtStrings {
if txt != "" && txt[ultimate(txt)] == ' ' {
return fmt.Errorf("txtstring ends with space")
}
}
}
}
return nil
}
// TxtNotEmpty audits TXT records for empty strings.
func TxtNotEmpty(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() { // TXT and similar:
// There must be strings.
if len(rc.TxtStrings) == 0 {
return fmt.Errorf("txt with no strings")
}
// Each string must be non-empty.
for _, txt := range rc.TxtStrings {
if len(txt) == 0 {
return fmt.Errorf("txtstring is empty")
}
}
}
}
return nil
}
// TxtNoUnpairedDoubleQuotes audits TXT records for strings that contain unpaired doublequotes.
func TxtNoUnpairedDoubleQuotes(records []*models.RecordConfig) error {
for _, rc := range records {
if rc.HasFormatIdenticalToTXT() {
for _, txt := range rc.TxtStrings {
if strings.Count(txt, `"`)%2 == 1 {
return fmt.Errorf("txtstring contains unpaired doublequotes")
}
}
}
}
return nil
}

46
pkg/rejectif/audit.go Normal file
View File

@ -0,0 +1,46 @@
package rejectif
import (
"github.com/StackExchange/dnscontrol/v3/models"
)
// Auditor stores a list of checks to be executed during Audit().
type Auditor struct {
checksFor map[string][]checker
}
type checker = func(*models.RecordConfig) error
// Add registers a function to call on each record of a given type.
func (aud *Auditor) Add(rtype string, fn checker) {
if aud.checksFor == nil {
aud.checksFor = map[string][]checker{}
}
aud.checksFor[rtype] = append(aud.checksFor[rtype], fn)
// SPF records get any checkers that TXT records do.
if rtype == "TXT" {
aud.Add("SPF", fn)
}
}
// Audit performs the audit. For each record it calls each function in
// the list of checks.
func (aud *Auditor) Audit(records models.Records) (errs []error) {
// No checks? Exit early.
if aud.checksFor == nil {
return nil
}
// For each record, call the checks for that type, gather errors.
for _, rc := range records {
for _, f := range aud.checksFor[rc.Type] {
e := f(rc)
if e != nil {
errs = append(errs, e)
}
}
}
return errs
}

18
pkg/rejectif/caa.go Normal file
View File

@ -0,0 +1,18 @@
package rejectif
import (
"fmt"
"strings"
"github.com/StackExchange/dnscontrol/v3/models"
)
// Keep these in alphabetical order.
// CaaTargetHasSemicolon audits CAA records for issues that contain semicolons.
func CaaTargetHasSemicolon(rc *models.RecordConfig) error {
if strings.Contains(rc.GetTargetField(), ";") {
return fmt.Errorf("caa target contains semicolon")
}
return nil
}

104
pkg/rejectif/txt.go Normal file
View File

@ -0,0 +1,104 @@
package rejectif
import (
"fmt"
"strings"
"github.com/StackExchange/dnscontrol/v3/models"
)
// Keep these in alphabetical order.
// TxtHasBackticks audits TXT records for strings that contain backticks.
func TxtHasBackticks(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if strings.Contains(txt, "`") {
return fmt.Errorf("txtstring contains backtick")
}
}
return nil
}
// TxtHasSingleQuotes audits TXT records for strings that contain single-quotes.
func TxtHasSingleQuotes(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if strings.Contains(txt, "'") {
return fmt.Errorf("txtstring contains single-quotes")
}
}
return nil
}
// TxtHasDoubleQuotes audits TXT records for strings that contain doublequotes.
func TxtHasDoubleQuotes(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if strings.Contains(txt, `"`) {
return fmt.Errorf("txtstring contains doublequotes")
}
}
return nil
}
// TxtIsExactlyLen255 audits TXT records for strings exactly 255 octets long.
// This is rare; you probably want to use TxtNoStringsLen256orLonger() instead.
func TxtIsExactlyLen255(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if len(txt) == 255 {
return fmt.Errorf("txtstring length is 255")
}
}
return nil
}
// TxtHasSegmentLen256orLonger audits TXT records for strings that are >255 octets.
func TxtHasSegmentLen256orLonger(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if len(txt) > 255 {
return fmt.Errorf("%q txtstring length > 255", rc.GetLabel())
}
}
return nil
}
// TxtHasMultipleSegments audits TXT records for multiple strings
func TxtHasMultipleSegments(rc *models.RecordConfig) error {
if len(rc.TxtStrings) > 1 {
return fmt.Errorf("multiple strings in one txt")
}
return nil
}
// TxtHasTrailingSpace audits TXT records for strings that end with space.
func TxtHasTrailingSpace(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if txt != "" && txt[ultimate(txt)] == ' ' {
return fmt.Errorf("txtstring ends with space")
}
}
return nil
}
// TxtIsEmpty audits TXT records for empty strings.
func TxtIsEmpty(rc *models.RecordConfig) error {
// There must be strings.
if len(rc.TxtStrings) == 0 {
return fmt.Errorf("txt with no strings")
}
// Each string must be non-empty.
for _, txt := range rc.TxtStrings {
if len(txt) == 0 {
return fmt.Errorf("txtstring is empty")
}
}
return nil
}
// TxtHasUnpairedDoubleQuotes audits TXT records for strings that contain unpaired doublequotes.
func TxtHasUnpairedDoubleQuotes(rc *models.RecordConfig) error {
for _, txt := range rc.TxtStrings {
if strings.Count(txt, `"`)%2 == 1 {
return fmt.Errorf("txtstring contains unpaired doublequotes")
}
}
return nil
}

View File

@ -1,4 +1,4 @@
package recordaudit package rejectif
/* /*
I proposed that Go add something like "len()" that returns the highest I proposed that Go add something like "len()" that returns the highest

View File

@ -2,7 +2,9 @@ package akamaiedgedns
import "github.com/StackExchange/dnscontrol/v3/models" import "github.com/StackExchange/dnscontrol/v3/models"
// AuditRecords returns an error if any records are not supportable by this provider. // AuditRecords returns a list of errors corresponding to the records
func AuditRecords(records []*models.RecordConfig) error { // that aren't supported by this provider. If all records are
// supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
) )
// ZoneListFilter describes a JSON list filter.
type ZoneListFilter struct { type ZoneListFilter struct {
Key string `json:"key"` Key string `json:"key"`
Value string `json:"value"` Value string `json:"value"`
@ -20,6 +21,7 @@ type ZoneListFilter struct {
Filter []*ZoneListFilter `json:"filters,omitempty"` Filter []*ZoneListFilter `json:"filters,omitempty"`
} }
// ZoneListRequest describes a JSON zone list request.
type ZoneListRequest struct { type ZoneListRequest struct {
Filter []*ZoneListFilter `json:"filters"` Filter []*ZoneListFilter `json:"filters"`
} }
@ -27,11 +29,11 @@ type ZoneListRequest struct {
func (api *autoDnsProvider) request(method string, requestPath string, data interface{}) ([]byte, error) { func (api *autoDnsProvider) request(method string, requestPath string, data interface{}) ([]byte, error) {
client := &http.Client{} client := &http.Client{}
requestUrl := api.baseURL requestURL := api.baseURL
requestUrl.Path = api.baseURL.Path + requestPath requestURL.Path = api.baseURL.Path + requestPath
request := &http.Request{ request := &http.Request{
URL: &requestUrl, URL: &requestURL,
Header: api.defaultHeaders, Header: api.defaultHeaders,
Method: method, Method: method,
} }
@ -50,7 +52,7 @@ func (api *autoDnsProvider) request(method string, requestPath string, data inte
responseText, _ := ioutil.ReadAll(response.Body) responseText, _ := ioutil.ReadAll(response.Body)
if response.StatusCode != 200 { if response.StatusCode != 200 {
return nil, errors.New("Request to " + requestUrl.Path + " failed: " + string(responseText)) return nil, errors.New("Request to " + requestURL.Path + " failed: " + string(responseText))
} }
return responseText, nil return responseText, nil

View File

@ -2,8 +2,9 @@ package autodns
import "github.com/StackExchange/dnscontrol/v3/models" import "github.com/StackExchange/dnscontrol/v3/models"
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package axfrddns package axfrddns
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package azuredns package azuredns
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package bind package bind
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,24 +2,20 @@ package cloudflare
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2022-06-18
return err
} // Still needed as of 2022-06-18
if err := recordaudit.TxtNoTrailingSpace(records); err != nil { a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified 2022-06-18
return err
} // Still needed as of 2022-06-18
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2022-06-18
return err
} // Still needed as of 2022-06-18
return nil return a.Audit(records)
} }

View File

@ -2,36 +2,24 @@ package cloudns
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNoBackticks(records); err != nil { a.Add("TXT", rejectif.TxtHasBackticks) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoTrailingSpace(records); err != nil { a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoDoubleQuotes(records); err != nil { a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-11
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2021-03-01
return err
}
return nil return a.Audit(records)
} }

View File

@ -2,39 +2,34 @@ package cscglobal
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
// Each test should be encapsulated in a function that can be tested a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2022-06-10
// individually. If the test is of general use, add it to the
// recordaudit module.
// Each test should document the last time we verified the test was a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified 2022-06-10
// still needed. Sometimes companies change their API.
if err := recordaudit.TxtNoDoubleQuotes(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2022-06-10
return err
} // Needed as of 2022-08-08
// if err := recordaudit.TxtNoStringsLen256orLonger(records); err != nil { a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2022-08-08
// return err
// } // Needed as of 2022-06-10
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { return a.Audit(records)
return err
} // Needed as of 2022-06-10
if err := recordaudit.TxtNoTrailingSpace(records); err != nil {
return err
} // Needed as of 2022-06-10
if err := recordaudit.TxtNotEmpty(records); err != nil {
return err
} // Needed as of 2022-06-10
return nil
} }
/* How To Write Providers:
Each test should be encapsulated in a function that can be tested
individually. If the test is of general use, add it to the
rejectif module.
The "Last verified" comment logs the last time we verified this
test was needed. Sometimes companies change their API. Once a year,
try removing tests one at a time to verify they are still needed.
*/

View File

@ -4,8 +4,9 @@ import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,37 +2,32 @@ package digitalocean
import ( import (
"fmt" "fmt"
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
// TODO(tlim): Audit CAA records. a.Add("TXT", MaxLengthDO) // Last verified 2021-03-01
// "Semicolons not supported in issue/issuewild fields.", "https://www.digitalocean.com/docs/networking/dns/how-to/create-caa-records"),
// Users are warned about these limits in docs/_providers/digitalocean.md
if err := MaxLengthDO(records); err != nil { a.Add("CAA", rejectif.CaaTargetHasSemicolon) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2021-03-01
// Double-quotes not permitted in TXT strings. I have a hunch that // Double-quotes not permitted in TXT strings. I have a hunch that
// this is due to a broken parser on the DO side. // this is due to a broken parser on the DO side.
if err := recordaudit.TxtNoDoubleQuotes(records); err != nil {
return err
}
// Still needed as of 2021-03-01
return nil return a.Audit(records)
} }
// MaxLengthDO returns and error if the strings are longer than // MaxLengthDO returns and error if the string is longer than
// permitted by DigitalOcean. Sadly their length limit is // permitted by DigitalOcean. Sadly their length limit is
// undocumented. This is a guess. // undocumented. This is a guess.
func MaxLengthDO(records []*models.RecordConfig) error { func MaxLengthDO(rc *models.RecordConfig) error {
// The total length of all strings can't be longer than 512; and in // The total length of all strings can't be longer than 512; and in
// reality must be shorter due to sloppy validation checks. // reality must be shorter due to sloppy validation checks.
// https://github.com/StackExchange/dnscontrol/issues/370 // https://github.com/StackExchange/dnscontrol/issues/370
@ -47,14 +42,10 @@ func MaxLengthDO(records []*models.RecordConfig) error {
// In other words, they're doing the checking on the API protocol // In other words, they're doing the checking on the API protocol
// encoded data instead of on on the resulting TXT record. Sigh. // encoded data instead of on on the resulting TXT record. Sigh.
for _, rc := range records { if len(rc.GetTargetField()) > 509 {
return fmt.Errorf("encoded txt too long")
if rc.HasFormatIdenticalToTXT() { // TXT and similar:
if len(rc.GetTargetField()) > 509 {
return fmt.Errorf("encoded txt too long")
}
}
} }
// FIXME(tlim): Try replacing GetTargetField() with (2 + (3*len(rc.TxtStrings) - 1))
return nil return nil
} }

View File

@ -2,28 +2,23 @@ package dnsimple
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2022-07
//TODO(onlyhavecans) I think we can support multiple strings. //TODO(onlyhavecans) I think we can support multiple strings.
if err := recordaudit.TxtNoMultipleStrings(records); err != nil {
return err
}
if err := recordaudit.TxtNoTrailingSpace(records); err != nil { a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified 2022-07
return err
} // as of 2022-07
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2022-07
return err
} // as of 2022-07
if err := recordaudit.TxtNoUnpairedDoubleQuotes(records); err != nil { a.Add("TXT", rejectif.TxtHasUnpairedDoubleQuotes) // Last verified 2022-07
return err
} // as of 2022-07
return nil return a.Audit(records)
} }

View File

@ -2,16 +2,16 @@ package dnsmadeeasy
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
if err := recordaudit.TxtNoDoubleQuotes(records); err != nil { func AuditRecords(records []*models.RecordConfig) []error {
return err a := rejectif.Auditor{}
}
// Still needed as of 2021-03-11
return nil a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2021-03-11
return a.Audit(records)
} }

View File

@ -1,11 +1,10 @@
package doh package doh
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -0,0 +1,10 @@
package domainnameshop
import "github.com/StackExchange/dnscontrol/v3/models"
// AuditRecords returns a list of errors corresponding to the records
// that aren't supported by this provider. If all records are
// supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil
}

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/providers" "github.com/StackExchange/dnscontrol/v3/providers"
) )
@ -46,7 +45,7 @@ var features = providers.DocumentationNotes{
func init() { func init() {
fns := providers.DspFuncs{ fns := providers.DspFuncs{
Initializer: newDomainNameShopProvider, Initializer: newDomainNameShopProvider,
RecordAuditor: auditRecords, RecordAuditor: AuditRecords,
} }
providers.RegisterDomainServiceProviderType("DOMAINNAMESHOP", fns, features) providers.RegisterDomainServiceProviderType("DOMAINNAMESHOP", fns, features)
@ -69,10 +68,6 @@ func newDomainNameShopProvider(conf map[string]string, metadata json.RawMessage)
return api, nil return api, nil
} }
func auditRecords(records []*models.RecordConfig) error {
return nil
}
type domainResponse struct { type domainResponse struct {
ID int `json:"id"` ID int `json:"id"`
Domain string `json:"domain"` Domain string `json:"domain"`

View File

@ -1,11 +1,10 @@
package exoscale package exoscale
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package gandiv5 package gandiv5
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package gcloud package gcloud
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package hedns package hedns
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package hetzner package hetzner
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,17 +2,16 @@ package hexonet
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-10-01
return err
}
// Still needed as of 2021-10-01
return nil return a.Audit(records)
} }

View File

@ -1,11 +1,10 @@
package hostingde package hostingde
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package internetbs package internetbs
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,32 +2,22 @@ package inwx
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNoBackticks(records); err != nil { a.Add("TXT", rejectif.TxtHasBackticks) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoStringsExactlyLen255(records); err != nil { a.Add("TXT", rejectif.TxtIsExactlyLen255) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoTrailingSpace(records); err != nil { a.Add("TXT", rejectif.TxtHasTrailingSpace) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
return nil return a.Audit(records)
} }

View File

@ -1,11 +1,10 @@
package linode package linode
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,41 +2,26 @@ package msdns
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { a.Add("TXT", rejectif.TxtHasBackticks) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoStringsLen256orLonger(records); err != nil { a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2021-03-01
return err
}
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtHasMultipleSegments) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoBackticks(records); err != nil { a.Add("TXT", rejectif.TxtHasSingleQuotes) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoDoubleQuotes(records); err != nil { a.Add("TXT", rejectif.TxtHasSegmentLen256orLonger)
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNoSingleQuotes(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
return nil return a.Audit(records)
} }

View File

@ -1,11 +1,10 @@
package namecheap package namecheap
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -5,49 +5,41 @@ import (
"strings" "strings"
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := MaxLengthNDC(records); err != nil { a.Add("TXT", MaxLengthNDC) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-03-01
return err
}
// Still needed as of 2021-03-01
return nil return a.Audit(records)
} }
// MaxLengthNDC returns and error if the sum of the strings // MaxLengthNDC returns and error if the sum of the strings
// are longer than permitted by NDC. Sadly their // are longer than permitted by NDC. Sadly their
// length limit is undocumented. This seems to work. // length limit is undocumented. This seems to work.
func MaxLengthNDC(records []*models.RecordConfig) error { func MaxLengthNDC(rc *models.RecordConfig) error {
for _, rc := range records { if len(rc.TxtStrings) == 0 {
return nil
}
if rc.HasFormatIdenticalToTXT() { // TXT and similar: sum := 2 // Count the start and end quote.
// Sum the length of the segments: // Add the length of each segment.
sum := 0 for _, segment := range rc.TxtStrings {
for _, segment := range rc.TxtStrings { sum += len(segment) // The length of each segment
sum += len(segment) // The length of each segment sum += strings.Count(segment, `"`) // Add 1 for any char to be escaped
sum += strings.Count(segment, `"`) // Add 1 for any char to be escaped }
} // Add 3 (quote space quote) for each interior join.
// Add the overhead of quoting them: sum += 3 * (len(rc.TxtStrings) - 1)
n := len(rc.TxtStrings)
if n > 0 {
sum += 2 + 3*(n-1) // Start and end double-quotes, plus `" "` between each segment.
}
if sum > 512 {
return fmt.Errorf("encoded txt too long")
}
}
if sum > 512 {
return fmt.Errorf("encoded txt too long")
} }
return nil return nil
} }

View File

@ -2,12 +2,16 @@ package netcup
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
return recordaudit.TxtNotEmpty(records) func AuditRecords(records []*models.RecordConfig) []error {
// Still needed as of 2021-03-01 a := rejectif.Auditor{}
a.Add("TXT", rejectif.TxtIsEmpty) // Last verified 2021-03-01
return a.Audit(records)
} }

View File

@ -2,17 +2,16 @@ package ns1
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { a.Add("TXT", rejectif.TxtHasMultipleSegments)
return err
}
// Still needed as of 2021-03-01
return nil return a.Audit(records)
} }

View File

@ -1,11 +1,10 @@
package octodns package octodns
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package opensrs package opensrs
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package oracle package oracle
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package ovh package ovh
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package packetframe package packetframe
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package powerdns package powerdns
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -41,9 +41,9 @@ var RegistrarTypes = map[string]RegistrarInitializer{}
type DspInitializer func(map[string]string, json.RawMessage) (DNSServiceProvider, error) type DspInitializer func(map[string]string, json.RawMessage) (DNSServiceProvider, error)
// RecordAuditor is a function that verifies that all the records // RecordAuditor is a function that verifies that all the records
// are supportable by this provider. It returns an error related to // are supportable by this provider. It returns a list of errors
// the first record that this provider can not support. // detailing records that this provider can not support.
type RecordAuditor func([]*models.RecordConfig) error type RecordAuditor func([]*models.RecordConfig) []error
// DspFuncs lists functions registered with a provider. // DspFuncs lists functions registered with a provider.
type DspFuncs struct { type DspFuncs struct {
@ -132,13 +132,13 @@ func beCompatible(n string, config map[string]string) (string, error) {
} }
// AuditRecords calls the RecordAudit function for a provider. // AuditRecords calls the RecordAudit function for a provider.
func AuditRecords(dType string, rcs models.Records) error { func AuditRecords(dType string, rcs models.Records) []error {
p, ok := DNSProviderTypes[dType] p, ok := DNSProviderTypes[dType]
if !ok { if !ok {
return fmt.Errorf("unknown DNS service provider type: %q", dType) return []error{fmt.Errorf("unknown DNS service provider type: %q", dType)}
} }
if p.RecordAuditor == nil { if p.RecordAuditor == nil {
return fmt.Errorf("DNS service provider type %q has no RecordAuditor", dType) return []error{fmt.Errorf("DNS service provider type %q has no RecordAuditor", dType)}
} }
return p.RecordAuditor(rcs) return p.RecordAuditor(rcs)
} }

View File

@ -1,11 +1,10 @@
package route53 package route53
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,24 +2,20 @@ package rwth
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { a.Add("TXT", rejectif.TxtHasMultipleSegments)
return err
}
if err := recordaudit.TxtNoTrailingSpace(records); err != nil { a.Add("TXT", rejectif.TxtHasTrailingSpace)
return err
}
if err := recordaudit.TxtNotEmpty(records); err != nil { a.Add("TXT", rejectif.TxtIsEmpty)
return err
}
return nil return a.Audit(records)
} }

View File

@ -1,11 +1,10 @@
package softlayer package softlayer
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -1,11 +1,10 @@
package transip package transip
import ( import "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/models"
)
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
return nil return nil
} }

View File

@ -2,23 +2,20 @@ package vultr
import ( import (
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
"github.com/StackExchange/dnscontrol/v3/pkg/recordaudit" "github.com/StackExchange/dnscontrol/v3/pkg/rejectif"
) )
// AuditRecords returns an error if any records are not // AuditRecords returns a list of errors corresponding to the records
// supportable by this provider. // that aren't supported by this provider. If all records are
func AuditRecords(records []*models.RecordConfig) error { // supported, an empty list is returned.
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}
// TODO(tlim) Needs investigation. Could be a dnscontrol issue or a.Add("TXT", rejectif.TxtHasDoubleQuotes) // Last verified 2021-03-02
// Needs investigation. Could be a dnscontrol issue or
// the provider doesn't support double quotes. // the provider doesn't support double quotes.
if err := recordaudit.TxtNoDoubleQuotes(records); err != nil {
return err
}
// Still needed as of 2021-03-02
if err := recordaudit.TxtNoMultipleStrings(records); err != nil { a.Add("TXT", rejectif.TxtHasMultipleSegments)
return err
}
return nil return a.Audit(records)
} }