CHORE: Fix lint warnings from golangci-lint (#3311)

This commit is contained in:
Tom Limoncelli 2025-01-13 11:33:12 -05:00 committed by GitHub
parent b5b2873c62
commit 5dbe5e84c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
235 changed files with 1774 additions and 1589 deletions

View file

@ -68,6 +68,5 @@ func generateDTSFile(funcs string) error {
fileContent += strings.TrimRight(line, " \t") + "\n"
}
fileContent = strings.TrimRight(fileContent, "\n")
os.WriteFile(join("commands", "types", "dnscontrol.d.ts"), []byte(fileContent+"\n"), 0644)
return nil
return os.WriteFile(join("commands", "types", "dnscontrol.d.ts"), []byte(fileContent+"\n"), 0o644)
}

View file

@ -13,7 +13,6 @@ import (
func generateFeatureMatrix() error {
matrix := matrixData()
markdownTable, err := markdownTable(matrix)
if err != nil {
return err
}
@ -45,7 +44,7 @@ func markdownTable(matrix *FeatureMatrix) (string, error) {
tableData = append(tableData, tableDataRow)
}
var markdownTable, err = markdown.NewTableFormatterBuilder().
markdownTable, err := markdown.NewTableFormatterBuilder().
Build(tableHeaders...).
Format(tableData)
if err != nil {
@ -123,7 +122,7 @@ func matrixData() *FeatureMatrix {
DomainModifierDnskey,
DualHost,
CreateDomains,
//NoPurge,
// NoPurge,
GetZones,
},
}
@ -346,7 +345,7 @@ func replaceInlineContent(
contentBytes = []byte(content)
contentBytes = append(contentBytes[:start], append(newContentBytes, contentBytes[end+len(endMarker):]...)...)
err = os.WriteFile(file, contentBytes, 0644)
err = os.WriteFile(file, contentBytes, 0o644)
if err != nil {
panic(err)
}

View file

@ -64,7 +64,7 @@ func readDocFile(fPath string) (map[string]interface{}, string, error) {
func parseFrontMatter(content string) (map[string]interface{}, string, error) {
delimiterIndices := delimiterRegex.FindAllStringIndex(content, 2)
if len(delimiterIndices) < 1 {
return nil, "", fmt.Errorf("failed to parse file. Remove it and try again")
return nil, "", errors.New("failed to parse file. Remove it and try again")
}
startIndex := delimiterIndices[0][0]
endIndex := delimiterIndices[1][0]
@ -126,7 +126,6 @@ func generateFunctionTypes() (string, error) {
if err != nil {
println("Error parsing front matter in", fPath, "error: ", err.Error())
continue
}
if frontMatter["ts_ignore"] == true {
continue

View file

@ -1,10 +1,11 @@
package main
import (
"github.com/StackExchange/dnscontrol/v4/providers"
"os"
"sort"
"strings"
"github.com/StackExchange/dnscontrol/v4/providers"
)
func generateOwnersFile() error {

View file

@ -11,9 +11,8 @@ import (
"github.com/StackExchange/dnscontrol/v4/pkg/diff2"
"github.com/StackExchange/dnscontrol/v4/pkg/js"
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
"github.com/urfave/cli/v2"
"github.com/fatih/color"
"github.com/urfave/cli/v2"
)
// categories of commands
@ -165,7 +164,7 @@ func GetDNSConfig(args GetDNSConfigArgs) (*models.DNSConfig, error) {
// convenient access patterns. Does everything we need to prepare for the validation phase, but
// cannot do anything that requires the credentials file yet.
func preloadProviders(cfg *models.DNSConfig) (*models.DNSConfig, error) {
//build name to type maps
// build name to type maps
cfg.RegistrarsByName = map[string]*models.RegistrarConfig{}
cfg.DNSProvidersByName = map[string]*models.DNSProviderConfig{}
for _, reg := range cfg.Registrars {

View file

@ -30,7 +30,9 @@ func shellCompletionCommand() *cli.Command {
BashComplete: func(ctx *cli.Context) {
for _, shell := range supportedShells {
if strings.HasPrefix(shell, ctx.Args().First()) {
ctx.App.Writer.Write([]byte(shell + "\n"))
if _, err := ctx.App.Writer.Write([]byte(shell + "\n")); err != nil {
panic(err)
}
}
}
},

View file

@ -3,14 +3,13 @@ package commands
import (
"bytes"
"fmt"
"slices"
"strings"
"testing"
"text/template"
"github.com/google/go-cmp/cmp"
"github.com/urfave/cli/v2"
"golang.org/x/exp/slices"
)
type shellTestDataItem struct {
@ -99,7 +98,7 @@ func TestShellCompletionCommand(t *testing.T) {
t.Fatal("expected error, but didn't get one")
}
want := fmt.Sprintf("unknown shell: %s", invalidShellTestDataItem.shellName)
want := "unknown shell: " + invalidShellTestDataItem.shellName
got := strings.TrimSpace(appErrWriterBuffer.String())
if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
@ -153,7 +152,7 @@ func TestShellCompletionCommand(t *testing.T) {
t.Fatal("expected error, but didn't get one")
}
want := fmt.Sprintf("unknown shell: %s", invalidShellTestDataItem.shellPath)
want := "unknown shell: " + invalidShellTestDataItem.shellPath
got := strings.TrimSpace(appErrWriterBuffer.String())
if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
@ -230,7 +229,7 @@ func testHelperGetShellsAndCompletionScripts() ([]shellTestDataItem, error) {
shellsAndValues,
shellTestDataItem{
shellName: shellName,
shellPath: fmt.Sprintf("/bin/%s", shellName),
shellPath: "/bin/" + shellName,
completionScriptTemplate: t,
},
)

View file

@ -66,7 +66,7 @@ func FmtFile(args FmtArgs) error {
if args.OutputFile == "" {
fmt.Print(beautified)
} else {
if err := os.WriteFile(args.OutputFile, []byte(beautified), 0744); err != nil {
if err := os.WriteFile(args.OutputFile, []byte(beautified), 0o744); err != nil {
return err
}
fmt.Fprintf(os.Stderr, "File %s successfully written\n", args.OutputFile)

View file

@ -2,6 +2,7 @@ package commands
import (
"encoding/json"
"errors"
"fmt"
"os"
"regexp"
@ -129,10 +130,10 @@ func GetCerts(args GetCertsArgs) error {
fmt.Println(args.JSFile)
// check agree flag
if !args.AgreeTOS {
return fmt.Errorf("you must agree to the Let's Encrypt Terms of Service by using -agreeTOS")
return errors.New("you must agree to the Let's Encrypt Terms of Service by using -agreeTOS")
}
if args.Email == "" {
return fmt.Errorf("must provide email to use for Let's Encrypt registration")
return errors.New("must provide email to use for Let's Encrypt registration")
}
// load dns config
@ -142,7 +143,7 @@ func GetCerts(args GetCertsArgs) error {
}
errs := normalize.ValidateAndNormalizeConfig(cfg)
if PrintValidationErrors(errs) {
return fmt.Errorf("exiting due to validation errors")
return errors.New("exiting due to validation errors")
}
providerConfigs, err := credsfile.LoadProviderConfigs(args.CredsFile)
if err != nil {
@ -170,7 +171,7 @@ func GetCerts(args GetCertsArgs) error {
return err
}
if len(certList) == 0 {
return fmt.Errorf("must provide at least one certificate to issue in cert configuration")
return errors.New("must provide at least one certificate to issue in cert configuration")
}
if err = validateCertificateList(certList, cfg); err != nil {
return err
@ -207,7 +208,7 @@ func GetCerts(args GetCertsArgs) error {
if manyerr == nil {
manyerr = err
} else {
manyerr = fmt.Errorf("%w; %v", manyerr, err)
manyerr = fmt.Errorf("%w; %w", manyerr, err)
}
}
}

View file

@ -26,7 +26,7 @@ var _ = cmd(catUtils, func() *cli.Command {
args.CredName = ctx.Args().Get(0)
arg1 := ctx.Args().Get(1)
args.ProviderName = arg1
// In v4.0, skip the first args.ZoneNames if it it equals "-".
// In v4.0, skip the first args.ZoneNames if it equals "-".
args.ZoneNames = ctx.Args().Slice()[2:]
if arg1 != "" && arg1 != "-" {
@ -212,7 +212,6 @@ func GetZone(args GetZoneArgs) error {
dspVariableName := "DSP_" + strings.ToUpper(args.CredName)
if args.OutputFormat == "js" || args.OutputFormat == "djs" {
if args.ProviderName == "-" {
fmt.Fprintf(w, `var %s = NewDnsProvider("%s");`+"\n",
dspVariableName, args.CredName)
@ -229,10 +228,11 @@ func GetZone(args GetZoneArgs) error {
z := prettyzone.PrettySort(recs, zoneName, 0, nil)
switch args.OutputFormat {
case "zone":
fmt.Fprintf(w, "$ORIGIN %s.\n", zoneName)
prettyzone.WriteZoneFileRC(w, z.Records, zoneName, uint32(args.DefaultTTL), nil)
if err := prettyzone.WriteZoneFileRC(w, z.Records, zoneName, uint32(args.DefaultTTL), nil); err != nil {
return err
}
fmt.Fprintln(w)
case "js", "djs":
@ -281,7 +281,6 @@ func GetZone(args GetZoneArgs) error {
case "tsv":
for _, rec := range recs {
cfproxy := ""
if cp, ok := rec.Metadata["cloudflare_proxy"]; ok {
if cp == "true" {
@ -315,7 +314,6 @@ func jsonQuoted(i string) string {
}
func formatDsl(rec *models.RecordConfig, defaultTTL uint32) string {
target := rec.GetTargetCombined()
ttl := uint32(0)

View file

@ -32,7 +32,7 @@ func testFormat(t *testing.T, domain, format string) {
expectedFilename := fmt.Sprintf("test_data/%s.zone.%s", domain, format)
outputFiletmpl := fmt.Sprintf("%s.zone.%s.*.txt", domain, format)
outfile, err := os.CreateTemp("", outputFiletmpl)
outfile, err := os.CreateTemp(t.TempDir(), outputFiletmpl)
if err != nil {
log.Fatal(fmt.Errorf("gz can't TempFile %q: %w", outputFiletmpl, err))
}
@ -68,7 +68,7 @@ func testFormat(t *testing.T, domain, format string) {
if w, g := string(want), string(got); w != g {
// If the test fails, output a file showing "got"
err = os.WriteFile(expectedFilename+".ACTUAL", got, 0644)
err = os.WriteFile(expectedFilename+".ACTUAL", got, 0o644)
if err != nil {
log.Fatal(err)
}

View file

@ -3,6 +3,7 @@ package commands
import (
"cmp"
"encoding/json"
"errors"
"fmt"
"os"
"strings"
@ -88,7 +89,7 @@ type PPreviewArgs struct {
}
// ReportItem is a record of corrections for a particular domain/provider/registrar.
//type ReportItem struct {
// type ReportItem struct {
// Domain string `json:"domain"`
// Corrections int `json:"corrections"`
// Provider string `json:"provider,omitempty"`
@ -140,8 +141,8 @@ func (args *PPreviewArgs) flags() []cli.Flag {
Name: "reportmax",
Hidden: true,
Usage: `Limit the IGNORE/NO_PURGE report to this many lines (Expermental. Will change in the future.)`,
Action: func(ctx *cli.Context, max int) error {
printer.MaxReport = max
Action: func(ctx *cli.Context, maxreport int) error {
printer.MaxReport = maxreport
return nil
},
})
@ -220,7 +221,6 @@ var pobsoleteDiff2FlagUsed = false
// run is the main routine common to preview/push
func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, report string) error {
// This is a hack until we have the new printer replacement.
printer.SkinnyReport = !args.Full
fullMode := args.Full
@ -250,7 +250,7 @@ func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, repor
out.PrintfIf(fullMode, "Normalizing and validating 'desired'..\n")
errs := normalize.ValidateAndNormalizeConfig(cfg)
if PrintValidationErrors(errs) {
return fmt.Errorf("exiting due to validation errors")
return errors.New("exiting due to validation errors")
}
zcache := NewZoneCache()
@ -312,7 +312,6 @@ func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, repor
reportItems = append(reportItems, genReportItem(zone.Name, corrections, zone.RegistrarName))
anyErrors = cmp.Or(anyErrors, pprintOrRunCorrections(zone.Name, zone.RegistrarInstance.Name, corrections, out, push, interactive, notifier, report))
}
}
if os.Getenv("TEAMCITY_VERSION") != "" {
@ -323,18 +322,18 @@ func prun(args PPreviewArgs, push bool, interactive bool, out printer.CLI, repor
out.Printf("Done. %d corrections.\n", totalCorrections)
err = writeReport(report, reportItems)
if err != nil {
return fmt.Errorf("could not write report")
return errors.New("could not write report")
}
if anyErrors {
return fmt.Errorf("completed with errors")
return errors.New("completed with errors")
}
if totalCorrections != 0 && args.WarnChanges {
return fmt.Errorf("there are pending changes")
return errors.New("there are pending changes")
}
return nil
}
//func countActions(corrections []*models.Correction) int {
// func countActions(corrections []*models.Correction) int {
// r := 0
// for _, c := range corrections {
// if c.F != nil {
@ -382,12 +381,12 @@ func splitConcurrent(domains []*models.DomainConfig, filter string) (serial []*m
// concurrency. Otherwise false is returned.
func allConcur(dc *models.DomainConfig) bool {
if !providers.ProviderHasCapability(dc.RegistrarInstance.ProviderType, providers.CanConcur) {
//fmt.Printf("WHY? %q: %+v\n", dc.Name, dc.RegistrarInstance)
// fmt.Printf("WHY? %q: %+v\n", dc.Name, dc.RegistrarInstance)
return false
}
for _, p := range dc.DNSProviderInstances {
if !providers.ProviderHasCapability(p.ProviderType, providers.CanConcur) {
//fmt.Printf("WHY? %q: %+v\n", dc.Name, p)
// fmt.Printf("WHY? %q: %+v\n", dc.Name, p)
return false
}
}
@ -421,7 +420,6 @@ func oneZone(zone *models.DomainConfig, args PPreviewArgs, zc *zoneCache) {
// Loop over the (selected) providers configured for that zone:
providersToProcess := whichProvidersToProcess(zone.DNSProviderInstances, args.Providers)
for _, provider := range providersToProcess {
// Populate the zones at the provider (if desired/needed/able):
if !args.NoPopulate {
populateCorrections := generatePopulateCorrections(provider, zone.Name, zc)
@ -441,7 +439,6 @@ func oneZone(zone *models.DomainConfig, args PPreviewArgs, zc *zoneCache) {
}
func whichProvidersToProcess(providers []*models.DNSProviderInstance, filter string) []*models.DNSProviderInstance {
if filter == "all" { // all
return providers
}
@ -477,7 +474,6 @@ func skipProvider(name string, providers []*models.DNSProviderInstance) bool {
}
func genReportItem(zname string, corrections []*models.Correction, pname string) *ReportItem {
// Only count the actions, not the messages.
cnt := 0
for _, cor := range corrections {
@ -502,7 +498,6 @@ func pprintOrRunCorrections(zoneName string, providerName string, corrections []
cc := 0
cn := 0
for _, correction := range corrections {
// Print what we're about to do.
if correction.F == nil {
out.PrintReport(cn, correction)
@ -514,7 +509,6 @@ func pprintOrRunCorrections(zoneName string, providerName string, corrections []
var err error
if push {
// If interactive, ask "are you sure?" and skip if not.
if interactive && !out.PromptToRun() {
continue
@ -542,7 +536,7 @@ func writeReport(report string, reportItems []*ReportItem) error {
return nil
}
f, err := os.OpenFile(report, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
f, err := os.OpenFile(report, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644)
if err != nil {
return err
}
@ -558,7 +552,6 @@ func writeReport(report string, reportItems []*ReportItem) error {
}
func generatePopulateCorrections(provider *models.DNSProviderInstance, zoneName string, zcache *zoneCache) []*models.Correction {
lister, ok := provider.Driver.(providers.ZoneLister)
if !ok {
return nil // We can't generate a list. No corrections are possible.
@ -595,7 +588,7 @@ func generateZoneCorrections(zone *models.DomainConfig, provider *models.DNSProv
}
func generateDelegationCorrections(zone *models.DomainConfig, providers []*models.DNSProviderInstance, _ *models.RegistrarInstance) ([]*models.Correction, int) {
//fmt.Printf("DEBUG: generateDelegationCorrections start zone=%q nsList = %v\n", zone.Name, zone.Nameservers)
// fmt.Printf("DEBUG: generateDelegationCorrections start zone=%q nsList = %v\n", zone.Name, zone.Nameservers)
nsList, err := nameservers.DetermineNameserversForProviders(zone, providers, true)
if err != nil {
return msg(fmt.Sprintf("DetermineNS: zone %q; Error: %s", zone.Name, err)), 0
@ -645,7 +638,7 @@ func PInitializeProviders(cfg *models.DNSConfig, providerConfigs map[string]map[
fmt.Fprintln(os.Stderr, strings.Join(msgs, "\n"))
}
if err != nil {
return
return notify, err
}
registrars := map[string]providers.Registrar{}
@ -674,7 +667,7 @@ func PInitializeProviders(cfg *models.DNSConfig, providerConfigs map[string]map[
pInst.IsDefault = !isNonDefault[pInst.Name]
}
}
return
return notify, err
}
// pproviderTypeFieldName is the name of the field in creds.json that specifies the provider type id.
@ -765,7 +758,6 @@ func puniqueStrings(stringSlice []string) []string {
}
func prefineProviderType(credEntryName string, t string, credFields map[string]string, source string) (replacementType string, warnMsg string, err error) {
// t="" and t="-" are processed the same. Standardize on "-" to reduce the number of cases to check.
if t == "" {
t = "-"
@ -778,7 +770,7 @@ func prefineProviderType(credEntryName string, t string, credFields map[string]s
// - or "" GANDI lookup worked. Nothing to say.
// - or "" - or "" ERROR "creds.json has invalid or missing data"
// GANDI "" WARNING "Working but.... Please fix as follows..."
// GANDI GANDI INFO "working but unneeded: clean up as follows..."
// GANDI INFO "working but unneeded: clean up as follows..."
// GANDI NAMEDOT ERROR "error mismatched: please fix as follows..."
// ERROR: Invalid.
@ -869,5 +861,4 @@ func prefineProviderType(credEntryName string, t string, credFields map[string]s
// use the value in creds.json (this should be the normal case)
return ct, "", nil
}
}

View file

@ -2,13 +2,12 @@ package commands
import (
"encoding/json"
"errors"
"fmt"
"os"
"strings"
"sync"
"golang.org/x/net/idna"
"github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/credsfile"
"github.com/StackExchange/dnscontrol/v4/pkg/nameservers"
@ -19,6 +18,7 @@ import (
"github.com/StackExchange/dnscontrol/v4/pkg/zonerecs"
"github.com/StackExchange/dnscontrol/v4/providers"
"golang.org/x/exp/slices"
"golang.org/x/net/idna"
)
// ReportItem is a record of corrections for a particular domain/provider/registrar.
@ -67,7 +67,7 @@ func run(args PPreviewArgs, push bool, interactive bool, out printer.CLI, report
errs := normalize.ValidateAndNormalizeConfig(cfg)
if PrintValidationErrors(errs) {
return fmt.Errorf("exiting due to validation errors")
return errors.New("exiting due to validation errors")
}
anyErrors := false
totalCorrections := 0
@ -112,8 +112,8 @@ func run(args PPreviewArgs, push bool, interactive bool, out printer.CLI, report
aceZoneName, _ := idna.ToASCII(domain.Name)
if !slices.Contains(zones, aceZoneName) {
//out.Warnf("DEBUG: zones: %v\n", zones)
//out.Warnf("DEBUG: Name: %v\n", domain.Name)
// out.Warnf("DEBUG: zones: %v\n", zones)
// out.Warnf("DEBUG: Name: %v\n", domain.Name)
out.Warnf("Zone '%s' does not exist in the '%s' profile and will be added automatically.\n", domain.Name, provider.Name)
continue // continue with next provider, as we can not determine corrections without an existing zone
@ -141,7 +141,6 @@ func run(args PPreviewArgs, push bool, interactive bool, out printer.CLI, report
nameservers.AddNSRecords(domain)
for _, provider := range providersWithExistingZone {
shouldrun := args.shouldRunProvider(provider.Name, domain)
out.StartDNSProvider(provider.Name, !shouldrun)
if !shouldrun {
@ -199,13 +198,13 @@ func run(args PPreviewArgs, push bool, interactive bool, out printer.CLI, report
notifier.Done()
out.Printf("Done. %d corrections.\n", totalCorrections)
if anyErrors {
return fmt.Errorf("completed with errors")
return errors.New("completed with errors")
}
if totalCorrections != 0 && args.WarnChanges {
return fmt.Errorf("there are pending changes")
return errors.New("there are pending changes")
}
if report != nil && *report != "" {
f, err := os.OpenFile(*report, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
f, err := os.OpenFile(*report, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644)
if err != nil {
return err
}
@ -245,7 +244,7 @@ func InitializeProviders(cfg *models.DNSConfig, providerConfigs map[string]map[s
fmt.Fprintln(os.Stderr, strings.Join(msgs, "\n"))
}
if err != nil {
return
return notify, err
}
registrars := map[string]providers.Registrar{}
@ -274,7 +273,7 @@ func InitializeProviders(cfg *models.DNSConfig, providerConfigs map[string]map[s
pInst.IsDefault = !isNonDefault[pInst.Name]
}
}
return
return notify, err
}
// providerTypeFieldName is the name of the field in creds.json that specifies the provider type id.
@ -364,7 +363,6 @@ func uniqueStrings(stringSlice []string) []string {
}
func refineProviderType(credEntryName string, t string, credFields map[string]string, source string) (replacementType string, warnMsg string, err error) {
// t="" and t="-" are processed the same. Standardize on "-" to reduce the number of cases to check.
if t == "" {
t = "-"
@ -377,7 +375,7 @@ func refineProviderType(credEntryName string, t string, credFields map[string]st
// - or "" GANDI lookup worked. Nothing to say.
// - or "" - or "" ERROR "creds.json has invalid or missing data"
// GANDI "" WARNING "Working but.... Please fix as follows..."
// GANDI GANDI INFO "working but unneeded: clean up as follows..."
// GANDI INFO "working but unneeded: clean up as follows..."
// GANDI NAMEDOT ERROR "error mismatched: please fix as follows..."
// ERROR: Invalid.
@ -468,7 +466,6 @@ func refineProviderType(credEntryName string, t string, credFields map[string]st
// use the value in creds.json (this should be the normal case)
return ct, "", nil
}
}
func printOrRunCorrections(domain string, provider string, corrections []*models.Correction, out printer.CLI, push bool, interactive bool, notifier notifications.Notifier) (anyErrors bool) {

View file

@ -6,7 +6,6 @@ import (
)
func Test_refineProviderType(t *testing.T) {
var mapEmpty map[string]string
mapTypeMissing := map[string]string{"otherfield": "othervalue"}
mapTypeFoo := map[string]string{"TYPE": "FOO"}

View file

@ -2,6 +2,7 @@ package commands
import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
@ -42,7 +43,6 @@ var _ = cmd(catDebug, func() *cli.Command {
Name: "check",
Usage: "Check and validate dnsconfig.js. Output to stdout. Do not access providers.",
Action: func(c *cli.Context) error {
// Create a PrintIRArgs struct and copy our args to the
// appropriate fields.
var pargs PrintIRArgs
@ -96,7 +96,7 @@ func PrintIR(args PrintIRArgs) error {
if !args.Raw {
errs := normalize.ValidateAndNormalizeConfig(cfg)
if PrintValidationErrors(errs) {
return fmt.Errorf("exiting due to validation errors")
return errors.New("exiting due to validation errors")
}
}
return PrintJSON(args.PrintJSONArgs, cfg)
@ -122,7 +122,7 @@ func PrintValidationErrors(errs []error) (fatal bool) {
// ExecuteDSL executes the dnsconfig.js contents.
func ExecuteDSL(args ExecuteDSLArgs) (*models.DNSConfig, error) {
if args.JSFile == "" {
return nil, fmt.Errorf("no config specified")
return nil, errors.New("no config specified")
}
dnsConfig, err := js.ExecuteJavaScript(args.JSFile, args.DevMode, stringSliceToMap(args.Variable))

View file

@ -13,7 +13,7 @@ func TestR53Test_1(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
w := `R53_ALIAS("foo", "A", "bar")`
@ -28,7 +28,7 @@ func TestR53Test_1ttl(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
w := `R53_ALIAS("foo", "A", "bar", TTL(321))`
@ -43,7 +43,7 @@ func TestR53Test_2(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
rec.R53Alias["zone_id"] = "blarg"
@ -59,7 +59,7 @@ func TestR53Test_2ttl(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
rec.R53Alias["zone_id"] = "blarg"
@ -75,7 +75,7 @@ func TestR53Test_3(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
rec.R53Alias["evaluate_target_health"] = "true"
@ -91,7 +91,7 @@ func TestR53Test_3ttl(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
rec.R53Alias["evaluate_target_health"] = "true"
@ -107,7 +107,7 @@ func TestR53Test_4(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
rec.R53Alias["zone_id"] = "blarg"
@ -124,7 +124,7 @@ func TestR53Test_4ttl(t *testing.T) {
Name: "foo",
NameFQDN: "foo.domain.tld",
}
rec.SetTarget("bar")
rec.MustSetTarget("bar")
rec.R53Alias = make(map[string]string)
rec.R53Alias["type"] = "A"
rec.R53Alias["zone_id"] = "blarg"

View file

@ -52,10 +52,18 @@ func WriteTypes(args TypesArgs) error {
}
defer file.Close()
file.WriteString("// This file was automatically generated by DNSControl. Do not edit it directly.\n")
file.WriteString("// To update it, run `dnscontrol write-types`.\n\n")
file.WriteString("// " + version + "\n")
file.WriteString(dtsContent)
if _, err := file.WriteString("// This file was automatically generated by DNSControl. Do not edit it directly.\n"); err != nil {
return err
}
if _, err := file.WriteString("// To update it, run `dnscontrol write-types`.\n\n"); err != nil {
return err
}
if _, err := file.WriteString("// " + version + "\n"); err != nil {
return err
}
if _, err := file.WriteString(dtsContent); err != nil {
return err
}
print("Successfully wrote " + args.DTSFile + "\n")
return nil

View file

@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"errors"
"flag"
"fmt"
"os"
@ -20,14 +21,16 @@ import (
"github.com/miekg/dns/dnsutil"
)
var providerFlag = flag.String("provider", "", "Provider to run (if empty, deduced from -profile)")
var profileFlag = flag.String("profile", "", "Entry in profiles.json to use (if empty, copied from -provider)")
var startIdx = flag.Int("start", -1, "Test number to begin with")
var endIdx = flag.Int("end", -1, "Test index to stop after")
var verbose = flag.Bool("verbose", false, "Print corrections as you run them")
var printElapsed = flag.Bool("elapsed", false, "Print elapsed time for each testgroup")
var enableCFWorkers = flag.Bool("cfworkers", true, "Set false to disable CF worker tests")
var enableCFRedirectMode = flag.String("cfredirect", "", "cloudflare pagerule tests: default=page_rules, c=convert old to enw, n=new-style, o=none")
var (
providerFlag = flag.String("provider", "", "Provider to run (if empty, deduced from -profile)")
profileFlag = flag.String("profile", "", "Entry in profiles.json to use (if empty, copied from -provider)")
startIdx = flag.Int("start", -1, "Test number to begin with")
endIdx = flag.Int("end", -1, "Test index to stop after")
verbose = flag.Bool("verbose", false, "Print corrections as you run them")
printElapsed = flag.Bool("elapsed", false, "Print elapsed time for each testgroup")
enableCFWorkers = flag.Bool("cfworkers", true, "Set false to disable CF worker tests")
enableCFRedirectMode = flag.String("cfredirect", "", "cloudflare pagerule tests: default=page_rules, c=convert old to enw, n=new-style, o=none")
)
func init() {
testing.Init()
@ -47,6 +50,12 @@ func CfCProxyFull() *TestCase { return tc("cproxyf", cfProxyCNAME("cproxy", "exa
// ---
func panicOnErr(err error) {
if err != nil {
panic(err)
}
}
func getProvider(t *testing.T) (providers.DNSServiceProvider, string, map[string]string) {
if *providerFlag == "" && *profileFlag == "" {
t.Log("No -provider or -profile specified")
@ -97,7 +106,7 @@ func getProvider(t *testing.T) (providers.DNSServiceProvider, string, map[string
*providerFlag = profileType
}
//fmt.Printf("DEBUG flag=%q Profile=%q TYPE=%q\n", *providerFlag, profileName, profileType)
// fmt.Printf("DEBUG flag=%q Profile=%q TYPE=%q\n", *providerFlag, profileName, profileType)
fmt.Printf("Testing Profile=%q TYPE=%q\n", profileName, profileType)
var metadata json.RawMessage
@ -152,7 +161,6 @@ func TestDNSProviders(t *testing.T) {
t.Run(domain, func(t *testing.T) {
runTests(t, provider, domain, cfg)
})
}
func getDomainConfigWithNameservers(t *testing.T, prv providers.DNSServiceProvider, domainName string) *models.DomainConfig {
@ -174,10 +182,9 @@ func getDomainConfigWithNameservers(t *testing.T, prv providers.DNSServiceProvid
// testPermitted returns nil if the test is permitted, otherwise an
// error explaining why it is not.
func testPermitted(p string, f TestGroup) error {
// not() and only() can't be mixed.
if len(f.only) != 0 && len(f.not) != 0 {
return fmt.Errorf("invalid filter: can't mix not() and only()")
return errors.New("invalid filter: can't mix not() and only()")
}
// TODO(tlim): Have a separate validation pass so that such mistakes
// are more visible?
@ -205,7 +212,7 @@ func testPermitted(p string, f TestGroup) error {
return nil
}
}
return fmt.Errorf("disabled by only")
return errors.New("disabled by only")
}
// If there are any "not" items, you must NOT be one of them.
@ -238,7 +245,7 @@ func makeChanges(t *testing.T, prv providers.DNSServiceProvider, dc *models.Doma
if strings.Contains(rc.GetLabelFQDN(), "**current-domain**") {
rc.SetLabelFromFQDN(strings.Replace(rc.GetLabelFQDN(), "**current-domain**", domainName, 1), domainName)
}
//if providers.ProviderHasCapability(*providerToRun, providers.CanUseAzureAlias) {
// if providers.ProviderHasCapability(*providerToRun, providers.CanUseAzureAlias) {
if strings.Contains(rc.GetTargetField(), "**subscription-id**") {
_ = rc.SetTarget(strings.Replace(rc.GetTargetField(), "**subscription-id**", origConfig["SubscriptionID"], 1))
}
@ -315,7 +322,6 @@ func makeChanges(t *testing.T, prv providers.DNSServiceProvider, dc *models.Doma
}
t.FailNow()
}
})
}
@ -334,7 +340,6 @@ func runTests(t *testing.T, prv providers.DNSServiceProvider, domainName string,
curGroup := -1
for gIdx, group := range testGroups {
// Abide by -start -end flags
curGroup++
if curGroup < firstGroup || curGroup > lastGroup {
@ -342,9 +347,9 @@ func runTests(t *testing.T, prv providers.DNSServiceProvider, domainName string,
}
// Abide by filter
//fmt.Printf("DEBUG testPermitted: prov=%q profile=%q\n", *providerFlag, *profileFlag)
// fmt.Printf("DEBUG testPermitted: prov=%q profile=%q\n", *providerFlag, *profileFlag)
if err := testPermitted(*profileFlag, *group); err != nil {
//t.Logf("%s: ***SKIPPED(%v)***", group.Desc, err)
// t.Logf("%s: ***SKIPPED(%v)***", group.Desc, err)
makeChanges(t, prv, dc, tc("Empty"), fmt.Sprintf("%02d:%s ***SKIPPED(%v)***", gIdx, group.Desc, err), false, origConfig)
continue
}
@ -356,7 +361,6 @@ func runTests(t *testing.T, prv providers.DNSServiceProvider, domainName string,
start := time.Now()
for _, tst := range group.tests {
// TODO(tlim): This is the old version. It skipped the remaining tc() statements if one failed.
// The new code continues to test the remaining tc() statements. Keeping this as a comment
// in case we ever want to do something similar.
@ -368,16 +372,13 @@ func runTests(t *testing.T, prv providers.DNSServiceProvider, domainName string,
if ok := makeChanges(t, prv, dc, tst, fmt.Sprintf("%02d:%s", gIdx, group.Desc), true, origConfig); !ok {
break
}
}
elapsed := time.Since(start)
if *printElapsed {
fmt.Printf("ELAPSED %02d %7.2f %q\n", gIdx, elapsed.Seconds(), group.Desc)
}
}
}
func TestDualProviders(t *testing.T) {
@ -474,7 +475,7 @@ func TestNameserverDots(t *testing.T) {
t.Run("No trailing dot in nameserver", func(t *testing.T) {
for _, nameserver := range dc.Nameservers {
//fmt.Printf("DEBUG: nameserver.Name = %q\n", nameserver.Name)
// fmt.Printf("DEBUG: nameserver.Name = %q\n", nameserver.Name)
if strings.HasSuffix(nameserver.Name, ".") {
t.Errorf("Provider returned nameserver with trailing dot: %q", nameserver)
}
@ -543,7 +544,7 @@ func azureAlias(name, aliasType, target string) *models.RecordConfig {
func caa(name string, tag string, flag uint8, target string) *models.RecordConfig {
r := makeRec(name, target, "CAA")
r.SetTargetCAA(flag, tag, target)
panicOnErr(r.SetTargetCAA(flag, tag, target))
return r
}
@ -567,10 +568,7 @@ func cfSingleRedirectEnabled() bool {
func cfSingleRedirect(name string, code any, when, then string) *models.RecordConfig {
r := makeRec("@", name, cfsingleredirect.SINGLEREDIRECT)
err := cfsingleredirect.FromRaw(r, []any{name, code, when, then})
if err != nil {
panic("Should not happen... cfSingleRedirect")
}
panicOnErr(cfsingleredirect.FromRaw(r, []any{name, code, when, then})) // Should not happen
return r
}
@ -606,13 +604,13 @@ func dname(name, target string) *models.RecordConfig {
func ds(name string, keyTag uint16, algorithm, digestType uint8, digest string) *models.RecordConfig {
r := makeRec(name, "", "DS")
r.SetTargetDS(keyTag, algorithm, digestType, digest)
panicOnErr(r.SetTargetDS(keyTag, algorithm, digestType, digest))
return r
}
func dnskey(name string, flags uint16, protocol, algorithm uint8, publicKey string) *models.RecordConfig {
r := makeRec(name, "", "DNSKEY")
r.SetTargetDNSKEY(flags, protocol, algorithm, publicKey)
panicOnErr(r.SetTargetDNSKEY(flags, protocol, algorithm, publicKey))
return r
}
@ -644,9 +642,10 @@ func ignore(labelSpec string, typeSpec string, targetSpec string) *models.Record
}
func loc(name string, d1 uint8, m1 uint8, s1 float32, ns string,
d2 uint8, m2 uint8, s2 float32, ew string, al float32, sz float32, hp float32, vp float32) *models.RecordConfig {
d2 uint8, m2 uint8, s2 float32, ew string, al float32, sz float32, hp float32, vp float32,
) *models.RecordConfig {
r := makeRec(name, "", "LOC")
r.SetLOCParams(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp)
panicOnErr(r.SetLOCParams(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp))
return r
}
@ -656,13 +655,13 @@ func makeRec(name, target, typ string) *models.RecordConfig {
TTL: 300,
}
SetLabel(r, name, "**current-domain**")
r.SetTarget(target)
r.MustSetTarget(target)
return r
}
func manyA(namePattern, target string, n int) []*models.RecordConfig {
recs := []*models.RecordConfig{}
for i := 0; i < n; i++ {
for i := range n {
recs = append(recs, makeRec(fmt.Sprintf(namePattern, i), target, "A"))
}
return recs
@ -680,7 +679,7 @@ func ns(name, target string) *models.RecordConfig {
func naptr(name string, order uint16, preference uint16, flags string, service string, regexp string, target string) *models.RecordConfig {
r := makeRec(name, target, "NAPTR")
r.SetTargetNAPTR(order, preference, flags, service, regexp, target)
panicOnErr(r.SetTargetNAPTR(order, preference, flags, service, regexp, target))
return r
}
@ -699,19 +698,19 @@ func r53alias(name, aliasType, target, evalTargetHealth string) *models.RecordCo
func soa(name string, ns, mbox string, serial, refresh, retry, expire, minttl uint32) *models.RecordConfig {
r := makeRec(name, "", "SOA")
r.SetTargetSOA(ns, mbox, serial, refresh, retry, expire, minttl)
panicOnErr(r.SetTargetSOA(ns, mbox, serial, refresh, retry, expire, minttl))
return r
}
func srv(name string, priority, weight, port uint16, target string) *models.RecordConfig {
r := makeRec(name, target, "SRV")
r.SetTargetSRV(priority, weight, port, target)
panicOnErr(r.SetTargetSRV(priority, weight, port, target))
return r
}
func sshfp(name string, algorithm uint8, fingerprint uint8, target string) *models.RecordConfig {
r := makeRec(name, target, "SSHFP")
r.SetTargetSSHFP(algorithm, fingerprint, target)
panicOnErr(r.SetTargetSSHFP(algorithm, fingerprint, target))
return r
}
@ -738,7 +737,7 @@ func makeOvhNativeRecord(name, target, rType string) *models.RecordConfig {
r := makeRec(name, "", "TXT")
r.Metadata = make(map[string]string)
r.Metadata["create_ovh_native_record"] = rType
r.SetTarget(target)
r.MustSetTarget(target)
return r
}
@ -807,7 +806,7 @@ func tc(desc string, recs ...*models.RecordConfig) *TestCase {
func txt(name, target string) *models.RecordConfig {
r := makeRec(name, "", "TXT")
r.SetTargetTXT(target)
panicOnErr(r.SetTargetTXT(target))
return r
}
@ -819,7 +818,7 @@ func ttl(r *models.RecordConfig, t uint32) *models.RecordConfig {
func tlsa(name string, usage, selector, matchingtype uint8, target string) *models.RecordConfig {
r := makeRec(name, target, "TLSA")
r.SetTargetTLSA(usage, selector, matchingtype, target)
panicOnErr(r.SetTargetTLSA(usage, selector, matchingtype, target))
return r
}
@ -832,7 +831,7 @@ func porkbunUrlfwd(name, target, t, includePath, wildcard string) *models.Record
return r
}
func clear() *TestCase {
func tcEmptyZone() *TestCase {
return tc("Empty")
}
@ -871,7 +870,6 @@ func alltrue(f ...bool) alltrueFilter {
//
func makeTests() []*TestGroup {
sha256hash := strings.Repeat("0123456789abcdef", 4)
sha512hash := strings.Repeat("0123456789abcdef", 8)
reversedSha512 := strings.Repeat("fedcba9876543210", 8)
@ -906,12 +904,11 @@ func makeTests() []*TestGroup {
// whether or not a certain kind of record can be created and
// deleted.
// clear() is the same as tc("Empty"). It removes all records.
// Each testgroup() begins with clear() automagically. You do not
// have to include the clear() in each testgroup().
// emptyzone() is the same as tc("Empty"). It removes all records.
// Each testgroup() begins with tcEmptyZone() automagically. You do not
// have to include the tcEmptyZone() in each testgroup().
tests := []*TestGroup{
// START HERE
// Narrative: Hello friend! Are you adding a new DNS provider to
@ -1040,7 +1037,7 @@ func makeTests() []*TestGroup {
testgroup("ManyAtOnce",
tc("CreateManyAtLabel", a("www", "1.1.1.1"), a("www", "2.2.2.2"), a("www", "3.3.3.3")),
clear(),
tcEmptyZone(),
tc("Create an A record", a("www", "1.1.1.1")),
tc("Add at label1", a("www", "1.1.1.1"), a("www", "2.2.2.2")),
tc("Add at label2", a("www", "1.1.1.1"), a("www", "2.2.2.2"), a("www", "3.3.3.3")),
@ -1048,7 +1045,7 @@ func makeTests() []*TestGroup {
testgroup("manyTypesAtOnce",
tc("CreateManyTypesAtLabel", a("www", "1.1.1.1"), mx("testmx", 5, "foo.com."), mx("testmx", 100, "bar.com.")),
clear(),
tcEmptyZone(),
tc("Create an A record", a("www", "1.1.1.1")),
tc("Add Type At Label", a("www", "1.1.1.1"), mx("testmx", 5, "foo.com.")),
tc("Add Type At Label", a("www", "1.1.1.1"), mx("testmx", 5, "foo.com."), mx("testmx", 100, "bar.com.")),
@ -1286,7 +1283,7 @@ func makeTests() []*TestGroup {
tc("a 764-byte TXT", txt("foo764", strings.Repeat("G", 764))), // 255*3-1
tc("a 765-byte TXT", txt("foo765", strings.Repeat("H", 765))), // 255*3
tc("a 766-byte TXT", txt("foo766", strings.Repeat("J", 766))), // 255*3+1
//clear(),
// tcEmptyZone(),
tc("TXT with 1 single-quote", txt("foosq", "quo'te")),
tc("TXT with 1 backtick", txt("foobt", "blah`blah")),
@ -1301,14 +1298,14 @@ func makeTests() []*TestGroup {
tc("TXT with semicolon ws", txt("foosc2", `wssemi ; colon`)),
tc("TXT interior ws", txt("foosp", "with spaces")),
//tc("TXT leading ws", txt("foowsb", " leadingspace")),
// tc("TXT leading ws", txt("foowsb", " leadingspace")),
tc("TXT trailing ws", txt("foows1", "trailingws ")),
// Vultr syntax-checks TXT records with SPF contents.
tc("Create a TXT/SPF", txt("foo", "v=spf1 ip4:99.99.99.99 -all")),
// Nobody needs this and many APIs don't allow it.
//tc("Create TXT with frequently difficult characters", txt("fooex", `!^.*$@#%^&()([][{}{<></:;-_=+\`)),
// tc("Create TXT with frequently difficult characters", txt("fooex", `!^.*$@#%^&()([][{}{<></:;-_=+\`)),
),
testgroup("TXT backslashes",
@ -1352,7 +1349,7 @@ func makeTests() []*TestGroup {
),
tc("deleteOne",
a("foo", "1.2.3.4"),
//a("foo", "3.4.5.6"), // Delete
// a("foo", "3.4.5.6"), // Delete
),
tc("addOne",
a("foo", "1.2.3.4"),
@ -1380,7 +1377,7 @@ func makeTests() []*TestGroup {
tc("deleteOne",
a("bar", "1.2.3.4"),
a("foo", "2.3.4.5"),
//a("foo", "8.8.8.8"), // Delete
// a("foo", "8.8.8.8"), // Delete
mx("foo", 10, "foo.**current-domain**"),
mx("foo", 20, "bar.**current-domain**"),
),
@ -1444,7 +1441,7 @@ func makeTests() []*TestGroup {
"CLOUDFLAREAPI", // Infinite pagesize but due to slow speed, skipping.
"DIGITALOCEAN", // No paging. Why bother?
"DESEC", // Skip due to daily update limits.
//"CSCGLOBAL", // Doesn't page. Works fine. Due to the slow API we skip.
// "CSCGLOBAL", // Doesn't page. Works fine. Due to the slow API we skip.
"GANDI_V5", // Their API is so damn slow. We'll add it back as needed.
"HEDNS", // Doesn't page. Works fine. Due to the slow API we skip.
"HEXONET", // Doesn't page. Works fine. Due to the slow API we skip.
@ -1452,7 +1449,7 @@ func makeTests() []*TestGroup {
"MSDNS", // No paging done. No need to test.
"NAMEDOTCOM", // Their API is so damn slow. We'll add it back as needed.
"NS1", // Free acct only allows 50 records, therefore we skip
//"ROUTE53", // Batches up changes in pages.
// "ROUTE53", // Batches up changes in pages.
"TRANSIP", // Doesn't page. Works fine. Due to the slow API we skip.
"CNR", // Test beaks limits.
),
@ -1463,7 +1460,7 @@ func makeTests() []*TestGroup {
testgroup("pager601",
only(
//"AZURE_DNS", // Removed because it is too slow
// "AZURE_DNS", // Removed because it is too slow
//"CLOUDFLAREAPI", // Infinite pagesize but due to slow speed, skipping.
//"CSCGLOBAL", // Doesn't page. Works fine. Due to the slow API we skip.
//"DESEC", // Skip due to daily update limits.
@ -1479,7 +1476,7 @@ func makeTests() []*TestGroup {
testgroup("pager1201",
only(
//"AKAMAIEDGEDNS", // No paging done. No need to test.
// "AKAMAIEDGEDNS", // No paging done. No need to test.
//"AZURE_DNS", // Currently failing. See https://github.com/StackExchange/dnscontrol/issues/770
//"CLOUDFLAREAPI", // Fails with >1000 corrections. See https://github.com/StackExchange/dnscontrol/issues/1440
//"CSCGLOBAL", // Doesn't page. Works fine. Due to the slow API we skip.
@ -1537,20 +1534,20 @@ func makeTests() []*TestGroup {
// LOCation records. // No.47
testgroup("LOC",
requires(providers.CanUseLOC),
//42 21 54 N 71 06 18 W -24m 30m
// 42 21 54 N 71 06 18 W -24m 30m
tc("Single LOC record", loc("@", 42, 21, 54, "N", 71, 6, 18, "W", -24.05, 30, 0, 0)),
//42 21 54 N 71 06 18 W -24m 30m
// 42 21 54 N 71 06 18 W -24m 30m
tc("Update single LOC record", loc("@", 42, 21, 54, "N", 71, 6, 18, "W", -24.06, 30, 10, 0)),
tc("Multiple LOC records-create a-d modify apex", //create a-d, modify @
//42 21 54 N 71 06 18 W -24m 30m
tc("Multiple LOC records-create a-d modify apex", // create a-d, modify @
// 42 21 54 N 71 06 18 W -24m 30m
loc("@", 42, 21, 54, "N", 71, 6, 18, "W", -24, 30, 0, 0),
//42 21 43.952 N 71 5 6.344 W -24m 1m 200m
// 42 21 43.952 N 71 5 6.344 W -24m 1m 200m
loc("a", 42, 21, 43.952, "N", 71, 5, 6.344, "W", -24.33, 1, 200, 10),
//52 14 05 N 00 08 50 E 10m
// 52 14 05 N 00 08 50 E 10m
loc("b", 52, 14, 5, "N", 0, 8, 50, "E", 10.22, 0, 0, 0),
//32 7 19 S 116 2 25 E 10m
// 32 7 19 S 116 2 25 E 10m
loc("c", 32, 7, 19, "S", 116, 2, 25, "E", 10, 0, 0, 0),
//42 21 28.764 N 71 00 51.617 W -44m 2000m
// 42 21 28.764 N 71 00 51.617 W -44m 2000m
loc("d", 42, 21, 28.764, "N", 71, 0, 51.617, "W", -44, 2000, 0, 0),
),
),
@ -1590,7 +1587,7 @@ func makeTests() []*TestGroup {
// SOA
testgroup("SOA",
requires(providers.CanUseSOA),
clear(), // Extra clear required or only the first run passes.
tcEmptyZone(), // Required or only the first run passes.
tc("Create SOA record", soa("@", "kim.ns.cloudflare.com.", "dns.cloudflare.com.", 2037190000, 10000, 2400, 604800, 3600)),
tc("Modify SOA ns ", soa("@", "mmm.ns.cloudflare.com.", "dns.cloudflare.com.", 2037190000, 10000, 2400, 604800, 3600)),
tc("Modify SOA mbox ", soa("@", "mmm.ns.cloudflare.com.", "eee.cloudflare.com.", 2037190000, 10000, 2400, 604800, 3600)),
@ -1610,7 +1607,7 @@ func makeTests() []*TestGroup {
tc("Change Priority", srv("_sip._tcp", 52, 6, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
tc("Change Weight", srv("_sip._tcp", 52, 62, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
tc("Change Port", srv("_sip._tcp", 52, 62, 72, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
clear(),
tcEmptyZone(),
tc("Null Target", srv("_sip._tcp", 15, 65, 75, ".")),
),
@ -1713,7 +1710,7 @@ func makeTests() []*TestGroup {
ds("child", 63909, 3, 4, "EEC7FA02E6788DA889B2CE41D43D92F948AB126EDCF83B7037E73CE9531C8E7E45653ABBAA76C2D6E42F98316EDE599B"),
ns("child", "ns101.cloudns.net."),
),
//tc("modify field 2", ds("child", 65535, 254, 4, "0123456789ABCDEF")),
// tc("modify field 2", ds("child", 65535, 254, 4, "0123456789ABCDEF")),
tc("delete 1, create 1",
ds("another-child", 35632, 13, 4, "F5F32ABCA6B01AA7A9963012F90B7C8523A1D946185A3AD70B67F3C9F18E7312FA9DD6AB2F7D8382F789213DB173D429"),
ns("another-child", "ns101.cloudns.net."),
@ -1726,7 +1723,7 @@ func makeTests() []*TestGroup {
),
// in CLouDNS we must delete DS Record before deleting NS record
// should no longer be necessary, provider should handle order correctly
//tc("delete all DS",
// tc("delete all DS",
// ns("another-child", "ns101.cloudns.net."),
//),
),
@ -1938,12 +1935,12 @@ func makeTests() []*TestGroup {
// Removed these for speed. They tested if order matters,
// which it doesn't seem to. Re-add if needed.
clear(),
tcEmptyZone(),
tc("multipleA",
cfRedir("cnn.**current-domain-no-trailing**/*", "https://www.cnn.com/$1"),
cfRedir("msnbc.**current-domain-no-trailing**/*", "https://msnbc.cnn.com/$1"),
),
clear(),
tcEmptyZone(),
tc("multipleB",
cfRedir("msnbc.**current-domain-no-trailing**/*", "https://msnbc.cnn.com/$1"),
cfRedir("cnn.**current-domain-no-trailing**/*", "https://www.cnn.com/$1"),
@ -1958,7 +1955,7 @@ func makeTests() []*TestGroup {
),
// NB(tlim): This test case used to fail but mysteriously started working.
clear(),
tcEmptyZone(),
tc("multiple3",
cfRedir("msnbc.**current-domain-no-trailing**/*", "https://msnbc.cnn.com/$1"),
cfRedir("cnn.**current-domain-no-trailing**/*", "https://www.cnn.com/$1"),
@ -1966,16 +1963,16 @@ func makeTests() []*TestGroup {
),
// Repeat the above tests using CF_TEMP_REDIR instead
clear(),
tcEmptyZone(),
tc("tempredir", cfRedirTemp("cnn.**current-domain-no-trailing**/*", "https://www.cnn.com/$1")),
tc("tempchange", cfRedirTemp("cnn.**current-domain-no-trailing**/*", "https://change.cnn.com/$1")),
tc("tempchangelabel", cfRedirTemp("cable.**current-domain-no-trailing**/*", "https://change.cnn.com/$1")),
clear(),
tcEmptyZone(),
tc("tempmultipleA",
cfRedirTemp("cnn.**current-domain-no-trailing**/*", "https://www.cnn.com/$1"),
cfRedirTemp("msnbc.**current-domain-no-trailing**/*", "https://msnbc.cnn.com/$1"),
),
clear(),
tcEmptyZone(),
tc("tempmultipleB",
cfRedirTemp("msnbc.**current-domain-no-trailing**/*", "https://msnbc.cnn.com/$1"),
cfRedirTemp("cnn.**current-domain-no-trailing**/*", "https://www.cnn.com/$1"),
@ -2018,10 +2015,10 @@ func makeTests() []*TestGroup {
testgroup("CF_PROXY A create",
only("CLOUDFLAREAPI"),
CfProxyOff(), clear(),
CfProxyOn(), clear(),
CfProxyFull1(), clear(),
CfProxyFull2(), clear(),
CfProxyOff(), tcEmptyZone(),
CfProxyOn(), tcEmptyZone(),
CfProxyFull1(), tcEmptyZone(),
CfProxyFull2(), tcEmptyZone(),
),
// These next testgroups attempt every possible transition between off, on, full1 and full2.
@ -2030,62 +2027,62 @@ func makeTests() []*TestGroup {
testgroup("CF_PROXY A off to X",
only("CLOUDFLAREAPI"),
//CF_PROXY_OFF(), CF_PROXY_OFF(), clear(), // redundant
CfProxyOff(), CfProxyOn(), clear(),
CfProxyOff(), CfProxyFull1(), clear(),
CfProxyOff(), CfProxyFull2(), clear(),
// CF_PROXY_OFF(), CF_PROXY_OFF(), tcEmptyZone(), // redundant
CfProxyOff(), CfProxyOn(), tcEmptyZone(),
CfProxyOff(), CfProxyFull1(), tcEmptyZone(),
CfProxyOff(), CfProxyFull2(), tcEmptyZone(),
),
testgroup("CF_PROXY A on to X",
only("CLOUDFLAREAPI"),
CfProxyOn(), CfProxyOff(), clear(),
//CF_PROXY_ON(), CF_PROXY_ON(), clear(), // redundant
//CF_PROXY_ON(), CF_PROXY_FULL1().ExpectNoChanges(), clear(), // Removed for speed
CfProxyOn(), CfProxyFull2(), clear(),
CfProxyOn(), CfProxyOff(), tcEmptyZone(),
// CF_PROXY_ON(), CF_PROXY_ON(), tcEmptyZone(), // redundant
// CF_PROXY_ON(), CF_PROXY_FULL1().ExpectNoChanges(), tcEmptyZone(), // Removed for speed
CfProxyOn(), CfProxyFull2(), tcEmptyZone(),
),
testgroup("CF_PROXY A full1 to X",
only("CLOUDFLAREAPI"),
CfProxyFull1(), CfProxyOff(), clear(),
//CF_PROXY_FULL1(), CF_PROXY_ON().ExpectNoChanges(), clear(), // Removed for speed
//CF_PROXY_FULL1(), CF_PROXY_FULL1(), clear(), // redundant
CfProxyFull1(), CfProxyFull2(), clear(),
CfProxyFull1(), CfProxyOff(), tcEmptyZone(),
// CF_PROXY_FULL1(), CF_PROXY_ON().ExpectNoChanges(), tcEmptyZone(), // Removed for speed
// CF_PROXY_FULL1(), tcEmptyZone(), // redundant
CfProxyFull1(), CfProxyFull2(), tcEmptyZone(),
),
testgroup("CF_PROXY A full2 to X",
only("CLOUDFLAREAPI"),
CfProxyFull2(), CfProxyOff(), clear(),
CfProxyFull2(), CfProxyOn(), clear(),
CfProxyFull2(), CfProxyFull1(), clear(),
//CF_PROXY_FULL2(), CF_PROXY_FULL2(), clear(), // redundant
CfProxyFull2(), CfProxyOff(), tcEmptyZone(),
CfProxyFull2(), CfProxyOn(), tcEmptyZone(),
CfProxyFull2(), CfProxyFull1(), tcEmptyZone(),
// CF_PROXY_FULL2(), CF_PROXY_FULL2(), tcEmptyZone(), // redundant
),
testgroup("CF_PROXY CNAME create",
only("CLOUDFLAREAPI"),
CfCProxyOff(), clear(),
CfCProxyOn(), clear(),
CfCProxyFull(), clear(),
CfCProxyOff(), tcEmptyZone(),
CfCProxyOn(), tcEmptyZone(),
CfCProxyFull(), tcEmptyZone(),
),
testgroup("CF_PROXY CNAME off to X",
only("CLOUDFLAREAPI"),
//CF_CPROXY_OFF(), CF_CPROXY_OFF(), clear(), // redundant
CfCProxyOff(), CfCProxyOn(), clear(),
CfCProxyOff(), CfCProxyFull(), clear(),
// CF_CPROXY_OFF(), CF_CPROXY_OFF(), tcEmptyZone(), // redundant
CfCProxyOff(), CfCProxyOn(), tcEmptyZone(),
CfCProxyOff(), CfCProxyFull(), tcEmptyZone(),
),
testgroup("CF_PROXY CNAME on to X",
only("CLOUDFLAREAPI"),
CfCProxyOn(), CfCProxyOff(), clear(),
//CF_CPROXY_ON(), CF_CPROXY_ON(), clear(), // redundant
//CF_CPROXY_ON(), CF_CPROXY_FULL().ExpectNoChanges(), clear(), // Removed for speed
CfCProxyOn(), CfCProxyOff(), tcEmptyZone(),
// CF_CPROXY_ON(), CF_CPROXY_ON(), tcEmptyZone(), // redundant
// CF_CPROXY_ON(), CF_CPROXY_FULL().ExpectNoChanges(), tcEmptyZone(), // Removed for speed
),
testgroup("CF_PROXY CNAME full to X",
only("CLOUDFLAREAPI"),
CfCProxyFull(), CfCProxyOff(), clear(),
//CF_CPROXY_FULL(), CF_CPROXY_ON().ExpectNoChanges(), clear(), // Removed for speed
//CF_CPROXY_FULL(), CF_CPROXY_FULL(), clear(), // redundant
CfCProxyFull(), CfCProxyOff(), tcEmptyZone(),
// CF_CPROXY_FULL(), CF_CPROXY_ON().ExpectNoChanges(), tcEmptyZone(), // Removed for speed
// CF_CPROXY_FULL(), tcEmptyZone(), // redundant
),
testgroup("CF_WORKER_ROUTE",
@ -2095,7 +2092,7 @@ func makeTests() []*TestGroup {
tc("simple", cfWorkerRoute("cnn.**current-domain-no-trailing**/*", "dnscontrol_integrationtest_cnn")),
tc("changeScript", cfWorkerRoute("cnn.**current-domain-no-trailing**/*", "dnscontrol_integrationtest_msnbc")),
tc("changePattern", cfWorkerRoute("cable.**current-domain-no-trailing**/*", "dnscontrol_integrationtest_msnbc")),
clear(),
tcEmptyZone(),
tc("createMultiple",
cfWorkerRoute("cnn.**current-domain-no-trailing**/*", "dnscontrol_integrationtest_cnn"),
cfWorkerRoute("msnbc.**current-domain-no-trailing**/*", "dnscontrol_integrationtest_msnbc"),
@ -2137,9 +2134,9 @@ func makeTests() []*TestGroup {
// NB(tlim): This ignores 1 record of a recordSet. This should
// fail for diff2.ByRecordSet() providers if diff2 is not
// implemented correctly.
//a("foo", "1.2.3.4"),
//a("foo", "2.3.4.5"),
//txt("foo", "simple"),
// a("foo", "1.2.3.4"),
// a("foo", "2.3.4.5"),
// txt("foo", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
ignore("foo", "", ""),
@ -2153,8 +2150,8 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("ignore label,type",
//a("foo", "1.2.3.4"),
//a("foo", "2.3.4.5"),
// a("foo", "1.2.3.4"),
// a("foo", "2.3.4.5"),
txt("foo", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
@ -2169,7 +2166,7 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("ignore label,type,target",
//a("foo", "1.2.3.4"),
// a("foo", "1.2.3.4"),
a("foo", "2.3.4.5"),
txt("foo", "simple"),
a("bar", "5.5.5.5"),
@ -2185,10 +2182,10 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("ignore type",
//a("foo", "1.2.3.4"),
//a("foo", "2.3.4.5"),
// a("foo", "1.2.3.4"),
// a("foo", "2.3.4.5"),
txt("foo", "simple"),
//a("bar", "5.5.5.5"),
// a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
ignore("", "A", ""),
).ExpectNoChanges(),
@ -2202,7 +2199,7 @@ func makeTests() []*TestGroup {
tc("ignore type,target",
a("foo", "1.2.3.4"),
//a("foo", "2.3.4.5"),
// a("foo", "2.3.4.5"),
txt("foo", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
@ -2218,7 +2215,7 @@ func makeTests() []*TestGroup {
tc("ignore target",
a("foo", "1.2.3.4"),
//a("foo", "2.3.4.5"),
// a("foo", "2.3.4.5"),
txt("foo", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
@ -2234,10 +2231,10 @@ func makeTests() []*TestGroup {
// Many types:
tc("ignore manytypes",
//a("foo", "1.2.3.4"),
//a("foo", "2.3.4.5"),
//txt("foo", "simple"),
//a("bar", "5.5.5.5"),
// a("foo", "1.2.3.4"),
// a("foo", "2.3.4.5"),
// txt("foo", "simple"),
// a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
ignore("", "A,TXT", ""),
).ExpectNoChanges(),
@ -2255,7 +2252,7 @@ func makeTests() []*TestGroup {
a("foo", "2.3.4.5"),
txt("foo", "simple"),
a("bar", "5.5.5.5"),
//cname("mail", "ghs.googlehosted.com."),
// cname("mail", "ghs.googlehosted.com."),
ignore("", "CNAME", "*.googlehosted.com."),
).ExpectNoChanges(),
tc("VERIFY PREVIOUS",
@ -2281,13 +2278,13 @@ func makeTests() []*TestGroup {
// NB(tlim): This ignores 1 record of a recordSet. This should
// fail for diff2.ByRecordSet() providers if diff2 is not
// implemented correctly.
//a("@", "1.2.3.4"),
//a("@", "2.3.4.5"),
//txt("@", "simple"),
// a("@", "1.2.3.4"),
// a("@", "2.3.4.5"),
// txt("@", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
ignore("@", "", ""),
//ignore("", "NS", ""),
// ignore("", "NS", ""),
// NB(tlim): .UnsafeIgnore is needed because the NS records
// that providers injects into zones are treated like input
// from dnsconfig.js.
@ -2301,8 +2298,8 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("apex label,type",
//a("@", "1.2.3.4"),
//a("@", "2.3.4.5"),
// a("@", "1.2.3.4"),
// a("@", "2.3.4.5"),
txt("@", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
@ -2317,7 +2314,7 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("apex label,type,target",
//a("@", "1.2.3.4"),
// a("@", "1.2.3.4"),
a("@", "2.3.4.5"),
txt("@", "simple"),
a("bar", "5.5.5.5"),
@ -2336,10 +2333,10 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("apex type",
//a("@", "1.2.3.4"),
//a("@", "2.3.4.5"),
// a("@", "1.2.3.4"),
// a("@", "2.3.4.5"),
txt("@", "simple"),
//a("bar", "5.5.5.5"),
// a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
ignore("", "A", ""),
).ExpectNoChanges(),
@ -2353,7 +2350,7 @@ func makeTests() []*TestGroup {
tc("apex type,target",
a("@", "1.2.3.4"),
//a("@", "2.3.4.5"),
// a("@", "2.3.4.5"),
txt("@", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
@ -2369,7 +2366,7 @@ func makeTests() []*TestGroup {
tc("apex target",
a("@", "1.2.3.4"),
//a("@", "2.3.4.5"),
// a("@", "2.3.4.5"),
txt("@", "simple"),
a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
@ -2385,10 +2382,10 @@ func makeTests() []*TestGroup {
// Many types:
tc("apex manytypes",
//a("@", "1.2.3.4"),
//a("@", "2.3.4.5"),
//txt("@", "simple"),
//a("bar", "5.5.5.5"),
// a("@", "1.2.3.4"),
// a("@", "2.3.4.5"),
// txt("@", "simple"),
// a("bar", "5.5.5.5"),
cname("mail", "ghs.googlehosted.com."),
ignore("", "A,TXT", ""),
).ExpectNoChanges(),
@ -2452,9 +2449,9 @@ func makeTests() []*TestGroup {
),
tc("ignore label=foo.*",
//a("foo.bat", "1.2.3.4"),
//a("foo.bat", "2.3.4.5"),
//txt("foo.bat", "simple"),
// a("foo.bat", "1.2.3.4"),
// a("foo.bat", "2.3.4.5"),
// txt("foo.bat", "simple"),
a("bar.bat", "5.5.5.5"),
cname("mail.bat", "ghs.googlehosted.com."),
ignore("foo.*", "", ""),
@ -2468,10 +2465,10 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("ignore label=foo.bat,type",
//a("foo.bat", "1.2.3.4"),
//a("foo.bat", "2.3.4.5"),
// a("foo.bat", "1.2.3.4"),
// a("foo.bat", "2.3.4.5"),
txt("foo.bat", "simple"),
//a("bar.bat", "5.5.5.5"),
// a("bar.bat", "5.5.5.5"),
cname("mail.bat", "ghs.googlehosted.com."),
ignore("*.bat", "A", ""),
).ExpectNoChanges(),
@ -2488,7 +2485,7 @@ func makeTests() []*TestGroup {
a("foo.bat", "2.3.4.5"),
txt("foo.bat", "simple"),
a("bar.bat", "5.5.5.5"),
//cname("mail.bat", "ghs.googlehosted.com."),
// cname("mail.bat", "ghs.googlehosted.com."),
ignore("", "", "*.googlehosted.com."),
).ExpectNoChanges(),
tc("VERIFY PREVIOUS",
@ -2521,8 +2518,8 @@ func makeTests() []*TestGroup {
aaaa("foo", "2003:dd:d7ff::fe71:aaaa"),
mx("foo", 10, "aspmx.l.google.com."),
mx("foo", 20, "alt1.aspmx.l.google.com."),
//a("zzz", "3.3.3.3"),
//a("zzz", "4.4.4.4"),
// a("zzz", "3.3.3.3"),
// a("zzz", "4.4.4.4"),
aaaa("zzz", "2003:dd:d7ff::fe71:cccc"),
),
tc("VERIFY PREVIOUS",
@ -2542,8 +2539,8 @@ func makeTests() []*TestGroup {
a("foo", "1.1.1.1"),
a("foo", "12.12.12.12"), // CHANGE
aaaa("foo", "2003:dd:d7ff::fe71:aaaa"),
//mx("foo", 10, "aspmx.l.google.com."),
//mx("foo", 20, "alt1.aspmx.l.google.com"),
// mx("foo", 10, "aspmx.l.google.com."),
// mx("foo", 20, "alt1.aspmx.l.google.com"),
a("zzz", "3.3.3.3"),
a("zzz", "4.4.4.4"),
aaaa("zzz", "2003:dd:d7ff::fe71:cccc"),
@ -2564,9 +2561,9 @@ func makeTests() []*TestGroup {
ignore("foo", "MX,AAAA", ""),
a("foo", "1.1.1.1"),
a("foo", "13.13.13.13"), // CHANGE
//aaaa("foo", "2003:dd:d7ff::fe71:aaaa"),
//mx("foo", 10, "aspmx.l.google.com."),
//mx("foo", 20, "alt1.aspmx.l.google.com"),
// aaaa("foo", "2003:dd:d7ff::fe71:aaaa"),
// mx("foo", 10, "aspmx.l.google.com."),
// mx("foo", 20, "alt1.aspmx.l.google.com"),
a("zzz", "3.3.3.3"),
a("zzz", "4.4.4.4"),
aaaa("zzz", "2003:dd:d7ff::fe71:cccc"),
@ -2585,7 +2582,7 @@ func makeTests() []*TestGroup {
// Change within a (name+type+data) ("ByRecord")
tc("IGNORE change ByRecord",
ignore("foo", "A", "1.1.1.1"),
//a("foo", "1.1.1.1"),
// a("foo", "1.1.1.1"),
a("foo", "14.14.14.14"),
aaaa("foo", "2003:dd:d7ff::fe71:aaaa"),
mx("foo", 10, "aspmx.l.google.com."),
@ -2658,7 +2655,7 @@ func makeTests() []*TestGroup {
a("testdefined", "9.9.9.9"),
),
tc("ignore",
//a("testignore", "8.8.8.8"),
// a("testignore", "8.8.8.8"),
a("testdefined", "9.9.9.9"),
ignore("testignore", "", ""),
).ExpectNoChanges(),
@ -2677,7 +2674,7 @@ func makeTests() []*TestGroup {
).ExpectNoChanges(),
tc("ignore with change",
//a("testignore", "8.8.8.8"),
// a("testignore", "8.8.8.8"),
a("testdefined", "2.2.2.2"),
ignore("testignore", "", ""),
),

View file

@ -2,6 +2,7 @@ package models
import (
"encoding/json"
"errors"
"fmt"
"strings"
)
@ -67,7 +68,7 @@ func ToNameservers(nss []string) ([]*Nameserver, error) {
nservers := []*Nameserver{}
for _, ns := range nss {
if strings.HasSuffix(ns, ".") {
return nil, fmt.Errorf("provider code leaves trailing dot on nameserver")
return nil, errors.New("provider code leaves trailing dot on nameserver")
// If you see this error, maybe the provider should call
// ToNameserversStripTD instead.
}

View file

@ -36,7 +36,7 @@ type DomainConfig struct {
UnmanagedUnsafe bool `json:"unmanaged_disable_safety_check,omitempty"` // DISABLE_IGNORE_SAFETY_CHECK
AutoDNSSEC string `json:"auto_dnssec,omitempty"` // "", "on", "off"
//DNSSEC bool `json:"dnssec,omitempty"`
// DNSSEC bool `json:"dnssec,omitempty"`
// These fields contain instantiated provider instances once everything is linked up.
// This linking is in two phases:
@ -130,9 +130,13 @@ func (dc *DomainConfig) Punycode() error {
if err != nil {
return err
}
rec.SetTarget(t)
if err := rec.SetTarget(t); err != nil {
return err
}
case "CLOUDFLAREAPI_SINGLE_REDIRECT", "CF_REDIRECT", "CF_TEMP_REDIRECT", "CF_WORKER_ROUTE":
rec.SetTarget(rec.GetTargetField())
if err := rec.SetTarget(rec.GetTargetField()); err != nil {
return err
}
case "A", "AAAA", "CAA", "DHCID", "DNSKEY", "DS", "HTTPS", "LOC", "NAPTR", "SOA", "SSHFP", "SVCB", "TXT", "TLSA", "AZURE_ALIAS":
// Nothing to do.
default:

View file

@ -65,23 +65,37 @@ func TestParseQuotedTxt(t *testing.T) {
{`"aaa" "bbb"`, []string{`aaa`, `bbb`}},
{`"a"a" "bbb"`, []string{`a"a`, `bbb`}},
// Seen in live traffic:
{"\"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\"",
[]string{r("B", 254)}},
{"\"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\"",
[]string{r("C", 255)}},
{"\"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\" \"D\"",
[]string{r("D", 255), "D"}},
{"\"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\" \"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\"",
[]string{r("E", 255), r("E", 255)}},
{"\"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\" \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\" \"F\"",
[]string{r("F", 255), r("F", 255), "F"}},
{"\"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\" \"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\" \"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\"",
[]string{r("G", 255), r("G", 255), r("G", 255)}},
{"\"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\" \"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\" \"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\" \"H\"",
[]string{r("H", 255), r("H", 255), r("H", 255), "H"}},
{
"\"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\"",
[]string{r("B", 254)},
},
{
"\"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\"",
[]string{r("C", 255)},
},
{
"\"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\" \"D\"",
[]string{r("D", 255), "D"},
},
{
"\"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\" \"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\"",
[]string{r("E", 255), r("E", 255)},
},
{
"\"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\" \"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\" \"F\"",
[]string{r("F", 255), r("F", 255), "F"},
},
{
"\"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\" \"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\" \"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\"",
[]string{r("G", 255), r("G", 255), r("G", 255)},
},
{
"\"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\" \"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\" \"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\" \"H\"",
[]string{r("H", 255), r("H", 255), r("H", 255), "H"},
},
{"\"quo'te\"", []string{`quo'te`}},
{"\"blah`blah\"", []string{"blah`blah"}},
//{"\"quo\\\"te\"", []string{`quo"te`}},
// {"\"quo\\\"te\"", []string{`quo"te`}},
//{"\"q\\\"uo\\\"te\"", []string{`q"uo"te`}},
//{"\"backs\\\\lash\"", []string{`back\slash`}},
}
@ -111,7 +125,7 @@ func TestParseQuotedFields(t *testing.T) {
}
for i, test := range tests {
ls, _ := ParseQuotedFields(test.d1)
//fmt.Printf("%v: expected TxtStrings:\nWANT: %v\n GOT: %v\n", i, test.e1, ls)
// fmt.Printf("%v: expected TxtStrings:\nWANT: %v\n GOT: %v\n", i, test.e1, ls)
if len(ls) != len(test.e1) {
t.Errorf("%v: expected TxtStrings=(%v) got (%v)", i, test.e1, ls)
}

View file

@ -253,9 +253,13 @@ func (rc *RecordConfig) UnmarshalJSON(b []byte) error {
}
// Copy the exported fields.
copier.CopyWithOption(&rc, &recj, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err := copier.CopyWithOption(&rc, &recj, copier.Option{IgnoreEmpty: true, DeepCopy: true}); err != nil {
return err
}
// Set each unexported field.
rc.SetTarget(recj.Target)
if err := rc.SetTarget(recj.Target); err != nil {
return err
}
// Some sanity checks:
if recj.Type != rc.Type {
@ -288,7 +292,6 @@ func (rc *RecordConfig) Copy() (*RecordConfig, error) {
// short must not have a training dot: That would mean you have a FQDN, and
// shouldn't be using SetLabel(). Maybe SetLabelFromFQDN()?
func (rc *RecordConfig) SetLabel(short, origin string) {
// Assertions that make sure the function is being used correctly:
if strings.HasSuffix(origin, ".") {
panic(fmt.Errorf("origin (%s) is not supposed to end with a dot", origin))
@ -317,7 +320,6 @@ func (rc *RecordConfig) SetLabel(short, origin string) {
// fqdn may have a trailing "." but it is not required.
// origin may not have a trailing dot.
func (rc *RecordConfig) SetLabelFromFQDN(fqdn, origin string) {
// Assertions that make sure the function is being used correctly:
if strings.HasSuffix(origin, ".") {
panic(fmt.Errorf("origin (%s) is not supposed to end with a dot", origin))
@ -360,9 +362,9 @@ func (rc *RecordConfig) ToComparableNoTTL() string {
return fmt.Sprintf("%s %v %d %d %d %d", rc.target, rc.SoaMbox, rc.SoaRefresh, rc.SoaRetry, rc.SoaExpire, rc.SoaMinttl)
// SoaSerial is not included because it isn't used in comparisons.
case "TXT":
//fmt.Fprintf(os.Stdout, "DEBUG: ToComNoTTL raw txts=%s q=%q\n", rc.target, rc.target)
// fmt.Fprintf(os.Stdout, "DEBUG: ToComNoTTL raw txts=%s q=%q\n", rc.target, rc.target)
r := txtutil.EncodeQuoted(rc.target)
//fmt.Fprintf(os.Stdout, "DEBUG: ToComNoTTL cmp txts=%s q=%q\n", r, r)
// fmt.Fprintf(os.Stdout, "DEBUG: ToComNoTTL cmp txts=%s q=%q\n", r, r)
return r
case "UNKNOWN":
return fmt.Sprintf("rtype=%s rdata=%s", rc.UnknownTypeName, rc.target)
@ -372,7 +374,6 @@ func (rc *RecordConfig) ToComparableNoTTL() string {
// ToRR converts a RecordConfig to a dns.RR.
func (rc *RecordConfig) ToRR() dns.RR {
// Don't call this on fake types.
rdtype, ok := dns.StringToType[rc.Type]
if !ok {
@ -486,7 +487,6 @@ func (rc *RecordConfig) ToRR() dns.RR {
// GetDependencies returns the FQDNs on which this record dependents
func (rc *RecordConfig) GetDependencies() []string {
switch rc.Type {
// #rtype_variations
case "NS", "SRV", "CNAME", "DNAME", "MX", "ALIAS", "AZURE_ALIAS", "R53_ALIAS":

View file

@ -24,7 +24,7 @@ func TestHasRecordTypeName(t *testing.T) {
}
func TestKey(t *testing.T) {
var tests = []struct {
tests := []struct {
rc RecordConfig
expected RecordKey
}{
@ -136,7 +136,7 @@ func TestRecordConfig_Copy(t *testing.T) {
TlsaMatchingType: 3,
R53Alias: map[string]string{"a": "eh", "b": "bee"},
AzureAlias: map[string]string{"az": "az", "ure": "your"},
//Original interface{},
// Original interface{},
},
want: &RecordConfig{
Type: "type",
@ -174,7 +174,7 @@ func TestRecordConfig_Copy(t *testing.T) {
TlsaMatchingType: 3,
R53Alias: map[string]string{"a": "eh", "b": "bee"},
AzureAlias: map[string]string{"az": "az", "ure": "your"},
//Original interface{},
// Original interface{},
},
},
}

View file

@ -16,7 +16,7 @@ func NewRecordDBFromRecords(recs Records, zone string) *RecordDB {
for _, rec := range recs {
result.labelAndTypeMap[rec.Key()] = struct{}{}
}
//fmt.Printf("DEBUG: BUILDING RecordDB: DONE!\n")
// fmt.Printf("DEBUG: BUILDING RecordDB: DONE!\n")
return result
}

View file

@ -9,7 +9,9 @@ import (
func (rc *RecordConfig) SetTargetCAA(flag uint8, tag string, target string) error {
rc.CaaTag = tag
rc.CaaFlag = flag
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
if rc.Type == "" {
rc.Type = "CAA"
}

View file

@ -31,8 +31,8 @@ func (rc *RecordConfig) SetTargetLOC(ver uint8, lat uint32, lon uint32, alt uint
// for further processing to the LOC native 7 input binary format:
// LocVersion (0), LocLatitude, LocLongitude, LocAltitude, LocSize, LocVertPre, LocHorizPre
func (rc *RecordConfig) SetLOCParams(d1 uint8, m1 uint8, s1 float32, ns string,
d2 uint8, m2 uint8, s2 float32, ew string, al float32, sz float32, hp float32, vp float32) error {
d2 uint8, m2 uint8, s2 float32, ew string, al float32, sz float32, hp float32, vp float32,
) error {
err := rc.calculateLOCFields(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp)
return err
@ -90,14 +90,13 @@ func (rc *RecordConfig) extractLOCFieldsFromStringInput(input string) error {
}
// fmt.Printf("\ngot: %d %d %g %s %d %d %g %s %0.2fm %0.2fm %0.2fm %0.2fm \n", d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp)
rc.calculateLOCFields(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp)
return nil
return rc.calculateLOCFields(d1, m1, s1, ns, d2, m2, s2, ew, al, sz, hp, vp)
}
// calculateLOCFields converts from 12 user inputs to the LOC 7 binary fields
func (rc *RecordConfig) calculateLOCFields(d1 uint8, m1 uint8, s1 float32, ns string,
d2 uint8, m2 uint8, s2 float32, ew string, al float32, sz float32, hp float32, vp float32) error {
d2 uint8, m2 uint8, s2 float32, ew string, al float32, sz float32, hp float32, vp float32,
) error {
// Crazy hairy shit happens here.
// We already got the useful "string" version earlier. ¯\_(ツ)_/¯ code golf...
const LOCEquator uint64 = 0x80000000 // 1 << 31 // RFC 1876, Section 2.

View file

@ -9,7 +9,9 @@ import (
// SetTargetMX sets the MX fields.
func (rc *RecordConfig) SetTargetMX(pref uint16, target string) error {
rc.MxPreference = pref
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
if rc.Type == "" {
rc.Type = "MX"
}

View file

@ -16,7 +16,9 @@ func (rc *RecordConfig) SetTargetNAPTR(order uint16, preference uint16, flags st
rc.NaptrFlags = flags
rc.NaptrService = service
rc.NaptrRegexp = regexp
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
if rc.Type == "" {
rc.Type = "NAPTR"

View file

@ -110,7 +110,7 @@ func (rc *RecordConfig) PopulateFromStringFunc(rtype, contents, origin string, t
case "TLSA":
return rc.SetTargetTLSAString(contents)
default:
//return fmt.Errorf("unknown rtype (%s) when parsing (%s) domain=(%s)", rtype, contents, origin)
// return fmt.Errorf("unknown rtype (%s) when parsing (%s) domain=(%s)", rtype, contents, origin)
return MakeUnknown(rc, rtype, contents, origin)
}
}

View file

@ -19,7 +19,10 @@ work that providers do.
// SetTargetSOA sets the SOA fields.
func (rc *RecordConfig) SetTargetSOA(ns, mbox string, serial, refresh, retry, expire, minttl uint32) error {
rc.SetTarget(ns) // The NS field is stored as the .Target
// The NS field is stored as the .Target
if err := rc.SetTarget(ns); err != nil {
return err
}
rc.SoaMbox = mbox
rc.SoaSerial = serial
rc.SoaRefresh = refresh
@ -39,7 +42,6 @@ func (rc *RecordConfig) SetTargetSOA(ns, mbox string, serial, refresh, retry, ex
// SetTargetSOAStrings is like SetTargetSOA but accepts strings.
func (rc *RecordConfig) SetTargetSOAStrings(ns, mbox, serial, refresh, retry, expire, minttl string) error {
u32serial, err := strconv.ParseUint(serial, 10, 32)
if err != nil {
return fmt.Errorf("SOA serial '%v' is invalid: %w", serial, err)

View file

@ -11,7 +11,9 @@ func (rc *RecordConfig) SetTargetSRV(priority, weight, port uint16, target strin
rc.SrvPriority = priority
rc.SrvWeight = weight
rc.SrvPort = port
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
if rc.Type == "" {
rc.Type = "SRV"
}

View file

@ -10,7 +10,9 @@ import (
func (rc *RecordConfig) SetTargetSSHFP(algorithm uint8, fingerprint uint8, target string) error {
rc.SshfpAlgorithm = algorithm
rc.SshfpFingerprint = fingerprint
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
if rc.Type == "" {
rc.Type = "SSHFP"
}

View file

@ -10,7 +10,9 @@ import (
// SetTargetSVCB sets the SVCB fields.
func (rc *RecordConfig) SetTargetSVCB(priority uint16, target string, params []dns.SVCBKeyValue) error {
rc.SvcPriority = priority
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
paramsStr := []string{}
for _, kv := range params {
paramsStr = append(paramsStr, fmt.Sprintf("%s=%s", kv.Key(), kv.String()))
@ -32,7 +34,7 @@ func (rc *RecordConfig) SetTargetSVCBString(origin, contents string) error {
}
record, err := dns.NewRR(fmt.Sprintf("%s. %s %s", origin, rc.Type, contents))
if err != nil {
return fmt.Errorf("could not parse SVCB record: %s", err)
return fmt.Errorf("could not parse SVCB record: %w", err)
}
switch r := record.(type) {
case *dns.HTTPS:

View file

@ -11,7 +11,9 @@ func (rc *RecordConfig) SetTargetTLSA(usage, selector, matchingtype uint8, targe
rc.TlsaUsage = usage
rc.TlsaSelector = selector
rc.TlsaMatchingType = matchingtype
rc.SetTarget(target)
if err := rc.SetTarget(target); err != nil {
return err
}
if rc.Type == "" {
rc.Type = "TLSA"
}

View file

@ -17,7 +17,7 @@ represented by the provider, which could be a single string, a series
of smaller strings, or a single string that is quoted/escaped. This
created tons of edge-cases and other distractions.
If a provider doesn't support certain charactors in a TXT record, use
If a provider doesn't support certain characters in a TXT record, use
the providers/$PROVIDER/auditrecords.go file to indicate this.
DNSControl uses this information to warn users of unsupporrted input,
and to skip related integration tests.
@ -87,7 +87,7 @@ func splitChunks(buf string, lim int) []string {
chunks = append(chunks, chunk)
}
if len(buf) > 0 {
chunks = append(chunks, buf[:])
chunks = append(chunks, buf)
}
return chunks
}

View file

@ -45,7 +45,6 @@ func (rc *RecordConfig) GetTargetCombinedFunc(encodeFn func(s string) string) st
// WARNING: How TXT records are handled is buggy but we can't change it because
// code depends on the bugs. Use Get GetTargetCombinedFunc() instead.
func (rc *RecordConfig) GetTargetCombined() string {
// Pseudo records:
if _, ok := dns.StringToType[rc.Type]; !ok {
switch rc.Type { // #rtype_variations
@ -82,7 +81,7 @@ func (rc *RecordConfig) zoneFileQuoted() string {
// TODO(tlim): Request the dns project add a function that returns
// the string without the header.
if rc.Type == "NAPTR" && rc.GetTargetField() == "" {
rc.SetTarget(".")
rc.MustSetTarget(".")
}
rr := rc.ToRR()
header := rr.Header().String()
@ -112,7 +111,7 @@ func (rc *RecordConfig) GetTargetDebug() string {
case "A", "AAAA", "AKAMAICDN", "CNAME", "DHCID", "NS", "PTR", "TXT":
// Nothing special.
case "AZURE_ALIAS":
content += fmt.Sprintf(" type=%s", rc.AzureAlias["type"])
content += " type=" + rc.AzureAlias["type"]
case "CAA":
content += fmt.Sprintf(" caatag=%s caaflag=%d", rc.CaaTag, rc.CaaFlag)
case "DS":
@ -153,9 +152,16 @@ func (rc *RecordConfig) SetTarget(target string) error {
return nil
}
// MustSetTarget is like SetTarget, but panics if an error occurs.
// It should only be used in _test.go files and in the init() function.
func (rc *RecordConfig) MustSetTarget(target string) {
if err := rc.SetTarget(target); err != nil {
panic(err)
}
}
// 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.SetTarget(ip.String())
return nil
return rc.SetTarget(ip.String())
}

View file

@ -4,6 +4,7 @@ package acme
import (
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io"
"log"
@ -104,7 +105,7 @@ func (c *certManager) IssueOrRenewCert(cfg *CertConfig, renewUnder int, verbose
if !verbose {
acmelog.Logger = log.New(io.Discard, "", 0)
}
defer c.finalCleanUp()
defer c.finalCleanUp() //nolint:errcheck
log.Printf("Checking certificate [%s]", cfg.CertName)
existing, err := c.storage.GetCertificate(cfg.CertName)
@ -114,7 +115,7 @@ func (c *certManager) IssueOrRenewCert(cfg *CertConfig, renewUnder int, verbose
var client *lego.Client
var action = func() (*certificate.Resource, error) {
action := func() (*certificate.Resource, error) {
return client.Certificate.Obtain(certificate.ObtainRequest{
Bundle: true,
Domains: cfg.Names,
@ -133,7 +134,7 @@ func (c *certManager) IssueOrRenewCert(cfg *CertConfig, renewUnder int, verbose
namesOK := dnsNamesEqual(cfg.Names, names)
if daysLeft >= float64(renewUnder) && namesOK {
log.Println("Nothing to do")
//nothing to do
// nothing to do
return false, nil
}
if !namesOK {
@ -159,7 +160,7 @@ func (c *certManager) IssueOrRenewCert(cfg *CertConfig, renewUnder int, verbose
}
client.Challenge.Remove(challenge.HTTP01)
client.Challenge.Remove(challenge.TLSALPN01)
client.Challenge.SetDNS01Provider(c, dns01.WrapPreCheck(c.preCheckDNS))
client.Challenge.SetDNS01Provider(c, dns01.WrapPreCheck(c.preCheckDNS)) //nolint:errcheck
certResource, err := action()
if err != nil {
@ -176,7 +177,7 @@ func (c *certManager) IssueOrRenewCert(cfg *CertConfig, renewUnder int, verbose
func getCertInfo(pemBytes []byte) (names []string, remaining float64, err error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, 0, fmt.Errorf("invalid certificate PEM data")
return nil, 0, errors.New("invalid certificate PEM data")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
@ -187,7 +188,7 @@ func getCertInfo(pemBytes []byte) (names []string, remaining float64, err error)
// may be decommed eventually, and since there are no unit tests,
// I'm not excited about making this change.
// var daysLeft = float64(time.Until(cert.NotAfter)) / float64(time.Hour*24)
var daysLeft = float64(cert.NotAfter.Sub(time.Now())) / float64(time.Hour*24)
daysLeft := float64(time.Until(cert.NotAfter)) / float64(time.Hour*24)
return cert.DNSNames, daysLeft, nil
}
@ -225,24 +226,26 @@ func (c *certManager) Present(domain, token, keyAuth string) (e error) {
nameservers.AddNSRecords(d)
// make sure we have the latest config before we change anything.
// alternately, we could avoid a lot of this trouble if we really really trusted no-purge in all cases
// alternately, we could avoid a lot of this trouble if we really trusted no-purge in all cases
if err := c.ensureNoPendingCorrections(d); err != nil {
return err
}
// copy domain and work from copy from now on. That way original config can be used to "restore" when we are all done.
copy, err := d.Copy()
// Copy domain and work from cpy from now on. That way original config can be used to "restore" when we are all done.
cpy, err := d.Copy()
if err != nil {
return err
}
c.originalDomains = append(c.originalDomains, d)
c.domains[name] = copy
d = copy
c.domains[name] = cpy
d = cpy
}
fqdn, val := dns01.GetRecord(domain, keyAuth)
txt := &models.RecordConfig{Type: "TXT"}
txt.SetTargetTXT(val)
if err := txt.SetTargetTXT(val); err != nil {
return err
}
txt.SetLabelFromFQDN(fqdn, d.Name)
d.Records = append(d.Records, txt)
return c.getAndRunCorrections(d)

View file

@ -4,7 +4,7 @@ import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"errors"
"os"
"path/filepath"
@ -18,6 +18,7 @@ type directoryStorage string
func (d directoryStorage) certFile(name, ext string) string {
return filepath.Join(d.certDir(name), name+"."+ext)
}
func (d directoryStorage) certDir(name string) string {
return filepath.Join(string(d), "certificates", name)
}
@ -29,12 +30,15 @@ func (d directoryStorage) accountDirectory(acmeHost string) string {
func (d directoryStorage) accountFile(acmeHost string) string {
return filepath.Join(d.accountDirectory(acmeHost), "account.json")
}
func (d directoryStorage) accountKeyFile(acmeHost string) string {
return filepath.Join(d.accountDirectory(acmeHost), "account.key")
}
const perms os.FileMode = 0600
const dirPerms os.FileMode = 0700
const (
perms os.FileMode = 0o600
dirPerms os.FileMode = 0o700
)
func (d directoryStorage) GetCertificate(name string) (*certificate.Resource, error) {
f, err := os.Open(d.certFile(name, "json"))
@ -106,7 +110,7 @@ func (d directoryStorage) GetAccount(acmeHost string) (*Account, error) {
}
keyBlock, _ := pem.Decode(keyBytes)
if keyBlock == nil {
return nil, fmt.Errorf("error decoding account private key")
return nil, errors.New("error decoding account private key")
}
acct.key, err = x509.ParseECPrivateKey(keyBlock.Bytes)
if err != nil {

View file

@ -5,6 +5,7 @@ import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"strings"
@ -123,7 +124,7 @@ func (v *vaultStorage) GetAccount(acmeHost string) (*Account, error) {
if dat, err = v.getString("tls.key", secret.Data, path); err != nil {
return nil, err
} else if block, _ = pem.Decode(dat); block == nil {
return nil, fmt.Errorf("error decoding account private key")
return nil, errors.New("error decoding account private key")
} else if key, err = x509.ParseECPrivateKey(block.Bytes); err != nil {
return nil, err
}

View file

@ -21,7 +21,7 @@ import (
// LoadProviderConfigs will open or execute the specified file name, and parse its contents. It will replace environment variables it finds if any value matches $[A-Za-z_-0-9]+
func LoadProviderConfigs(fname string) (map[string]map[string]string, error) {
var results = map[string]map[string]string{}
results := map[string]map[string]string{}
var dat []byte
var err error
@ -45,7 +45,7 @@ func LoadProviderConfigs(fname string) (map[string]map[string]string, error) {
r := JsonConfigReader.New(strings.NewReader(s))
err = json.NewDecoder(r).Decode(&results)
if err != nil {
return nil, fmt.Errorf("failed parsing provider credentials file %v: %v", fname, err)
return nil, fmt.Errorf("failed parsing provider credentials file %v: %w", fname, err)
}
if err = replaceEnvVars(results); err != nil {
return nil, err
@ -66,7 +66,7 @@ func LoadProviderConfigs(fname string) (map[string]map[string]string, error) {
func isExecutable(filename string) bool {
if stat, statErr := os.Stat(filename); statErr == nil {
if mode := stat.Mode(); mode&0111 == 0111 {
if mode := stat.Mode(); mode&0o111 == 0o111 {
return true
}
}
@ -81,7 +81,7 @@ func readCredsFile(filename string) ([]byte, error) {
fmt.Printf("INFO: Config file %q does not exist. Skipping.\n", filename)
return []byte{}, nil
}
return nil, fmt.Errorf("failed reading provider credentials file %v: %v", filename, err)
return nil, fmt.Errorf("failed reading provider credentials file %v: %w", filename, err)
}
return dat, nil
}

View file

@ -26,8 +26,7 @@ type Differ interface {
ChangedGroups(existing []*models.RecordConfig) (map[models.RecordKey][]string, []string, int, error)
}
type differ struct {
}
type differ struct{}
// get normalized content for record. target, ttl, mxprio, and specified metadata
func (d *differ) content(r *models.RecordConfig) string {

View file

@ -89,7 +89,6 @@ func analyzeByLabel(cc *CompareConfig) (ChangeList, int) {
}
func analyzeByRecord(cc *CompareConfig) (ChangeList, int) {
var instructions ChangeList
var actualChangeCount int
// For each label, for each type at that label, see if there are any changes.
@ -136,7 +135,6 @@ func mkDelete(l string, t string, msgs []string, oldRecs models.Records) Change
}
func removeCommon(existing, desired []targetConfig) ([]targetConfig, []targetConfig) {
// Sort by comparableFull.
sort.Slice(existing, func(i, j int) bool { return existing[i].comparableFull < existing[j].comparableFull })
sort.Slice(desired, func(i, j int) bool { return desired[i].comparableFull < desired[j].comparableFull })
@ -159,7 +157,6 @@ func removeCommon(existing, desired []targetConfig) ([]targetConfig, []targetCon
// findTTLChanges finds the records that ONLY change their TTL. For those, generate a Change.
// Remove such items from the list.
func findTTLChanges(existing, desired []targetConfig) ([]targetConfig, []targetConfig, ChangeList) {
if (len(existing) == 0) || (len(desired) == 0) {
return existing, desired, nil
}
@ -251,8 +248,7 @@ func humanDiff(a, b targetConfig) string {
}
func diffTargets(existing, desired []targetConfig) ChangeList {
//fmt.Printf("DEBUG: diffTargets(\nexisting=%v\ndesired=%v\nDEBUG.\n", existing, desired)
// fmt.Printf("DEBUG: diffTargets(\nexisting=%v\ndesired=%v\nDEBUG.\n", existing, desired)
// Nothing to do?
if len(existing) == 0 && len(desired) == 0 {
@ -277,7 +273,7 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
// the remaining chunks are changes (regardless of TTL)
mi := min(len(existing), len(desired))
for i := 0; i < mi; i++ {
for i := range mi {
er := existing[i].rec
dr := desired[i].rec

View file

@ -60,48 +60,55 @@ func makeRec(label, rtype, content string) *models.RecordConfig {
origin := "f.com"
r := models.RecordConfig{TTL: 300}
r.SetLabel(label, origin)
r.PopulateFromString(rtype, content, origin)
if err := r.PopulateFromString(rtype, content, origin); err != nil {
panic(err)
}
return &r
}
func makeRecTTL(label, rtype, content string, ttl uint32) *models.RecordConfig {
r := makeRec(label, rtype, content)
r.TTL = ttl
return r
}
var testDataAA1234 = makeRec("laba", "A", "1.2.3.4") // [ 0]
var testDataAA5678 = makeRec("laba", "A", "5.6.7.8") //
var testDataAA1234ttl700 = makeRecTTL("laba", "A", "1.2.3.4", 700) //
var testDataAA5678ttl700 = makeRecTTL("laba", "A", "5.6.7.8", 700) //
var testDataAMX10a = makeRec("laba", "MX", "10 laba") // [ 1]
var testDataCCa = makeRec("labc", "CNAME", "laba") // [ 2]
var testDataEA15 = makeRec("labe", "A", "10.10.10.15") // [ 3]
var e4 = makeRec("labe", "A", "10.10.10.16") // [ 4]
var e5 = makeRec("labe", "A", "10.10.10.17") // [ 5]
var e6 = makeRec("labe", "A", "10.10.10.18") // [ 6]
var e7 = makeRec("labg", "NS", "laba") // [ 7]
var e8 = makeRec("labg", "NS", "labb") // [ 8]
var e9 = makeRec("labg", "NS", "labc") // [ 9]
var e10 = makeRec("labg", "NS", "labe") // [10]
var e11mx = makeRec("labh", "MX", "22 ttt") // [11]
var e11 = makeRec("labh", "CNAME", "labd") // [11]
var testDataApexMX1aaa = makeRec("", "MX", "1 aaa")
var (
testDataAA1234 = makeRec("laba", "A", "1.2.3.4") // [ 0]
testDataAA5678 = makeRec("laba", "A", "5.6.7.8") //
testDataAA1234ttl700 = makeRecTTL("laba", "A", "1.2.3.4", 700) //
testDataAA5678ttl700 = makeRecTTL("laba", "A", "5.6.7.8", 700) //
testDataAMX10a = makeRec("laba", "MX", "10 laba") // [ 1]
testDataCCa = makeRec("labc", "CNAME", "laba") // [ 2]
testDataEA15 = makeRec("labe", "A", "10.10.10.15") // [ 3]
e4 = makeRec("labe", "A", "10.10.10.16") // [ 4]
e5 = makeRec("labe", "A", "10.10.10.17") // [ 5]
e6 = makeRec("labe", "A", "10.10.10.18") // [ 6]
e7 = makeRec("labg", "NS", "laba") // [ 7]
e8 = makeRec("labg", "NS", "labb") // [ 8]
e9 = makeRec("labg", "NS", "labc") // [ 9]
e10 = makeRec("labg", "NS", "labe") // [10]
e11mx = makeRec("labh", "MX", "22 ttt") // [11]
e11 = makeRec("labh", "CNAME", "labd") // [11]
testDataApexMX1aaa = makeRec("", "MX", "1 aaa")
)
var testDataAA1234clone = makeRec("laba", "A", "1.2.3.4") // [ 0']
var testDataAA12345 = makeRec("laba", "A", "1.2.3.5") // [ 1']
var testDataAMX20b = makeRec("laba", "MX", "20 labb") // [ 2']
var d3 = makeRec("labe", "A", "10.10.10.95") // [ 3']
var d4 = makeRec("labe", "A", "10.10.10.96") // [ 4']
var d5 = makeRec("labe", "A", "10.10.10.97") // [ 5']
var d6 = makeRec("labe", "A", "10.10.10.98") // [ 6']
var d7 = makeRec("labf", "TXT", "foo") // [ 7']
var d8 = makeRec("labg", "NS", "labf") // [ 8']
var d9 = makeRec("labg", "NS", "laba") // [ 9']
var d10 = makeRec("labg", "NS", "labe") // [10']
var d11 = makeRec("labg", "NS", "labb") // [11']
var d12 = makeRec("labh", "A", "1.2.3.4") // [12']
var d13 = makeRec("labc", "CNAME", "labe") // [13']
var testDataApexMX22bbb = makeRec("", "MX", "22 bbb")
var (
testDataAA1234clone = makeRec("laba", "A", "1.2.3.4") // [ 0']
testDataAA12345 = makeRec("laba", "A", "1.2.3.5") // [ 1']
testDataAMX20b = makeRec("laba", "MX", "20 labb") // [ 2']
d3 = makeRec("labe", "A", "10.10.10.95") // [ 3']
d4 = makeRec("labe", "A", "10.10.10.96") // [ 4']
d5 = makeRec("labe", "A", "10.10.10.97") // [ 5']
d6 = makeRec("labe", "A", "10.10.10.98") // [ 6']
d7 = makeRec("labf", "TXT", "foo") // [ 7']
d8 = makeRec("labg", "NS", "labf") // [ 8']
d9 = makeRec("labg", "NS", "laba") // [ 9']
d10 = makeRec("labg", "NS", "labe") // [10']
d11 = makeRec("labg", "NS", "labb") // [11']
d12 = makeRec("labh", "A", "1.2.3.4") // [12']
d13 = makeRec("labc", "CNAME", "labe") // [13']
testDataApexMX22bbb = makeRec("", "MX", "22 bbb")
)
func justMsgString(cl ChangeList) string {
msgs := justMsgs(cl)
@ -158,7 +165,6 @@ func Test_analyzeByRecordSet(t *testing.T) {
wantChangeZone string
wantChangeCount int
}{
{
name: "oneequal",
args: args{
@ -559,7 +565,6 @@ ChangeList: len=11
})
// NB(tlim): There is no analyzeByZone(). diff2.ByZone() uses analyzeByRecord().
}
}
@ -586,15 +591,15 @@ func mkTargetConfig(x ...*models.RecordConfig) []targetConfig {
}
func mkTargetConfigMap(x ...*models.RecordConfig) map[string]*targetConfig {
var m = map[string]*targetConfig{}
m := map[string]*targetConfig{}
for _, v := range mkTargetConfig(x...) {
v := v
m[v.comparableFull] = &v
}
return m
}
func Test_diffTargets(t *testing.T) {
type args struct {
existing []targetConfig
desired []targetConfig
@ -604,7 +609,6 @@ func Test_diffTargets(t *testing.T) {
args args
want ChangeList
}{
{
name: "add1changettl",
args: args{
@ -612,9 +616,10 @@ func Test_diffTargets(t *testing.T) {
desired: mkTargetConfig(testDataAA5678ttl700, testDataAA1234ttl700),
},
want: ChangeList{
Change{Type: CHANGE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "A"},
New: models.Records{testDataAA5678ttl700, testDataAA1234ttl700},
Change{
Type: CHANGE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "A"},
New: models.Records{testDataAA5678ttl700, testDataAA1234ttl700},
Msgs: []string{
"± MODIFY-TTL laba.f.com A 5.6.7.8 ttl=(300->700)",
"+ CREATE laba.f.com A 1.2.3.4 ttl=700",
@ -629,7 +634,7 @@ func Test_diffTargets(t *testing.T) {
existing: mkTargetConfig(testDataAA1234),
desired: mkTargetConfig(testDataAA1234),
},
//want: ,
// want: ,
},
{
@ -639,7 +644,8 @@ func Test_diffTargets(t *testing.T) {
desired: mkTargetConfig(testDataAA1234, testDataAMX10a),
},
want: ChangeList{
Change{Type: CREATE,
Change{
Type: CREATE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "MX"},
New: models.Records{makeRec("laba", "MX", "10 laba.f.com.")},
Msgs: []string{"+ CREATE laba.f.com MX 10 laba.f.com. ttl=300"},
@ -654,7 +660,8 @@ func Test_diffTargets(t *testing.T) {
desired: mkTargetConfig(testDataAA1234),
},
want: ChangeList{
Change{Type: DELETE,
Change{
Type: DELETE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "MX"},
Old: models.Records{makeRec("laba", "MX", "10 laba.f.com.")},
Msgs: []string{"- DELETE laba.f.com MX 10 laba.f.com. ttl=300"},
@ -669,7 +676,8 @@ func Test_diffTargets(t *testing.T) {
desired: mkTargetConfig(testDataAA1234, testDataAMX20b),
},
want: ChangeList{
Change{Type: CHANGE,
Change{
Type: CHANGE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "MX"},
Old: models.Records{testDataAMX10a},
New: models.Records{testDataAMX20b},
@ -685,7 +693,8 @@ func Test_diffTargets(t *testing.T) {
desired: mkTargetConfig(testDataAA1234),
},
want: ChangeList{
Change{Type: CHANGE,
Change{
Type: CHANGE,
Key: models.RecordKey{NameFQDN: "laba.f.com", Type: "A"},
Old: models.Records{testDataAA1234, testDataAA5678},
New: models.Records{testDataAA1234},
@ -696,13 +705,13 @@ func Test_diffTargets(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
//fmt.Printf("DEBUG: Test %02d\n", i)
// fmt.Printf("DEBUG: Test %02d\n", i)
got := diffTargets(tt.args.existing, tt.args.desired)
g := strings.TrimSpace(justMsgString(got))
w := strings.TrimSpace(justMsgString(tt.want))
d := diff.Diff(g, w)
if d != "" {
//fmt.Printf("DEBUG: fail %q %q\n", g, w)
// fmt.Printf("DEBUG: fail %q %q\n", g, w)
t.Errorf("diffTargets()\n diff=%s", d)
}
})
@ -720,7 +729,6 @@ func Test_removeCommon(t *testing.T) {
want []targetConfig
want1 []targetConfig
}{
{
name: "same",
args: args{
@ -772,7 +780,6 @@ func Test_filterBy(t *testing.T) {
args args
want []targetConfig
}{
{
name: "removeall",
args: args{
@ -821,7 +828,6 @@ func Test_splitTTLOnly(t *testing.T) {
wantDesireDiff []targetConfig
wantChanges string
}{
{
name: "simple",
args: args{

View file

@ -113,7 +113,6 @@ func NewCompareConfig(origin string, existing, desired models.Records, compFn Co
// verifyCNAMEAssertions verifies assertions about CNAME updates ordering.
func (cc *CompareConfig) verifyCNAMEAssertions() {
// According to the RFCs if a label has a CNAME, it can not have any other
// records at that label... even other CNAMEs. Therefore, we need to be
// careful with changes at a label that involve a CNAME.
@ -121,7 +120,7 @@ func (cc *CompareConfig) verifyCNAMEAssertions() {
// OLD: a.example.com CNAME b
// NEW: a.example.com A 1.2.3.4
// We must delete the CNAME record THEN create the A record. If we
// blindly create the the A first, most APIs will reply with an error
// blindly create the A first, most APIs will reply with an error
// because there is already a CNAME at that label.
// Example 2:
// OLD: a.example.com A 1.2.3.4
@ -141,9 +140,7 @@ func (cc *CompareConfig) verifyCNAMEAssertions() {
for _, ld := range cc.ldata {
for j, td := range ld.tdata {
if td.rType == "CNAME" {
// This assertion doesn't hold for a site that permits a
// recordset with both CNAMEs and other records, such as
// Cloudflare.
@ -167,13 +164,11 @@ func (cc *CompareConfig) verifyCNAMEAssertions() {
}
}
}
}
// Generate a string that can be used to compare this record to others
// for equality.
func mkCompareBlobs(rc *models.RecordConfig, f func(*models.RecordConfig) string) (string, string) {
// Start with the comparable string
comp := rc.ToComparableNoTTL()
@ -204,7 +199,6 @@ func (cc *CompareConfig) addRecords(recs models.Records, storeInExisting bool) {
z := prettyzone.PrettySort(recs, cc.origin, 0, nil)
for _, rec := range z.Records {
key := rec.Key()
label := key.NameFQDN
rtype := key.Type

View file

@ -51,7 +51,6 @@ func TestNewCompareConfig(t *testing.T) {
args args
want string
}{
{
name: "one",
args: args{
@ -227,7 +226,6 @@ compFn: <nil>
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
models.CanonicalizeTargets(tt.args.desired, "f.com")
models.CanonicalizeTargets(tt.args.existing, "f.com")
@ -264,7 +262,6 @@ func Test_mkCompareBlobs(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := mkCompareBlobs(tt.args.rc, tt.args.f)
if got != tt.want {
t.Errorf("mkCompareBlobs() got = %q, want %q", got, tt.want)

View file

@ -5,6 +5,7 @@ package diff2
// NO_PURGE, ENSURE_ABSENT and IGNORE*() features.
import (
"errors"
"fmt"
"strings"
@ -56,7 +57,7 @@ As a result, the diff2 algorithm won't delete them because they are desired!
(Of course "desired" can't have duplicate records. Check before you add.)
This is different than in the old implementation (pkg/diff) which would generate the
diff but but then do a bunch of checking to see if the record was one that
diff but then do a bunch of checking to see if the record was one that
shouldn't be deleted. Or, in the case of NO_PURGE, would simply not do the
deletions. This was complex because there were many edge cases to deal with.
It was often also wrong. For example, if a provider updates all records in a
@ -114,13 +115,16 @@ func handsoff(
return nil, nil, err
}
var punct = ":"
punct := ":"
if printer.MaxReport == 0 {
punct = "."
}
// Process IGNORE*() and NO_PURGE features:
ignorable, foreign := processIgnoreAndNoPurge(domain, existing, desired, absences, unmanagedConfigs, noPurge)
ignorable, foreign, err := processIgnoreAndNoPurge(domain, existing, desired, absences, unmanagedConfigs, noPurge)
if err != nil {
return nil, nil, err
}
if len(foreign) != 0 {
msgs = append(msgs, fmt.Sprintf("%d records not being deleted because of NO_PURGE%s", len(foreign), punct))
msgs = append(msgs, reportSkips(foreign, !printer.SkinnyReport)...)
@ -138,7 +142,7 @@ func handsoff(
msgs = append(msgs, fmt.Sprintf(" %s %s %s", r.GetLabelFQDN(), r.Type, r.GetTargetCombined()))
}
if !unmanagedSafely {
return nil, nil, fmt.Errorf(strings.Join(msgs, "\n") +
return nil, nil, errors.New(strings.Join(msgs, "\n") +
"\nERROR: Unsafe to continue. Add DISABLE_IGNORE_SAFETY_CHECK to D() to override")
}
}
@ -172,14 +176,16 @@ func reportSkips(recs models.Records, full bool) []string {
}
// processIgnoreAndNoPurge processes the IGNORE_*() and NO_PURGE/ENSURE_ABSENT() features.
func processIgnoreAndNoPurge(domain string, existing, desired, absences models.Records, unmanagedConfigs []*models.UnmanagedConfig, noPurge bool) (models.Records, models.Records) {
func processIgnoreAndNoPurge(domain string, existing, desired, absences models.Records, unmanagedConfigs []*models.UnmanagedConfig, noPurge bool) (models.Records, models.Records, error) {
var ignorable, foreign models.Records
desiredDB := models.NewRecordDBFromRecords(desired, domain)
absentDB := models.NewRecordDBFromRecords(absences, domain)
compileUnmanagedConfigs(unmanagedConfigs)
if err := compileUnmanagedConfigs(unmanagedConfigs); err != nil {
return nil, nil, err
}
for _, rec := range existing {
isMatch := matchAny(unmanagedConfigs, rec)
//fmt.Printf("DEBUG: matchAny returned: %v\n", isMatch)
// fmt.Printf("DEBUG: matchAny returned: %v\n", isMatch)
if isMatch {
ignorable = append(ignorable, rec)
} else {
@ -194,7 +200,7 @@ func processIgnoreAndNoPurge(domain string, existing, desired, absences models.R
}
}
}
return ignorable, foreign
return ignorable, foreign, nil
}
// findConflicts takes a list of recs and a list of (compiled) UnmanagedConfigs
@ -247,7 +253,7 @@ func compileUnmanagedConfigs(configs []*models.UnmanagedConfig) error {
// matchAny returns true if rec matches any of the uconfigs.
func matchAny(uconfigs []*models.UnmanagedConfig, rec *models.RecordConfig) bool {
//fmt.Printf("DEBUG: matchAny(%s, %q, %q, %q)\n", models.DebugUnmanagedConfig(uconfigs), rec.NameFQDN, rec.Type, rec.GetTargetField())
// fmt.Printf("DEBUG: matchAny(%s, %q, %q, %q)\n", models.DebugUnmanagedConfig(uconfigs), rec.NameFQDN, rec.Type, rec.GetTargetField())
for _, uc := range uconfigs {
if matchLabel(uc.LabelGlob, rec.GetLabel()) &&
matchType(uc.RTypeMap, rec.Type) &&
@ -257,12 +263,14 @@ func matchAny(uconfigs []*models.UnmanagedConfig, rec *models.RecordConfig) bool
}
return false
}
func matchLabel(labelGlob glob.Glob, labelName string) bool {
if labelGlob == nil {
return true
}
return labelGlob.Match(labelName)
}
func matchType(typeMap map[string]struct{}, typeName string) bool {
if len(typeMap) == 0 {
return true
@ -270,6 +278,7 @@ func matchType(typeMap map[string]struct{}, typeName string) bool {
_, ok := typeMap[typeName]
return ok
}
func matchTarget(targetGlob glob.Glob, targetName string) bool {
if targetGlob == nil {
return true

View file

@ -11,7 +11,7 @@ import (
testifyrequire "github.com/stretchr/testify/require"
)
// parseZoneContents is copied verbatium from providers/bind/bindProvider.go
// parseZoneContents is copied verbatim from providers/bind/bindProvider.go
// because import cycles and... tests shouldn't depend on huge modules.
func parseZoneContents(content string, zoneName string, zonefileName string) (models.Records, error) {
zp := dns.NewZoneParser(strings.NewReader(content), zoneName, zonefileName)
@ -47,7 +47,7 @@ func handsoffHelper(t *testing.T, existingZone, desiredJs string, noPurge bool,
existing, err := parseZoneContents(existingZone, "f.com", "no_file_name")
if err != nil {
panic(err)
t.Fatal(err)
}
dnsconfig, err := js.ExecuteJavascriptString([]byte(desiredJs), false, nil)
@ -68,13 +68,16 @@ func handsoffHelper(t *testing.T, existingZone, desiredJs string, noPurge bool,
absences[i].SetLabel(j.GetLabel(), "f.com")
}
ignored, purged := processIgnoreAndNoPurge(
ignored, purged, err := processIgnoreAndNoPurge(
"f.com",
existing, desired,
absences,
unmanagedConfigs,
noPurge,
)
if err != nil {
t.Fatal(err)
}
ignoredRecs := showRecs(ignored)
purgedRecs := showRecs(purged)

View file

@ -1,10 +0,0 @@
package diff2
import "golang.org/x/exp/constraints"
func min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}

View file

@ -145,7 +145,6 @@ func (edges Edges[T]) RemoveNode(toRemove *Node[T]) Edges[T] {
// Contains returns true if a node is in the graph AND is in that direction.
func (edges Edges[T]) Contains(toFind *Node[T], direction edgeDirection) bool {
for _, edge := range edges {
if edge.Node == toFind && edge.Direction == direction {
return true

View file

@ -58,7 +58,7 @@ func Test_RemoveNode(t *testing.T) {
// example.com change has been removed
nodes := graph.Tree.Get("example.com")
assert.Len(t, nodes, 0)
assert.Empty(t, nodes)
nodes = graph.Tree.Get("a.hq.example.com")
assert.Len(t, nodes, 1)

View file

@ -22,7 +22,6 @@ func SortUsingGraph[T dnsgraph.Graphable](records []T) SortResult[T] {
sortState := createDirectedSortState(records)
for sortState.hasWork() {
for _, node := range sortState.graph.All {
sortState.hasResolvedLastRound = false

View file

@ -9,7 +9,6 @@ import (
)
func Test_graphsort(t *testing.T) {
t.Run("Direct dependency",
executeGraphSort(
[]testutils.StubRecord{

View file

@ -7,7 +7,6 @@ import (
)
func Test_domaintree(t *testing.T) {
t.Run("Single FQDN",
executeTreeTest(
[]string{

View file

@ -18,7 +18,7 @@ func hashFunc(call otto.FunctionCall) otto.Value {
algorithm := call.Argument(0).String() // The algorithm to use for hashing
value := call.Argument(1).String() // The value to hash
//lint:ignore SA4006 work around bug in staticcheck. This value is needed if the switch statement follows the default path.
result := otto.Value{}
result := otto.Value{} //nolint:staticcheck
fmt.Printf("%s\n", value)
switch algorithm {

View file

@ -51,7 +51,6 @@ func ExecuteJavaScript(file string, devMode bool, variables map[string]string) (
// ExecuteJavascriptString accepts a string containing javascript and runs it, returning the resulting dnsConfig.
func ExecuteJavascriptString(script []byte, devMode bool, variables map[string]string) (*models.DNSConfig, error) {
vm := otto.New()
l := loop.New(vm)
@ -69,16 +68,26 @@ func ExecuteJavascriptString(script []byte, devMode bool, variables map[string]s
}
}
vm.Set("require", require)
vm.Set("REV", reverse)
vm.Set("REVCOMPAT", reverseCompat)
vm.Set("glob", listFiles) // used for require_glob()
vm.Set("PANIC", jsPanic)
vm.Set("HASH", hashFunc)
// add functions to otto
functions := map[string]interface{}{
"require": require,
"REV": reverse,
"REVCOMPAT": reverseCompat,
"glob": listFiles, // used for require_glob()
"PANIC": jsPanic,
"HASH": hashFunc,
}
for name, fn := range functions {
if err := vm.Set(name, fn); err != nil {
return nil, err
}
}
// add cli variables to otto
for key, value := range variables {
vm.Set(key, value)
if err := vm.Set(key, value); err != nil {
return nil, err
}
}
helperJs := GetHelpers(devMode)
@ -150,15 +159,14 @@ func require(call otto.FunctionCall) otto.Value {
printer.Debugf("requiring: %s (%s)\n", file, relFile)
// quick fix, by replacing to linux slashes, to make it work with windows paths too.
data, err := os.ReadFile(filepath.ToSlash(relFile))
if err != nil {
throw(call.Otto, err.Error())
}
var value = otto.TrueValue()
value := otto.TrueValue()
// If its a json file return the json value, else default to true
var ext = strings.ToLower(filepath.Ext(relFile))
ext := strings.ToLower(filepath.Ext(relFile))
if strings.HasSuffix(ext, "json") || strings.HasSuffix(ext, "json5") {
cmd := fmt.Sprintf(`JSON.parse(JSON.stringify(%s))`, string(data))
value, err = call.Otto.Run(cmd)
@ -201,7 +209,7 @@ func listFiles(call otto.FunctionCall) otto.Value {
}
// Second: Recursive?
var recursive = true
recursive := true
if call.Argument(1).IsDefined() && !call.Argument(1).IsNull() {
if call.Argument(1).IsBoolean() {
recursive, _ = call.Argument(1).ToBoolean() // If it should be recursive
@ -211,7 +219,7 @@ func listFiles(call otto.FunctionCall) otto.Value {
}
// Third: File extension filter.
var fileExtension = ".js"
fileExtension := ".js"
if call.Argument(2).IsDefined() && !call.Argument(2).IsNull() {
if call.Argument(2).IsString() {
fileExtension = call.Argument(2).String() // Which file extension to filter for.
@ -247,7 +255,7 @@ func listFiles(call otto.FunctionCall) otto.Value {
// ONLY skip, when the file extension is NOT matching, or when filter is NOT disabled.
return nil
}
//dirPath := filepath.ToSlash(filepath.Dir(path)) + "/"
// dirPath := filepath.ToSlash(filepath.Dir(path)) + "/"
files = append(files, path)
return err
})

View file

@ -23,7 +23,10 @@ const (
)
func init() {
os.Chdir("../..") // go up a directory so we helpers.js is in a consistent place.
// go up a directory so we helpers.js is in a consistent place.
if err := os.Chdir("../.."); err != nil {
panic(err)
}
}
func TestParsedFiles(t *testing.T) {
@ -56,8 +59,8 @@ func TestParsedFiles(t *testing.T) {
}
for _, dc := range conf.Domains {
//fmt.Printf("DEBUG: PrettySort: domain=%q #rec=%d\n", dc.Name, len(dc.Records))
//fmt.Printf("DEBUG: records = %d %v\n", len(dc.Records), dc.Records)
// fmt.Printf("DEBUG: PrettySort: domain=%q #rec=%d\n", dc.Name, len(dc.Records))
// fmt.Printf("DEBUG: records = %d %v\n", len(dc.Records), dc.Records)
ps := prettyzone.PrettySort(dc.Records, dc.Name, 0, nil)
dc.Records = ps.Records
if len(dc.Records) == 0 {
@ -67,7 +70,7 @@ func TestParsedFiles(t *testing.T) {
// Initialize any DNS providers mentioned.
for _, dProv := range conf.DNSProviders {
var pcfg = map[string]string{}
pcfg := map[string]string{}
if dProv.Type == "-" {
// Pretend any "look up provider type in creds.json" results
@ -101,8 +104,10 @@ func TestParsedFiles(t *testing.T) {
es := string(expectedJSON)
as := string(actualJSON)
_, _ = es, as
// When debugging, leave behind the actual result:
os.WriteFile(expectedFile+".ACTUAL", []byte(as), 0644) // Leave behind the actual result:
// Leave behind the actual result:
if err := os.WriteFile(expectedFile+".ACTUAL", []byte(as), 0o644); err != nil {
t.Fatal(err)
}
testifyrequire.JSONEqf(t, es, as, "EXPECTING %q = \n```\n%s\n```", expectedFile, as)
// For each domain, if there is a zone file, test against it:
@ -128,16 +133,16 @@ func TestParsedFiles(t *testing.T) {
as := actualZone
if es != as {
// On failure, leave behind the .ACTUAL file.
os.WriteFile(zoneFile+".ACTUAL", []byte(actualZone), 0644)
if err := os.WriteFile(zoneFile+".ACTUAL", []byte(actualZone), 0o644); err != nil {
t.Fatal(err)
}
}
testifyrequire.Equal(t, es, as, "EXPECTING %q =\n```\n%s```", zoneFile, as)
}
if dCount > 0 && (len(conf.Domains) != dCount) {
t.Fatal(fmt.Errorf("only %d of %d domains in %q have zonefiles", dCount, len(conf.Domains), name))
}
})
}
}
@ -160,6 +165,5 @@ func TestErrors(t *testing.T) {
t.Fatal("Expected error but found none")
}
})
}
}

View file

@ -49,7 +49,7 @@ func DetermineNameserversForProviders(dc *models.DomainConfig, providers []*mode
if n > 0 && n < take {
take = n
}
for i := 0; i < take; i++ {
for i := range take {
ns = append(ns, nss[i])
}
}
@ -78,7 +78,9 @@ func AddNSRecords(dc *models.DomainConfig) {
if !strings.HasSuffix(t, ".") {
t += "."
}
rc.SetTarget(t)
if err := rc.SetTarget(t); err != nil {
fmt.Printf("failed AddNSRecords rc.SetTarget(%q): %s\n", t, err)
}
dc.Records = append(dc.Records, rc)
}

View file

@ -9,14 +9,16 @@ import (
"testing"
)
const providersImportDir = "../../providers"
const providersPackageName = "providers"
const (
providersImportDir = "../../providers"
providersPackageName = "providers"
)
func TestCapabilitiesAreFiltered(t *testing.T) {
// Any capabilities which we wish to whitelist because it's not directly
// something we can test against.
skipCheckCapabilities := make(map[string]struct{})
//skipCheckCapabilities["CanUseBlahBlahBlah"] = struct{}{}
// skipCheckCapabilities["CanUseBlahBlahBlah"] = struct{}{}
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, providersImportDir, nil, 0)
@ -70,5 +72,4 @@ func TestCapabilitiesAreFiltered(t *testing.T) {
t.Errorf("MISSING: providers.%s (%d) is not checked by checkProviderCapabilities", capName, capInt)
}
}
}

View file

@ -56,7 +56,6 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
}
// now split if needed
if split, ok := txt.Metadata["split"]; ok {
overhead1 := 0
// overhead1: The first segment of the SPF record
// needs to be shorter than the others due to the overhead of
@ -91,10 +90,14 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
for _, k := range sortedKeys(recs) {
v := recs[k]
if k == "@" {
txt.SetTargetTXTs(v)
if err := txt.SetTargetTXTs(v); err != nil {
errs = append(errs, err)
}
} else {
cp, _ := txt.Copy()
cp.SetTargetTXTs(v)
if err := cp.SetTargetTXTs(v); err != nil {
errs = append(errs, err)
}
cp.SetLabelFromFQDN(k, domain.Name)
domain.Records = append(domain.Records, cp)
}
@ -107,7 +110,7 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
}
// check if cache is stale
for _, e := range cache.ResolveErrors() {
errs = append(errs, Warning{fmt.Errorf("problem resolving SPF record: %s", e)})
errs = append(errs, Warning{fmt.Errorf("problem resolving SPF record: %w", e)})
}
if len(cache.ResolveErrors()) == 0 {
changed := cache.ChangedRecords()

View file

@ -8,12 +8,11 @@ import (
func makeRC(label, domain, target string, rc models.RecordConfig) *models.RecordConfig {
rc.SetLabel(label, domain)
rc.SetTarget(target)
rc.MustSetTarget(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"
const transformSingle = "0.0.0.0~1.1.1.1~~8.0.0.0"
src := &models.DomainConfig{

View file

@ -5,6 +5,7 @@ import (
"fmt"
"net"
"sort"
"strconv"
"strings"
"github.com/StackExchange/dnscontrol/v4/models"
@ -35,7 +36,7 @@ func checkTarget(target string) error {
return nil
}
if target == "" {
return fmt.Errorf("empty target")
return errors.New("empty target")
}
if strings.ContainsAny(target, `'" +,|!£$%&()=?^*ç°§;:<>[]()@`) {
return fmt.Errorf("target (%v) includes invalid char", target)
@ -53,7 +54,7 @@ func checkTarget(target string) error {
// validateRecordTypes list of valid rec.Type values. Returns true if this is a real DNS record type, false means it is a pseudo-type used internally.
func validateRecordTypes(rec *models.RecordConfig, domain string, pTypes []string) error {
// #rtype_variations
var validTypes = map[string]bool{
validTypes := map[string]bool{
"A": true,
"AAAA": true,
"ALIAS": false,
@ -230,12 +231,12 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
default:
if rec.Metadata["orig_custom_type"] != "" {
// it is a valid custom type. We perform no validation on target
return
return errs
}
errs = append(errs, fmt.Errorf("checkTargets: Unimplemented record type (%v) domain=%v name=%v",
rec.Type, domain, rec.GetLabel()))
}
return
return errs
}
func transformCNAME(target, oldDomain, newDomain, suffixstrip string) string {
@ -270,7 +271,8 @@ func transformLabel(label, suffixstrip string) (string, error) {
// import_transform imports the records of one zone into another, modifying records along the way.
func importTransform(srcDomain, dstDomain *models.DomainConfig,
transforms []transform.IPConversion, ttl uint32, suffixstrip string) error {
transforms []transform.IPConversion, ttl uint32, suffixstrip string,
) error {
// Read srcDomain.Records, transform, and append to dstDomain.Records:
// 1. Skip any that aren't A or CNAMEs.
// 2. Append destDomainname to the end of the label.
@ -290,7 +292,7 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig,
case "A":
trs, err := transform.IPToList(net.ParseIP(rec.GetTargetField()), transforms)
if err != nil {
return fmt.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.GetTargetField(), transforms, err)
return fmt.Errorf("import_transform: TransformIP(%v, %v) returned err=%w", rec.GetTargetField(), transforms, err)
}
for _, tr := range trs {
r := newRec(rec, ttl)
@ -299,7 +301,9 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig,
return err
}
r.SetLabel(l, dstDomain.Name)
r.SetTarget(tr.String())
if err := r.SetTarget(tr.String()); err != nil {
return err
}
dstDomain.Records = append(dstDomain.Records, r)
}
case "CNAME":
@ -309,7 +313,9 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig,
return err
}
r.SetLabel(l, dstDomain.Name)
r.SetTarget(transformCNAME(r.GetTargetField(), srcDomain.Name, dstDomain.Name, suffixstrip))
if err := r.SetTarget(transformCNAME(r.GetTargetField(), srcDomain.Name, dstDomain.Name, suffixstrip)); err != nil {
return err
}
dstDomain.Records = append(dstDomain.Records, r)
default:
// Anything else is ignored.
@ -376,7 +382,6 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
// Normalize Records.
models.PostProcessRecords(domain.Records)
for _, rec := range domain.Records {
if rec.TTL == 0 {
rec.TTL = models.DefaultTTL
}
@ -425,9 +430,13 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
if rec.SubDomain != "" {
origin = rec.SubDomain + "." + origin
}
rec.SetTarget(dnsutil.AddOrigin(rec.GetTargetField(), origin))
if err := rec.SetTarget(dnsutil.AddOrigin(rec.GetTargetField(), origin)); err != nil {
errs = append(errs, err)
}
} else if rec.Type == "A" || rec.Type == "AAAA" {
rec.SetTarget(net.ParseIP(rec.GetTargetField()).String())
if err := rec.SetTarget(net.ParseIP(rec.GetTargetField()).String()); err != nil {
errs = append(errs, err)
}
} else if rec.Type == "PTR" {
var err error
var name string
@ -460,7 +469,6 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
if _, ok := rec.Metadata["ignore_name_disable_safety_check"]; ok {
errs = append(errs, errors.New("IGNORE_NAME_DISABLE_SAFETY_CHECK no longer supported. Please use DISABLE_IGNORE_SAFETY_CHECK for the entire domain"))
}
}
}
@ -481,7 +489,7 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
}
c := config.FindDomain(rec.GetTargetField())
if c == nil {
err = fmt.Errorf("IMPORT_TRANSFORM mentions non-existant domain %q", rec.GetTargetField())
err = fmt.Errorf("IMPORT_TRANSFORM mentions non-existent domain %q", rec.GetTargetField())
errs = append(errs, err)
}
err = importTransform(c, domain, table, rec.TTL, suffixstrip)
@ -677,7 +685,6 @@ func checkRecordSetHasMultipleTTLs(records []*models.RecordConfig) (errs []error
func formatInconsistency(r map[string]map[uint32]bool) string {
var rtypeResult []string
for rtype, ttlsMap := range r {
ttlList := make([]int, len(ttlsMap))
i := 0
for k := range ttlsMap {
@ -696,7 +703,7 @@ func formatInconsistency(r map[string]map[uint32]bool) string {
func commaSepInts(list []int) string {
slist := make([]string, len(list))
for i, v := range list {
slist[i] = fmt.Sprintf("%d", v)
slist[i] = strconv.Itoa(v)
}
return strings.Join(slist, ",")
}
@ -707,7 +714,7 @@ func commaSepInts(list []int) string {
var providerCapabilityChecks = []pairTypeCapability{
// #rtype_variations
// If a zone uses rType X, the provider must support capability Y.
//{"X", providers.Y},
// {"X", providers.Y},
capabilityCheck("AKAMAICDN", providers.CanUseAKAMAICDN),
capabilityCheck("ALIAS", providers.CanUseAlias),
capabilityCheck("AUTODNSSEC", providers.CanAutoDNSSEC),
@ -803,7 +810,6 @@ func checkProviderCapabilities(dc *models.DomainConfig) error {
break
}
}
}
if !hasAny {
continue
@ -854,15 +860,20 @@ func applyRecordTransforms(domain *models.DomainConfig) error {
}
for i, newIP := range newIPs {
if i == 0 && !newIP.Equal(ip) {
rec.SetTarget(newIP.String()) // replace target of first record if different
// replace target of first record if different
if err := rec.SetTarget(newIP.String()); err != nil {
return err
}
} else if i > 0 {
// any additional ips need identical records with the alternate ip added to the domain
copy, err := rec.Copy()
cpy, err := rec.Copy()
if err != nil {
return err
}
copy.SetTarget(newIP.String())
domain.Records = append(domain.Records, copy)
if err := cpy.SetTarget(newIP.String()); err != nil {
return err
}
domain.Records = append(domain.Records, cpy)
}
}
}

View file

@ -9,7 +9,7 @@ import (
)
func TestSoaLabelAndTarget(t *testing.T) {
var tests = []struct {
tests := []struct {
isError bool
label string
target string
@ -22,8 +22,10 @@ func TestSoaLabelAndTarget(t *testing.T) {
}
for _, test := range tests {
experiment := fmt.Sprintf("%s %s", test.label, test.target)
rc := makeRC(test.label, "foo.com", test.target, models.RecordConfig{Type: "SOA",
SoaExpire: 1, SoaMinttl: 1, SoaRefresh: 1, SoaRetry: 1, SoaSerial: 1, SoaMbox: "bar.foo.com"})
rc := makeRC(test.label, "foo.com", test.target, models.RecordConfig{
Type: "SOA",
SoaExpire: 1, SoaMinttl: 1, SoaRefresh: 1, SoaRetry: 1, SoaSerial: 1, SoaMbox: "bar.foo.com",
})
err := checkTargets(rc, "foo.com")
if err != nil && !test.isError {
t.Errorf("%v: Error (%v)\n", experiment, err)
@ -35,7 +37,7 @@ func TestSoaLabelAndTarget(t *testing.T) {
}
func TestCheckSoa(t *testing.T) {
var tests = []struct {
tests := []struct {
isError bool
expire uint32
minttl uint32
@ -75,7 +77,7 @@ func TestCheckSoa(t *testing.T) {
}
func TestCheckLabel(t *testing.T) {
var tests = []struct {
tests := []struct {
label string
rType string
target string
@ -109,7 +111,6 @@ func TestCheckLabel(t *testing.T) {
t.Errorf("%02d: Expected error but got none", i)
}
})
}
}
@ -123,7 +124,7 @@ func checkError(t *testing.T, err error, shouldError bool, experiment string) {
}
func Test_assert_valid_ipv4(t *testing.T) {
var tests = []struct {
tests := []struct {
experiment string
isError bool
}{
@ -140,7 +141,7 @@ func Test_assert_valid_ipv4(t *testing.T) {
}
func Test_assert_valid_target(t *testing.T) {
var tests = []struct {
tests := []struct {
experiment string
isError bool
}{
@ -162,7 +163,7 @@ func Test_assert_valid_target(t *testing.T) {
}
func Test_transform_cname(t *testing.T) {
var tests = []struct {
tests := []struct {
experiment string
expected string
}{
@ -182,41 +183,71 @@ func Test_transform_cname(t *testing.T) {
}
func Test_transform_cname_strip(t *testing.T) {
var tests = []struct {
tests := []struct {
p []string
expected string
}{
{[]string{"ai.meta.stackexchange.com.", "stackexchange.com", "com.internal", "com"},
"ai.meta.stackexchange.com.internal."},
{[]string{"askubuntu.com.", "askubuntu.com", "com.internal", "com"},
"askubuntu.com.internal."},
{[]string{"blogoverflow.com.", "stackoverflow.com", "com.internal", "com"},
"blogoverflow.com.internal."},
{[]string{"careers.stackoverflow.com.", "stackoverflow.com", "com.internal", "com"},
"careers.stackoverflow.com.internal."},
{[]string{"chat.stackexchange.com.", "askubuntu.com", "com.internal", "com"},
"chat.stackexchange.com.internal."},
{[]string{"chat.stackexchange.com.", "stackoverflow.com", "com.internal", "com"},
"chat.stackexchange.com.internal."},
{[]string{"chat.stackexchange.com.", "superuser.com", "com.internal", "com"},
"chat.stackexchange.com.internal."},
{[]string{"sstatic.net.", "sstatic.net", "net.internal", "net"},
"sstatic.net.internal."},
{[]string{"stackapps.com.", "stackapps.com", "com.internal", "com"},
"stackapps.com.internal."},
{[]string{"stackexchange.com.", "stackexchange.com", "com.internal", "com"},
"stackexchange.com.internal."},
{[]string{"stackoverflow.com.", "stackoverflow.com", "com.internal", "com"},
"stackoverflow.com.internal."},
{[]string{"superuser.com.", "superuser.com", "com.internal", "com"},
"superuser.com.internal."},
{[]string{"teststackoverflow.com.", "teststackoverflow.com", "com.internal", "com"},
"teststackoverflow.com.internal."},
{[]string{"webapps.stackexchange.com.", "stackexchange.com", "com.internal", "com"},
"webapps.stackexchange.com.internal."},
{
[]string{"ai.meta.stackexchange.com.", "stackexchange.com", "com.internal", "com"},
"ai.meta.stackexchange.com.internal.",
},
{
[]string{"askubuntu.com.", "askubuntu.com", "com.internal", "com"},
"askubuntu.com.internal.",
},
{
[]string{"blogoverflow.com.", "stackoverflow.com", "com.internal", "com"},
"blogoverflow.com.internal.",
},
{
[]string{"careers.stackoverflow.com.", "stackoverflow.com", "com.internal", "com"},
"careers.stackoverflow.com.internal.",
},
{
[]string{"chat.stackexchange.com.", "askubuntu.com", "com.internal", "com"},
"chat.stackexchange.com.internal.",
},
{
[]string{"chat.stackexchange.com.", "stackoverflow.com", "com.internal", "com"},
"chat.stackexchange.com.internal.",
},
{
[]string{"chat.stackexchange.com.", "superuser.com", "com.internal", "com"},
"chat.stackexchange.com.internal.",
},
{
[]string{"sstatic.net.", "sstatic.net", "net.internal", "net"},
"sstatic.net.internal.",
},
{
[]string{"stackapps.com.", "stackapps.com", "com.internal", "com"},
"stackapps.com.internal.",
},
{
[]string{"stackexchange.com.", "stackexchange.com", "com.internal", "com"},
"stackexchange.com.internal.",
},
{
[]string{"stackoverflow.com.", "stackoverflow.com", "com.internal", "com"},
"stackoverflow.com.internal.",
},
{
[]string{"superuser.com.", "superuser.com", "com.internal", "com"},
"superuser.com.internal.",
},
{
[]string{"teststackoverflow.com.", "teststackoverflow.com", "com.internal", "com"},
"teststackoverflow.com.internal.",
},
{
[]string{"webapps.stackexchange.com.", "stackexchange.com", "com.internal", "com"},
"webapps.stackexchange.com.internal.",
},
//
{[]string{"sstatic.net.", "sstatic.net", "com.internal", "com"},
"sstatic.net.internal."},
{
[]string{"sstatic.net.", "sstatic.net", "com.internal", "com"},
"sstatic.net.internal.",
},
}
for _, test := range tests {
@ -231,7 +262,7 @@ func TestNSAtRoot(t *testing.T) {
// do not allow ns records for @
rec := &models.RecordConfig{Type: "NS"}
rec.SetLabel("test", "foo.com")
rec.SetTarget("ns1.name.com.")
rec.MustSetTarget("ns1.name.com.")
errs := checkTargets(rec, "foo.com")
if len(errs) > 0 {
t.Error("Expect no error with ns record on subdomain")
@ -246,7 +277,7 @@ func TestNSAtRoot(t *testing.T) {
func TestNS1URLFWDValid(t *testing.T) {
rec := &models.RecordConfig{Type: "NS1_URLFWD"}
rec.SetLabel("test1", "foo.com")
rec.SetTarget("/ http://example.com 302 2 0")
rec.MustSetTarget("/ http://example.com 302 2 0")
errs := checkTargets(rec, "foo.com")
if len(errs) > 0 {
@ -257,7 +288,7 @@ func TestNS1URLFWDValid(t *testing.T) {
func TestNS1URLFWDInvalid(t *testing.T) {
rec := &models.RecordConfig{Type: "NS1_URLFWD"}
rec.SetLabel("test2", "foo.com")
rec.SetTarget("/ http://example.com 302 2")
rec.MustSetTarget("/ http://example.com 302 2")
errs := checkTargets(rec, "foo.com")
if len(errs) == 0 {
@ -266,7 +297,7 @@ func TestNS1URLFWDInvalid(t *testing.T) {
}
func TestTransforms(t *testing.T) {
var tests = []struct {
tests := []struct {
givenIP string
expectedRecords []string
}{
@ -300,9 +331,9 @@ func TestTransforms(t *testing.T) {
}
func TestCNAMEMutex(t *testing.T) {
var recA = &models.RecordConfig{Type: "CNAME"}
recA := &models.RecordConfig{Type: "CNAME"}
recA.SetLabel("foo", "foo.example.com")
recA.SetTarget("example.com.")
recA.MustSetTarget("example.com.")
tests := []struct {
rType string
name string
@ -315,9 +346,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}
recB := &models.RecordConfig{Type: tst.rType}
recB.SetLabel(tst.name, "example.com")
recB.SetTarget("example2.com.")
recB.MustSetTarget("example2.com.")
dc := &models.DomainConfig{
Name: "example.com",
Records: []*models.RecordConfig{recA, recB},
@ -479,7 +510,8 @@ func TestTLSAValidation(t *testing.T) {
RegistrarName: "BIND",
Records: []*models.RecordConfig{
makeRC("_443._tcp", "_443._tcp.example.com", "abcdef0", models.RecordConfig{
Type: "TLSA", TlsaUsage: 4, TlsaSelector: 1, TlsaMatchingType: 1}),
Type: "TLSA", TlsaUsage: 4, TlsaSelector: 1, TlsaMatchingType: 1,
}),
},
},
},

View file

@ -30,7 +30,7 @@ func (b bonfireNotifier) Notify(domain, provider, msg string, err error, preview
// chat doesn't markdownify multiline messages. Split in two so the first line can have markdown
parts := strings.SplitN(payload, "\n", 2)
for _, p := range parts {
http.Post(string(b), "text/markdown", strings.NewReader(p))
_, _ = http.Post(string(b), "text/markdown", strings.NewReader(p))
}
}

View file

@ -40,7 +40,6 @@ func stripAnsiColors(colored string) string {
}
func (m multiNotifier) Notify(domain, provider string, message string, err error, preview bool) {
// force-remove ansi colors that might come with the message from dnscontrol.
// These usually don't render well in notifiers, outputting escape codes.
// If a notifier wants to output colors, they should probably implement
@ -50,6 +49,7 @@ func (m multiNotifier) Notify(domain, provider string, message string, err error
n.Notify(domain, provider, nMsg, err, preview)
}
}
func (m multiNotifier) Done() {
for _, n := range m {
n.Done()

View file

@ -3,7 +3,6 @@ package notifications
import "testing"
func Test_stripAnsiColorsValid(t *testing.T) {
coloredStr := "\x1b[0133myellow\x1b[0m" // 33 == yellow
nonColoredStr := "yellow"
@ -14,7 +13,6 @@ func Test_stripAnsiColorsValid(t *testing.T) {
}
func Test_stripAnsiColorsInvalid(t *testing.T) {
coloredStr := "\x1b[01AAmyellow\x1b[0m" // AA not a real color
nonColoredStr := "yellow"

View file

@ -26,7 +26,7 @@ func (b shoutrrrNotifier) Notify(domain, provider, msg string, err error, previe
} else {
payload = fmt.Sprintf("DNSControl successfully ran correction for %s[%s]:\n%s", domain, provider, msg)
}
shoutrrr.Send(string(b), payload)
_ = shoutrrr.Send(string(b), payload)
}
func (b shoutrrrNotifier) Done() {}

View file

@ -40,7 +40,7 @@ func (s *slackNotifier) Notify(domain, provider, msg string, err error, preview
}
json, _ := json.Marshal(payload)
http.Post(s.URL, "text/json", bytes.NewReader(json))
_, _ = http.Post(s.URL, "text/json", bytes.NewReader(json))
}
func (s *slackNotifier) Done() {}

View file

@ -46,7 +46,7 @@ func (s *teamsNotifier) Notify(domain, provider, msg string, err error, preview
}
json, _ := json.Marshal(payload)
http.Post(s.URL, "text/json", bytes.NewReader(json))
_, _ = http.Post(s.URL, "text/json", bytes.NewReader(json))
}
func (s *teamsNotifier) Done() {}

View file

@ -35,7 +35,7 @@ func (s *telegramNotifier) Notify(domain, provider, msg string, err error, previ
Text string `json:"text"`
}
var url = fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", s.BotToken)
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", s.BotToken)
payload.ChatID, _ = strconv.ParseInt(s.ChatID, 10, 64)
@ -50,7 +50,6 @@ func (s *telegramNotifier) Notify(domain, provider, msg string, err error, previ
marshaledPayload, _ := json.Marshal(payload)
_, _ = http.Post(url, "application/json", bytes.NewBuffer(marshaledPayload))
}
func (s *telegramNotifier) Done() {}

View file

@ -20,25 +20,25 @@ type SSH struct {
Session sshSession
}
// func (b *SSH) StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, io.Reader, error) {
// func (b *SSH) StartProcess(cmd string, args ...string) (Waiter, io.Writer, io.Reader, error)
// stdin, err := b.Session.StdinPipe()
// if err != nil {
// return nil, nil, nil, nil, errors.Annotate(err, "Could not get hold of the SSH session's stdin stream")
// return nil, errors.Annotate(err, "Could not get hold of the SSH session's stdin stream")
// }
// stdout, err := b.Session.StdoutPipe()
// if err != nil {
// return nil, nil, nil, nil, errors.Annotate(err, "Could not get hold of the SSH session's stdout stream")
// return nil, errors.Annotate(err, "Could not get hold of the SSH session's stdout stream")
// }
// stderr, err := b.Session.StderrPipe()
// if err != nil {
// return nil, nil, nil, nil, errors.Annotate(err, "Could not get hold of the SSH session's stderr stream")
// return nil, errors.Annotate(err, "Could not get hold of the SSH session's stderr stream")
// }
// err = b.Session.Start(b.createCmd(cmd, args))
// if err != nil {
// return nil, nil, nil, nil, errors.Annotate(err, "Could not spawn process via SSH")
// return nil, errors.Annotate(err, "Could not spawn process via SSH")
// }
// return b.Session, stdin, stdout, stderr, nil

View file

@ -42,6 +42,6 @@ func (s *session) Execute(cmd string) (string, string, error) {
}
func (s *session) Exit() {
s.upstream.Execute(fmt.Sprintf("Disconnect-PSSession -Session $%s", s.name))
_, _, _ = s.upstream.Execute("Disconnect-PSSession -Session $" + s.name)
s.upstream.Exit()
}

View file

@ -91,5 +91,5 @@ func (c *UserPasswordCredential) prepare(s Middleware) (interface{}, error) {
return nil, errors.Annotate(err, "Could not create PSCredential object")
}
return fmt.Sprintf("$%s", name), nil
return "$" + name, nil
}

View file

@ -59,8 +59,8 @@ func (s *shell) Execute(cmd string) (string, string, error) {
waiter := &sync.WaitGroup{}
waiter.Add(2)
go streamReader(s.stdout, outBoundary, &sout, waiter)
go streamReader(s.stderr, errBoundary, &serr, waiter)
go streamReader(s.stdout, outBoundary, &sout, waiter) //nolint:errcheck
go streamReader(s.stdout, outBoundary, &sout, waiter) //nolint:errcheck
waiter.Wait()
@ -72,7 +72,7 @@ func (s *shell) Execute(cmd string) (string, string, error) {
}
func (s *shell) Exit() {
s.stdin.Write([]byte("exit" + newline))
_, _ = s.stdin.Write([]byte("exit" + newline))
// if it's possible to close stdin, do so (some backends, like the local one,
// do support it)
@ -81,7 +81,7 @@ func (s *shell) Exit() {
closer.Close()
}
s.handle.Wait()
_ = s.handle.Wait()
s.handle = nil
s.stdin = nil

View file

@ -7,6 +7,7 @@ import (
"fmt"
"io"
"sort"
"strconv"
"strings"
"github.com/StackExchange/dnscontrol/v4/models"
@ -87,7 +88,6 @@ func PrettySort(records models.Records, origin string, defaultTTL uint32, commen
// generateZoneFileHelper creates a pretty zonefile.
func (z *ZoneGenData) generateZoneFileHelper(w io.Writer) error {
nameShortPrevious := ""
sort.Sort(z)
@ -103,7 +103,6 @@ func (z *ZoneGenData) generateZoneFileHelper(w io.Writer) error {
}
}
for i, rr := range z.Records {
// Fake types are commented out.
prefix := ""
_, ok := dns.StringToType[rr.Type]
@ -122,7 +121,7 @@ func (z *ZoneGenData) generateZoneFileHelper(w io.Writer) error {
// ttl
ttl := ""
if rr.TTL != z.DefaultTTL && rr.TTL != 0 {
ttl = fmt.Sprint(rr.TTL)
ttl = strconv.FormatUint(uint64(rr.TTL), 10)
}
// type

View file

@ -30,7 +30,9 @@ func parseAndRegen(t *testing.T, buf *bytes.Buffer, expected string) {
// Generate it back:
buf2 := &bytes.Buffer{}
writeZoneFileRR(buf2, parsed, "bosun.org")
if err := writeZoneFileRR(buf2, parsed, "bosun.org"); err != nil {
t.Fatal(err)
}
// Compare:
if buf2.String() != expected {
@ -61,6 +63,7 @@ func writeZoneFileRR(w io.Writer, records []dns.RR, origin string) error {
return WriteZoneFileRC(w, rcs, origin, 0, nil)
}
func TestMostCommonTtl(t *testing.T) {
var records []dns.RR
var g, e uint32
@ -117,7 +120,6 @@ func TestMostCommonTtl(t *testing.T) {
if e != g {
t.Fatalf("expected %d; got %d\n", e, g)
}
}
// func WriteZoneFile
@ -127,7 +129,9 @@ func TestWriteZoneFileSimple(t *testing.T) {
r2, _ := dns.NewRR("bosun.org. 300 IN A 192.30.252.154")
r3, _ := dns.NewRR("www.bosun.org. 300 IN CNAME bosun.org.")
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org"); err != nil {
t.Fatal(err)
}
expected := `$TTL 300
@ IN A 192.30.252.153
IN A 192.30.252.154
@ -148,7 +152,9 @@ func TestWriteZoneFileSimpleTtl(t *testing.T) {
r3, _ := dns.NewRR("bosun.org. 100 IN A 192.30.252.155")
r4, _ := dns.NewRR("www.bosun.org. 300 IN CNAME bosun.org.")
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4}, "bosun.org"); err != nil {
t.Fatal(err)
}
expected := `$TTL 100
@ IN A 192.30.252.153
IN A 192.30.252.154
@ -178,7 +184,9 @@ func TestWriteZoneFileMx(t *testing.T) {
r8, _ := dns.NewRR("ccc.bosun.org. IN MX 40 aaa.example.com.")
r9, _ := dns.NewRR("ccc.bosun.org. IN MX 1 ttt.example.com.")
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6, r7, r8, r9}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6, r7, r8, r9}, "bosun.org"); err != nil {
t.Fatal(err)
}
if buf.String() != testdataZFMX {
t.Log(buf.String())
t.Log(testdataZFMX)
@ -207,7 +215,9 @@ func TestWriteZoneFileSrv(t *testing.T) {
r4, _ := dns.NewRR(`bosun.org. 300 IN SRV 20 10 5050 foo.com.`)
r5, _ := dns.NewRR(`bosun.org. 300 IN SRV 10 10 5050 foo.com.`)
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5}, "bosun.org"); err != nil { // 5
t.Fatal(err)
}
if buf.String() != testdataZFSRV {
t.Log(buf.String())
t.Log(testdataZFSRV)
@ -230,7 +240,9 @@ func TestWriteZoneFilePtr(t *testing.T) {
r2, _ := dns.NewRR(`bosun.org. 300 IN PTR barney.bosun.org.`)
r3, _ := dns.NewRR(`bosun.org. 300 IN PTR alex.bosun.org.`)
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{r1, r2, r3}, "bosun.org"); err != nil {
t.Fatal(err)
}
if buf.String() != testdataZFPTR {
t.Log(buf.String())
t.Log(testdataZFPTR)
@ -254,7 +266,9 @@ func TestWriteZoneFileCaa(t *testing.T) {
r5, _ := dns.NewRR(`bosun.org. 300 IN CAA 0 iodef "https://example.net"`)
r6, _ := dns.NewRR(`bosun.org. 300 IN CAA 1 iodef "mailto:example.com"`)
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{r1, r2, r3, r4, r5, r6}, "bosun.org"); err != nil {
t.Fatal(err)
}
if buf.String() != testdataZFCAA {
t.Log(buf.String())
t.Log(testdataZFCAA)
@ -298,7 +312,9 @@ func TestWriteZoneFileTxt(t *testing.T) {
// Generate the zonefile:
buf := &bytes.Buffer{}
writeZoneFileRR(buf, []dns.RR{rr}, "bosun.org")
if err := writeZoneFileRR(buf, []dns.RR{rr}, "bosun.org"); err != nil {
t.Fatal(err)
}
gz := buf.String()
if gz != ez {
t.Log("got: " + gz)
@ -309,7 +325,6 @@ func TestWriteZoneFileTxt(t *testing.T) {
// Reverse the process. Turn the zonefile into a list of records
parseAndRegen(t, buf, ez)
}
}
// Test 1 of each record type
@ -344,7 +359,9 @@ func TestWriteZoneFileEach(t *testing.T) {
d = append(d, mustNewRR(`bosun.org. 300 IN HTTPS 1 . alpn="h3,h2"`))
d = append(d, mustNewRR(`bosun.org. 300 IN SVCB 1 . alpn="h3,h2"`))
buf := &bytes.Buffer{}
writeZoneFileRR(buf, d, "bosun.org")
if err := writeZoneFileRR(buf, d, "bosun.org"); err != nil {
t.Fatal(err)
}
if buf.String() != testdataZFEach {
t.Log(buf.String())
t.Log(testdataZFEach)
@ -390,7 +407,9 @@ func TestWriteZoneFileSynth(t *testing.T) {
recs = append(recs, rsynz)
buf := &bytes.Buffer{}
WriteZoneFileRC(buf, recs, "bosun.org", 0, []string{"c1", "c2", "c3\nc4"})
if err := WriteZoneFileRC(buf, recs, "bosun.org", 0, []string{"c1", "c2", "c3\nc4"}); err != nil {
t.Fatal(err)
}
expected := `$TTL 300
; c1
; c2
@ -438,7 +457,9 @@ func TestWriteZoneFileOrder(t *testing.T) {
}
buf := &bytes.Buffer{}
writeZoneFileRR(buf, records, "stackoverflow.com")
if err := writeZoneFileRR(buf, records, "stackoverflow.com"); err != nil {
t.Fatal(err)
}
// Compare
if buf.String() != testdataOrder {
t.Log("Found:")
@ -458,7 +479,9 @@ func TestWriteZoneFileOrder(t *testing.T) {
}
// Generate
buf := &bytes.Buffer{}
writeZoneFileRR(buf, records, "stackoverflow.com")
if err := writeZoneFileRR(buf, records, "stackoverflow.com"); err != nil {
t.Fatal(err)
}
// Compare
if buf.String() != testdataOrder {
t.Log(buf.String())
@ -532,7 +555,7 @@ func TestZoneLabelLess(t *testing.T) {
zap
*/
var tests = []struct {
tests := []struct {
e1, e2 string
expected bool
}{
@ -584,7 +607,7 @@ func TestZoneRrtypeLess(t *testing.T) {
In zonefiles we want to list SOAs, then NSs, then all others.
*/
var tests = []struct {
tests := []struct {
e1, e2 string
expected bool
}{

View file

@ -29,7 +29,7 @@ func (z *ZoneGenData) Less(i, j int) bool {
//fmt.Printf("DEBUG: LabelLess(%q, %q) = %v %q %q\n", compA, compB, LabelLess(compA, compB), a.Name, b.Name)
compA, compB := a.NameFQDN, b.NameFQDN
// If we are at the apex, pass "@" to the Less function.
// Unify FQDNs to "@". LabelLess needs FQDNs to be "@" to work properly.
if a.Name == "@" {
compA = "@"
}
@ -68,7 +68,7 @@ func (z *ZoneGenData) Less(i, j int) bool {
}
return a.MxPreference < b.MxPreference
case "SRV":
//ta2, tb2 := a.(*dns.SRV), b.(*dns.SRV)
// ta2, tb2 := a.(*dns.SRV), b.(*dns.SRV)
pa, pb := a.SrvPort, b.SrvPort
if pa != pb {
return pa < pb
@ -88,13 +88,13 @@ func (z *ZoneGenData) Less(i, j int) bool {
}
return a.SvcPriority < b.SvcPriority
case "PTR":
//ta2, tb2 := a.(*dns.PTR), b.(*dns.PTR)
// ta2, tb2 := a.(*dns.PTR), b.(*dns.PTR)
pa, pb := a.GetTargetField(), b.GetTargetField()
if pa != pb {
return pa < pb
}
case "CAA":
//ta2, tb2 := a.(*dns.CAA), b.(*dns.CAA)
// ta2, tb2 := a.(*dns.CAA), b.(*dns.CAA)
// sort by tag
pa, pb := a.CaaTag, b.CaaTag
if pa != pb {
@ -123,7 +123,7 @@ func (z *ZoneGenData) Less(i, j int) bool {
default:
// pass through. String comparison is sufficient.
}
//fmt.Printf("DEBUG: Less %q < %q == %v\n", a.String(), b.String(), a.String() < b.String())
// fmt.Printf("DEBUG: Less %q < %q == %v\n", a.String(), b.String(), a.String() < b.String())
return a.String() < b.String()
}
@ -138,7 +138,7 @@ func LabelLess(a, b string) bool {
}
// Sort @ at the top, then *, then everything else lexigraphically.
// i.e. @ always is less. * is is less than everything but @.
// i.e. @ always is less. * is less than everything but @.
if a == "@" {
return true
}
@ -171,11 +171,10 @@ func LabelLess(a, b string) bool {
for i, j := ia, ib; minIdx >= 0; i, j, minIdx = i-1, j-1, minIdx-1 {
// Compare as[i] < bs[j]
// Sort @ at the top, then *, then everything else.
// i.e. @ always is less. * is is less than everything but @.
// i.e. @ always is less. * is less than everything but @.
// If both are numeric, compare as integers, otherwise as strings.
if as[i] != bs[j] {
// If the first element is *, it is always less.
if i == 0 && as[i] == "*" {
return true
@ -207,7 +206,8 @@ func zoneRrtypeLess(a, b string) bool {
// List SOAs, NSs, etc. then all others alphabetically.
for _, t := range []string{"SOA", "NS", "CNAME",
for _, t := range []string{
"SOA", "NS", "CNAME",
"A", "AAAA", "MX", "SRV", "TXT",
} {
if a == t {

View file

@ -32,7 +32,7 @@ type Printer interface {
Println(lines ...string)
Warnf(fmt string, args ...interface{})
Errorf(fmt string, args ...interface{})
PrintfIf(print bool, fmt string, args ...interface{})
PrintfIf(prnt bool, fmt string, args ...interface{})
}
// Debugf is called to print/format debug information.
@ -61,20 +61,18 @@ func Warnf(fmt string, args ...interface{}) {
// }
// PrintfIf is called to optionally print something.
func PrintfIf(print bool, fmt string, args ...interface{}) {
DefaultPrinter.PrintfIf(print, fmt, args...)
func PrintfIf(prnt bool, fmt string, args ...interface{}) {
DefaultPrinter.PrintfIf(prnt, fmt, args...)
}
var (
// DefaultPrinter is the default Printer, used by Debugf, Printf, and Warnf.
DefaultPrinter = &ConsolePrinter{
Reader: bufio.NewReader(os.Stdin),
Writer: os.Stdout,
Verbose: false,
}
)
// DefaultPrinter is the default Printer, used by Debugf, Printf, and Warnf.
var DefaultPrinter = &ConsolePrinter{
Reader: bufio.NewReader(os.Stdin),
Writer: os.Stdout,
Verbose: false,
}
// SkinnyReport is true to to disable certain print statements.
// SkinnyReport is true to disable certain print statements.
// This is a hack until we have the new printer replacement. The long
// variable name is easy to grep for when we make the conversion.
var SkinnyReport = true
@ -211,8 +209,8 @@ func (c ConsolePrinter) Errorf(format string, args ...interface{}) {
}
// PrintfIf is called to optionally print/format a message.
func (c ConsolePrinter) PrintfIf(print bool, format string, args ...interface{}) {
if print {
func (c ConsolePrinter) PrintfIf(prnt bool, format string, args ...interface{}) {
if prnt {
fmt.Fprintf(c.Writer, format, args...)
}
}

View file

@ -25,7 +25,7 @@ func NewFromRecords(recs models.Records) *RecordDB {
// ContainsLT returns true if recdb contains rec. Matching is done
// on the record's label and type (i.e. the RecordKey)
//func (recdb RecordDB) ContainsLT(rec *models.RecordConfig) bool {
// func (recdb RecordDB) ContainsLT(rec *models.RecordConfig) bool {
// _, ok := recdb.labelAndTypeMap[rec.Key()]
// return ok
//}

View file

@ -1,7 +1,7 @@
package rejectif
import (
"fmt"
"errors"
"strings"
"github.com/StackExchange/dnscontrol/v4/models"
@ -12,7 +12,7 @@ import (
// CaaFlagIsNonZero identifies CAA records where tag is no zero.
func CaaFlagIsNonZero(rc *models.RecordConfig) error {
if rc.CaaFlag != 0 {
return fmt.Errorf("caa flag is non-zero")
return errors.New("caa flag is non-zero")
}
return nil
}
@ -22,7 +22,7 @@ func CaaFlagIsNonZero(rc *models.RecordConfig) error {
// See https://github.com/StackExchange/dnscontrol/issues/1374
func CaaTargetContainsWhitespace(rc *models.RecordConfig) error {
if strings.ContainsAny(rc.GetTargetField(), " \t\r\n") {
return fmt.Errorf("caa target contains whitespace")
return errors.New("caa target contains whitespace")
}
return nil
}

View file

@ -1,7 +1,7 @@
package rejectif
import (
"fmt"
"errors"
"github.com/StackExchange/dnscontrol/v4/models"
)
@ -12,7 +12,7 @@ import (
// is only permitted at the apex.
func LabelNotApex(rc *models.RecordConfig) error {
if rc.GetLabel() != "@" {
return fmt.Errorf("use not at apex")
return errors.New("use not at apex")
}
return nil
}

View file

@ -1,7 +1,7 @@
package rejectif
import (
"fmt"
"errors"
"github.com/StackExchange/dnscontrol/v4/models"
)
@ -12,7 +12,7 @@ import (
// This is needed by providers that don't support RFC 7505.
func MxNull(rc *models.RecordConfig) error {
if rc.GetTargetField() == "." {
return fmt.Errorf("mx has null target")
return errors.New("mx has null target")
}
return nil
}

View file

@ -1,7 +1,7 @@
package rejectif
import (
"fmt"
"errors"
"github.com/StackExchange/dnscontrol/v4/models"
)
@ -11,7 +11,7 @@ import (
// SrvHasNullTarget detects SRV records that has a null target.
func SrvHasNullTarget(rc *models.RecordConfig) error {
if rc.GetTargetField() == "." {
return fmt.Errorf("srv has null target")
return errors.New("srv has null target")
}
return nil
}

View file

@ -1,6 +1,7 @@
package rejectif
import (
"errors"
"fmt"
"strings"
@ -12,7 +13,7 @@ import (
// TxtHasBackslash audits TXT records for strings that contains one or more backslashes.
func TxtHasBackslash(rc *models.RecordConfig) error {
if strings.Contains(rc.GetTargetTXTJoined(), `\`) {
return fmt.Errorf("txtstring contains backslashes")
return errors.New("txtstring contains backslashes")
}
return nil
}
@ -20,7 +21,7 @@ func TxtHasBackslash(rc *models.RecordConfig) error {
// TxtHasBackticks audits TXT records for strings that contain backticks.
func TxtHasBackticks(rc *models.RecordConfig) error {
if strings.Contains(rc.GetTargetTXTJoined(), "`") {
return fmt.Errorf("txtstring contains backtick")
return errors.New("txtstring contains backtick")
}
return nil
}
@ -28,7 +29,7 @@ func TxtHasBackticks(rc *models.RecordConfig) error {
// TxtHasDoubleQuotes audits TXT records for strings that contain doublequotes.
func TxtHasDoubleQuotes(rc *models.RecordConfig) error {
if strings.Contains(rc.GetTargetTXTJoined(), `"`) {
return fmt.Errorf("txtstring contains doublequotes")
return errors.New("txtstring contains doublequotes")
}
return nil
}
@ -36,7 +37,7 @@ func TxtHasDoubleQuotes(rc *models.RecordConfig) error {
// TxtHasSemicolon audits TXT records for strings that contain backticks.
func TxtHasSemicolon(rc *models.RecordConfig) error {
if strings.Contains(rc.GetTargetTXTJoined(), ";") {
return fmt.Errorf("txtstring contains semicolon")
return errors.New("txtstring contains semicolon")
}
return nil
}
@ -44,7 +45,7 @@ func TxtHasSemicolon(rc *models.RecordConfig) error {
// TxtHasSingleQuotes audits TXT records for strings that contain single-quotes.
func TxtHasSingleQuotes(rc *models.RecordConfig) error {
if strings.Contains(rc.GetTargetTXTJoined(), "'") {
return fmt.Errorf("txtstring contains single-quotes")
return errors.New("txtstring contains single-quotes")
}
return nil
}
@ -53,7 +54,7 @@ func TxtHasSingleQuotes(rc *models.RecordConfig) error {
func TxtHasTrailingSpace(rc *models.RecordConfig) error {
txt := rc.GetTargetTXTJoined()
if txt != "" && txt[ultimate(txt)] == ' ' {
return fmt.Errorf("txtstring ends with space")
return errors.New("txtstring ends with space")
}
return nil
}
@ -61,7 +62,7 @@ func TxtHasTrailingSpace(rc *models.RecordConfig) error {
// TxtHasUnpairedDoubleQuotes audits TXT records for strings that contain unpaired doublequotes.
func TxtHasUnpairedDoubleQuotes(rc *models.RecordConfig) error {
if strings.Count(rc.GetTargetTXTJoined(), `"`)%2 == 1 {
return fmt.Errorf("txtstring contains unpaired doublequotes")
return errors.New("txtstring contains unpaired doublequotes")
}
return nil
}
@ -69,7 +70,7 @@ func TxtHasUnpairedDoubleQuotes(rc *models.RecordConfig) error {
// TxtIsEmpty audits TXT records for empty strings.
func TxtIsEmpty(rc *models.RecordConfig) error {
if len(rc.GetTargetTXTJoined()) == 0 {
return fmt.Errorf("txtstring is empty")
return errors.New("txtstring is empty")
}
return nil
}
@ -90,7 +91,7 @@ func TxtLongerThan(maxLength int) func(rc *models.RecordConfig) error {
func TxtStartsOrEndsWithSpaces(rc *models.RecordConfig) error {
txt := rc.GetTargetTXTJoined()
if len(txt) > 0 && (txt[0] == ' ' || txt[len(txt)-1] == ' ') {
return fmt.Errorf("txtstring starts or ends with spaces")
return errors.New("txtstring starts or ends with spaces")
}
return nil
}

View file

@ -1,14 +1,12 @@
package rfc4183
import (
"fmt"
)
import "errors"
// reverseIPv6 returns the ipv6.arpa string suitable for reverse DNS lookups.
func reverseIPv6(ip []byte, maskbits int) (arpa string, err error) {
// Must be IPv6
if len(ip) != 16 {
return "", fmt.Errorf("not IPv6")
return "", errors.New("not IPv6")
}
buf := []byte("x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa")

View file

@ -1,17 +1,20 @@
package rfc4183
import (
"errors"
"fmt"
"strings"
)
var newmode bool
var modeset bool
var (
newmode bool
modeset bool
)
// SetCompatibilityMode sets REV() compatibility mode.
func SetCompatibilityMode(m string) error {
if modeset {
return fmt.Errorf("ERROR: REVCOMPAT() already set")
return errors.New("ERROR: REVCOMPAT() already set")
}
modeset = true

View file

@ -10,7 +10,6 @@ import (
// a in-addr name. IP addresses are assumed to be /32 or /128 CIDR blocks.
// CIDR host bits are changed to 0s.
func ReverseDomainName(cidr string) (string, error) {
// Mask missing? Add it.
if !strings.Contains(cidr, "/") {
a, err := netip.ParseAddr(cidr)
@ -75,5 +74,4 @@ func ReverseDomainName(cidr string) (string, error) {
return fmt.Sprintf("%d-%d.%d.in-addr.arpa", y, m, x), nil
}
return "", fmt.Errorf("fewer than 8 mask bits is not reasonable: %v", cidr)
}

View file

@ -6,7 +6,7 @@ import (
)
func TestReverse(t *testing.T) {
var tests = []struct {
tests := []struct {
in string
out string
}{
@ -106,7 +106,7 @@ func TestReverse(t *testing.T) {
}
func TestReverseErrors(t *testing.T) {
var tests = []struct {
tests := []struct {
in string
}{
{"0.0.0.0/0"},

View file

@ -10,7 +10,6 @@ import (
// 'i': uinet16 (will convert strings, truncate floats, etc)
// 's': Valid only if string.
func PaveArgs(args []any, argTypes string) error {
if len(args) != len(argTypes) {
return fmt.Errorf("wrong number of arguments. Expected %v, got %v", len(argTypes), len(args))
}
@ -18,7 +17,6 @@ func PaveArgs(args []any, argTypes string) error {
for i, at := range argTypes {
arg := args[i]
switch at {
case 'i': // uint16
if s, ok := arg.(string); ok { // Is this a string-encoded int?
ni, err := strconv.Atoi(s)
@ -42,7 +40,6 @@ func PaveArgs(args []any, argTypes string) error {
} else {
args[i] = fmt.Sprintf("%v", arg)
}
}
}

View file

@ -8,11 +8,9 @@ import (
)
func PostProcess(domains []*models.DomainConfig) error {
var err error
for _, dc := range domains {
for _, rawRec := range dc.RawRecords {
rec := &models.RecordConfig{
Type: rawRec.Type,
@ -33,9 +31,8 @@ func PostProcess(domains []*models.DomainConfig) error {
}
// Call the proper initialize function.
// TODO(tlim): Good candiate for an interface or a lookup table.
// TODO(tlim): Good candidate for an interface or a lookup table.
switch rawRec.Type {
case "CLOUDFLAREAPI_SINGLE_REDIRECT":
err = cfsingleredirect.FromRaw(rec, rawRec.Args)
rec.SetLabel("@", dc.Name)

View file

@ -9,23 +9,24 @@ import (
// use this to split TXT records into 255 sized chunks for RFC 4408
// https://tools.ietf.org/html/rfc4408#section-3.1.3
// Borrowed from https://stackoverflow.com/a/61469854/11477663
// TODO(tlim): Consider replacing with https://pkg.go.dev/slices#Chunk
func Chunks(s string, chunkSize int) []string {
if chunkSize >= len(s) {
return []string{s}
}
var chunks []string
chunk := make([]rune, chunkSize)
len := 0
lngth := 0
for _, r := range s {
chunk[len] = r
len++
if len == chunkSize {
chunk[lngth] = r
lngth++
if lngth == chunkSize {
chunks = append(chunks, string(chunk))
len = 0
lngth = 0
}
}
if len > 0 {
chunks = append(chunks, string(chunk[:len]))
if lngth > 0 {
chunks = append(chunks, string(chunk[:lngth]))
}
return chunks
}
@ -58,7 +59,6 @@ func (s *SPFRecord) TXTSplit(pattern string, overhead int, txtMaxSize int) map[s
m := map[string][]string{}
s.split("@", pattern, 1, m, overhead, txtMaxSize)
return m
}
func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[string][]string, overhead int, txtMaxSize int) {

View file

@ -1,6 +1,7 @@
package spflib
import (
"errors"
"fmt"
"strings"
)
@ -28,7 +29,7 @@ var qualifiers = map[byte]bool{
// Parse parses a raw SPF record.
func Parse(text string, dnsres Resolver) (*SPFRecord, error) {
if !strings.HasPrefix(text, "v=spf1 ") {
return nil, fmt.Errorf("not an SPF record")
return nil, errors.New("not an SPF record")
}
parts := strings.Split(text, " ")
rec := &SPFRecord{}
@ -73,7 +74,7 @@ func Parse(text string, dnsres Resolver) (*SPFRecord, error) {
}
p.IncludeRecord, err = Parse(subRecord, dnsres)
if err != nil {
return nil, fmt.Errorf("in included SPF: %s", err)
return nil, fmt.Errorf("in included SPF: %w", err)
}
}
} else if strings.HasPrefix(part, "exists:") || strings.HasPrefix(part, "ptr:") {
@ -81,7 +82,6 @@ func Parse(text string, dnsres Resolver) (*SPFRecord, error) {
} else {
return nil, fmt.Errorf("unsupported SPF part %s", part)
}
}
return rec, nil
}

View file

@ -9,7 +9,6 @@ import (
)
func dump(rec *SPFRecord, indent string, w io.Writer) {
fmt.Fprintf(w, "%sTotal Lookups: %d\n", indent, rec.Lookups())
fmt.Fprint(w, indent+"v=spf1")
for _, p := range rec.Parts {
@ -53,19 +52,21 @@ func TestParse(t *testing.T) {
if err != nil {
t.Fatal(err)
}
rec, err := Parse(strings.Join([]string{"v=spf1",
rec, err := Parse(strings.Join([]string{
"v=spf1",
"ip4:198.252.206.0/24",
"ip4:192.111.0.0/24",
"include:_spf.google.com",
"include:mailgun.org",
//"include:spf-basic.fogcreek.com",
// "include:spf-basic.fogcreek.com",
"include:mail.zendesk.com",
"include:servers.mcsv.net",
"include:sendgrid.net",
"include:spf.mtasv.net",
"exists:%{i}._spf.sparkpostmail.com",
"ptr:sparkpostmail.com",
"~all"}, " "), dnsres)
"~all",
}, " "), dnsres)
if err != nil {
t.Fatal(err)
}
@ -90,9 +91,11 @@ func TestParseRedirectNotLast(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, err = Parse(strings.Join([]string{"v=spf1",
_, err = Parse(strings.Join([]string{
"v=spf1",
"redirect=servers.mcsv.net",
"~all"}, " "), dnsres)
"~all",
}, " "), dnsres)
if err == nil {
t.Fatal("should fail")
}
@ -104,7 +107,8 @@ func TestParseRedirectColon(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, err = Parse(strings.Join([]string{"v=spf1",
_, err = Parse(strings.Join([]string{
"v=spf1",
"redirect:servers.mcsv.net",
}, " "), dnsres)
if err == nil {
@ -117,8 +121,10 @@ func TestParseRedirectOnly(t *testing.T) {
if err != nil {
t.Fatal(err)
}
rec, err := Parse(strings.Join([]string{"v=spf1",
"redirect=servers.mcsv.net"}, " "), dnsres)
rec, err := Parse(strings.Join([]string{
"v=spf1",
"redirect=servers.mcsv.net",
}, " "), dnsres)
if err != nil {
t.Fatal(err)
}
@ -130,9 +136,11 @@ func TestParseRedirectLast(t *testing.T) {
if err != nil {
t.Fatal(err)
}
rec, err := Parse(strings.Join([]string{"v=spf1",
rec, err := Parse(strings.Join([]string{
"v=spf1",
"ip4:198.252.206.0/24",
"redirect=servers.mcsv.net"}, " "), dnsres)
"redirect=servers.mcsv.net",
}, " "), dnsres)
if err != nil {
t.Fatal(err)
}

View file

@ -125,6 +125,7 @@ func (c *cache) ResolveErrors() (errs []error) {
}
return
}
func (c *cache) Save(filename string) error {
outRecs := make(map[string]*cacheEntry, len(c.records))
for k, entry := range c.records {
@ -136,5 +137,5 @@ func (c *cache) Save(filename string) error {
}
}
dat, _ := json.MarshalIndent(outRecs, "", " ")
return os.WriteFile(filename, dat, 0644)
return os.WriteFile(filename, dat, 0o644)
}

View file

@ -12,7 +12,6 @@ import (
// For cases not covered by RFC2317, implement RFC4183
// The host bits must all be zeros.
func ReverseDomainName(cidr string) (string, error) {
if rfc4183.IsRFC4183Mode() {
return rfc4183.ReverseDomainName(cidr)
}

View file

@ -6,7 +6,7 @@ import (
)
func TestReverse(t *testing.T) {
var tests = []struct {
tests := []struct {
in string
isError bool
out string

View file

@ -63,7 +63,6 @@ var isRfc2317Format1 = regexp.MustCompile(`(\d{1,3})/(\d{1,3})\.(\d{1,3})\.(\d{1
// ipMatchesClasslessDomain returns true if ip is appropriate for domain.
// domain is a reverse DNS lookup zone (in-addr.arpa) as described in RFC2317.
func ipMatchesClasslessDomain(ip net.IP, domain string) bool {
// The unofficial but preferred format in RFC2317:
m := isRfc2317Format1.FindStringSubmatch(domain)
if m != nil {

View file

@ -56,8 +56,10 @@ func TestPtrMagic(t *testing.T) {
// User manually reversed addresses:
{"1.1.1.1.in-addr.arpa.", "1.1.in-addr.arpa", "1.1", false},
{"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.",
"0.2.ip6.arpa", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0", false},
{
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.",
"0.2.ip6.arpa", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0", false,
},
// Error cases:
{"1.1.1.1.in-addr.arpa.", "2.2.in-addr.arpa", "", true},

View file

@ -1,6 +1,7 @@
package transform
import (
"errors"
"fmt"
"net"
"strings"
@ -22,7 +23,7 @@ func ipToUint(i net.IP) (uint32, error) {
return r, nil
}
// UintToIP convert a 32-bit into into a net.IP.
// UintToIP convert a 32-bit into a net.IP.
func UintToIP(u uint32) net.IP {
return net.IPv4(
byte((u>>24)&255),
@ -51,7 +52,6 @@ func DecodeTransformTable(transforms string) ([]IPConversion, error) {
parseList := func(s string) ([]net.IP, error) {
ips := []net.IP{}
for _, ip := range strings.Split(s, ",") {
if ip == "" {
continue
}
@ -77,7 +77,7 @@ func DecodeTransformTable(transforms string) ([]IPConversion, error) {
return nil, fmt.Errorf("transform_table Low should be less than High. row (%v) %v>%v (%v)", ri, con.Low, con.High, transforms)
}
if len(con.NewBases) > 0 && len(con.NewIPs) > 0 {
return nil, fmt.Errorf("transform_table_rows should only specify one of NewBases or NewIPs, Not both")
return nil, errors.New("transform_table_rows should only specify one of NewBases or NewIPs, Not both")
}
result = append(result, con)
}
@ -104,15 +104,15 @@ func IPToList(address net.IP, transforms []IPConversion) ([]net.IP, error) {
return nil, err
}
for _, conv := range transforms {
min, err := ipToUint(conv.Low)
min_, err := ipToUint(conv.Low)
if err != nil {
return nil, err
}
max, err := ipToUint(conv.High)
max_, err := ipToUint(conv.High)
if err != nil {
return nil, err
}
if (thisIP >= min) && (thisIP <= max) {
if (thisIP >= min_) && (thisIP <= max_) {
if len(conv.NewIPs) > 0 {
return conv.NewIPs, nil
}
@ -122,7 +122,7 @@ func IPToList(address net.IP, transforms []IPConversion) ([]net.IP, error) {
if err != nil {
return nil, err
}
list = append(list, UintToIP(newbase+(thisIP-min)))
list = append(list, UintToIP(newbase+(thisIP-min_)))
}
return list, nil
}

View file

@ -68,6 +68,7 @@ func Test_DecodeTransformTable_1(t *testing.T) {
testIP(t, "NewBase[1]", "7.6.5.4", result[1].NewBases[0])
// test_ip(t, "newIP[1]", "", result[0].NewIP)
}
func Test_DecodeTransformTable_NewIP(t *testing.T) {
result, err := DecodeTransformTable("1.2.3.4 ~ 2.3.4.5 ~ ~ 3.4.5.6 ")
if err != nil {
@ -104,8 +105,7 @@ func Test_DecodeTransformTable_Base_and_IP(t *testing.T) {
}
func Test_IP(t *testing.T) {
var transforms1 = []IPConversion{{
transforms1 := []IPConversion{{
Low: net.ParseIP("11.11.11.0"),
High: net.ParseIP("11.11.11.20"),
NewBases: []net.IP{net.ParseIP("99.99.99.0")},
@ -128,7 +128,7 @@ func Test_IP(t *testing.T) {
}}
// NO TRANSFORMS ON 99.x.x.x PLZ
var tests = []struct {
tests := []struct {
experiment string
expected string
}{
@ -172,23 +172,23 @@ func Test_IP(t *testing.T) {
}
func Test_IP_NewIP(t *testing.T) {
var transforms1 = []IPConversion{{
Low: net.ParseIP("11.11.11.0"),
High: net.ParseIP("11.11.11.20"),
NewIPs: []net.IP{net.ParseIP("1.1.1.1")},
}, {
Low: net.ParseIP("22.22.22.0"),
High: net.ParseIP("22.22.22.40"),
NewIPs: []net.IP{net.ParseIP("2.2.2.2")},
}, {
Low: net.ParseIP("33.33.33.20"),
High: net.ParseIP("33.33.35.40"),
NewIPs: []net.IP{net.ParseIP("3.3.3.3")},
},
transforms1 := []IPConversion{
{
Low: net.ParseIP("11.11.11.0"),
High: net.ParseIP("11.11.11.20"),
NewIPs: []net.IP{net.ParseIP("1.1.1.1")},
}, {
Low: net.ParseIP("22.22.22.0"),
High: net.ParseIP("22.22.22.40"),
NewIPs: []net.IP{net.ParseIP("2.2.2.2")},
}, {
Low: net.ParseIP("33.33.33.20"),
High: net.ParseIP("33.33.35.40"),
NewIPs: []net.IP{net.ParseIP("3.3.3.3")},
},
}
var tests = []struct {
tests := []struct {
experiment string
expected string
}{

View file

@ -70,10 +70,10 @@ func txtDecode(s string) (string, error) {
/*
BNF:
txttarget := `""`` | item | item ` ` item*
txttarget := `""`` | item | item ` item*
item := quoteditem | unquoteditem
quoteditem := quote innertxt quote
quote := `"`
:= `"`
innertxt := (escaped | printable )*
escaped := `\\` | `\"`
printable := (printable ASCII chars)
@ -81,16 +81,14 @@ func txtDecode(s string) (string, error) {
*/
//printer.Printf("DEBUG: txtDecode txt inboundv=%v\n", s)
// printer.Printf("DEBUG: txtDecode txt inboundv=%v\n", s)
b := &bytes.Buffer{}
state := StateStart
for i, c := range s {
//printer.Printf("DEBUG: state=%v rune=%v\n", state, string(c))
// printer.Printf("DEBUG: state=%v rune=%v\n", state, string(c))
switch state {
case StateStart:
if c == ' ' {
// skip whitespace
@ -133,18 +131,17 @@ func txtDecode(s string) (string, error) {
} else {
return "", fmt.Errorf("txtDecode expected whitespace after close quote q(%q)", s)
}
}
}
r := b.String()
//printer.Printf("DEBUG: txtDecode txt decodedv=%v\n", r)
// printer.Printf("DEBUG: txtDecode txt decodedv=%v\n", r)
return r, nil
}
// txtEncode encodes TXT strings in RFC1035 format as interpreted by Tom.
func txtEncode(ts []string) string {
//printer.Printf("DEBUG: txtEncode txt outboundv=%v\n", ts)
// printer.Printf("DEBUG: txtEncode txt outboundv=%v\n", ts)
if (len(ts) == 0) || (strings.Join(ts, "") == "") {
return `""`
}
@ -160,6 +157,6 @@ func txtEncode(ts []string) string {
}
t := strings.Join(r, ` `)
//printer.Printf("DEBUG: txtEncode txt encodedv=%v\n", t)
// printer.Printf("DEBUG: txtEncode txt encodedv=%v\n", t)
return t
}

Some files were not shown because too many files have changed in this diff Show more