mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-09-20 14:56:20 +08:00
Switch from fmt.Error* to errors.Error* (#317)
This commit is contained in:
parent
65f8fb63f0
commit
4b1dc82c9b
|
@ -11,6 +11,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
@ -59,7 +60,7 @@ func checkGoFmt() error {
|
|||
if fList == "" {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("The following files need to have gofmt run on them:\n%s", fList)
|
||||
return errors.Errorf("The following files need to have gofmt run on them:\n%s", fList)
|
||||
}
|
||||
|
||||
func checkGoGenerate() error {
|
||||
|
@ -75,7 +76,7 @@ func checkGoGenerate() error {
|
|||
return err
|
||||
}
|
||||
if len(modified) != 0 {
|
||||
return fmt.Errorf("ERROR: The following files are modified after go generate:\n%s", strings.Join(modified, "\n"))
|
||||
return errors.Errorf("ERROR: The following files are modified after go generate:\n%s", strings.Join(modified, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func parseargs(args []string) (zonename string, filename string, r io.Reader, er
|
|||
// Anything else returns an error.
|
||||
|
||||
if len(args) < 2 {
|
||||
return "", "", nil, fmt.Errorf("no command line parameters. Zone name required")
|
||||
return "", "", nil, errors.Errorf("no command line parameters. Zone name required")
|
||||
}
|
||||
|
||||
zonename = args[0]
|
||||
|
@ -56,7 +56,7 @@ func parseargs(args []string) (zonename string, filename string, r io.Reader, er
|
|||
return "", "", nil, errors.Wrapf(err, "Could not open file: %s", filename)
|
||||
}
|
||||
} else {
|
||||
return "", "", nil, fmt.Errorf("too many command line parameters")
|
||||
return "", "", nil, errors.Errorf("too many command line parameters")
|
||||
}
|
||||
|
||||
return zonename, filename, r, nil
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
|
@ -116,7 +117,7 @@ func preloadProviders(cfg *models.DNSConfig, err error) (*models.DNSConfig, erro
|
|||
for _, d := range cfg.Domains {
|
||||
reg, ok := cfg.RegistrarsByName[d.RegistrarName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Registrar named %s expected for %s, but never registered", d.RegistrarName, d.Name)
|
||||
return nil, errors.Errorf("Registrar named %s expected for %s, but never registered", d.RegistrarName, d.Name)
|
||||
}
|
||||
d.RegistrarInstance = &models.RegistrarInstance{
|
||||
ProviderBase: models.ProviderBase{
|
||||
|
@ -127,7 +128,7 @@ func preloadProviders(cfg *models.DNSConfig, err error) (*models.DNSConfig, erro
|
|||
for pName, n := range d.DNSProviderNames {
|
||||
prov, ok := cfg.DNSProvidersByName[pName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("DNS Provider named %s expected for %s, but never registered", pName, d.Name)
|
||||
return nil, errors.Errorf("DNS Provider named %s expected for %s, but never registered", pName, d.Name)
|
||||
}
|
||||
d.DNSProviderInstances = append(d.DNSProviderInstances, &models.DNSProviderInstance{
|
||||
ProviderBase: models.ProviderBase{
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
|
@ -94,7 +95,7 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI) error {
|
|||
}
|
||||
errs := normalize.NormalizeAndValidateConfig(cfg)
|
||||
if PrintValidationErrors(errs) {
|
||||
return fmt.Errorf("Exiting due to validation errors")
|
||||
return errors.Errorf("Exiting due to validation errors")
|
||||
}
|
||||
// TODO:
|
||||
notifier, err := InitializeProviders(args.CredsFile, cfg, args.Notify)
|
||||
|
@ -162,7 +163,7 @@ DomainLoop:
|
|||
notifier.Done()
|
||||
out.Debugf("Done. %d corrections.\n", totalCorrections)
|
||||
if anyErrors {
|
||||
return fmt.Errorf("Completed with errors")
|
||||
return errors.Errorf("Completed with errors")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/pkg/js"
|
||||
"github.com/StackExchange/dnscontrol/pkg/normalize"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
|
@ -72,7 +73,7 @@ func PrintIR(args PrintIRArgs) error {
|
|||
if !args.Raw {
|
||||
errs := normalize.NormalizeAndValidateConfig(cfg)
|
||||
if PrintValidationErrors(errs) {
|
||||
return fmt.Errorf("Exiting due to validation errors")
|
||||
return errors.Errorf("Exiting due to validation errors")
|
||||
}
|
||||
}
|
||||
return PrintJSON(args.PrintJSONArgs, cfg)
|
||||
|
@ -98,15 +99,15 @@ 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.Errorf("No config specified")
|
||||
}
|
||||
text, err := ioutil.ReadFile(args.JSFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Reading js file %s: %s", args.JSFile, err)
|
||||
return nil, errors.Errorf("Reading js file %s: %s", args.JSFile, err)
|
||||
}
|
||||
dnsConfig, err := js.ExecuteJavascript(string(text), args.DevMode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Executing javascript in %s: %s", args.JSFile, err)
|
||||
return nil, errors.Errorf("Executing javascript in %s: %s", args.JSFile, err)
|
||||
}
|
||||
return dnsConfig, nil
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/pkg/transform"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
|
@ -452,12 +453,12 @@ func SplitCombinedMxValue(s string) (preference uint16, target string, err error
|
|||
parts := strings.Fields(s)
|
||||
|
||||
if len(parts) != 2 {
|
||||
return 0, "", fmt.Errorf("MX value %#v contains too many fields", s)
|
||||
return 0, "", errors.Errorf("MX value %#v contains too many fields", s)
|
||||
}
|
||||
|
||||
n64, err := strconv.ParseUint(parts[0], 10, 16)
|
||||
if err != nil {
|
||||
return 0, "", fmt.Errorf("MX preference %#v does not fit into a uint16", parts[0])
|
||||
return 0, "", errors.Errorf("MX preference %#v does not fit into a uint16", parts[0])
|
||||
}
|
||||
return uint16(n64), parts[1], nil
|
||||
}
|
||||
|
@ -484,20 +485,20 @@ func SplitCombinedSrvValue(s string) (priority, weight, port uint16, target stri
|
|||
parts := strings.Fields(s)
|
||||
|
||||
if len(parts) != 4 {
|
||||
return 0, 0, 0, "", fmt.Errorf("SRV value %#v contains too many fields", s)
|
||||
return 0, 0, 0, "", errors.Errorf("SRV value %#v contains too many fields", s)
|
||||
}
|
||||
|
||||
priorityconv, err := strconv.ParseInt(parts[0], 10, 16)
|
||||
if err != nil {
|
||||
return 0, 0, 0, "", fmt.Errorf("Priority %#v does not fit into a uint16", parts[0])
|
||||
return 0, 0, 0, "", errors.Errorf("Priority %#v does not fit into a uint16", parts[0])
|
||||
}
|
||||
weightconv, err := strconv.ParseInt(parts[1], 10, 16)
|
||||
if err != nil {
|
||||
return 0, 0, 0, "", fmt.Errorf("Weight %#v does not fit into a uint16", parts[0])
|
||||
return 0, 0, 0, "", errors.Errorf("Weight %#v does not fit into a uint16", parts[0])
|
||||
}
|
||||
portconv, err := strconv.ParseInt(parts[2], 10, 16)
|
||||
if err != nil {
|
||||
return 0, 0, 0, "", fmt.Errorf("Port %#v does not fit into a uint16", parts[0])
|
||||
return 0, 0, 0, "", errors.Errorf("Port %#v does not fit into a uint16", parts[0])
|
||||
}
|
||||
return uint16(priorityconv), uint16(weightconv), uint16(portconv), parts[3], nil
|
||||
}
|
||||
|
@ -522,7 +523,7 @@ func SplitCombinedCaaValue(s string) (tag string, flag uint8, value string, err
|
|||
|
||||
splitData := strings.SplitN(s, " ", 3)
|
||||
if len(splitData) != 3 {
|
||||
err = fmt.Errorf("Unexpected data for CAA record returned by Vultr")
|
||||
err = errors.Errorf("Unexpected data for CAA record returned by Vultr")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -588,9 +589,9 @@ func InterfaceToIP(i interface{}) (net.IP, error) {
|
|||
if ip := net.ParseIP(v); ip != nil {
|
||||
return ip, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%s is not a valid ip address", v)
|
||||
return nil, errors.Errorf("%s is not a valid ip address", v)
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot convert type %s to ip", reflect.TypeOf(i))
|
||||
return nil, errors.Errorf("cannot convert type %s to ip", reflect.TypeOf(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package normalize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/pkg/spflib"
|
||||
|
@ -40,7 +40,7 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
|
|||
// now split if needed
|
||||
if split, ok := txt.Metadata["split"]; ok {
|
||||
if !strings.Contains(split, "%d") {
|
||||
errs = append(errs, Warning{fmt.Errorf("Split format `%s` in `%s` is not proper format (should have %%d in it)", split, txt.NameFQDN)})
|
||||
errs = append(errs, Warning{errors.Errorf("Split format `%s` in `%s` is not proper format (should have %%d in it)", split, txt.NameFQDN)})
|
||||
continue
|
||||
}
|
||||
recs := rec.TXTSplit(split + "." + domain.Name)
|
||||
|
@ -63,7 +63,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{errors.Errorf("problem resolving SPF record: %s", e)})
|
||||
}
|
||||
if len(cache.ResolveErrors()) == 0 {
|
||||
changed := cache.ChangedRecords()
|
||||
|
@ -71,7 +71,7 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
|
|||
if err := cache.Save("spfcache.updated.json"); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
errs = append(errs, Warning{fmt.Errorf("%d spf record lookups are out of date with cache (%s).\nWrote changes to spfcache.updated.json. Please rename and commit:\n $ mv spfcache.updated.json spfcache.json\n $ git commit spfcache.json", len(changed), strings.Join(changed, ","))})
|
||||
errs = append(errs, Warning{errors.Errorf("%d spf record lookups are out of date with cache (%s).\nWrote changes to spfcache.updated.json. Please rename and commit:\n $ mv spfcache.updated.json spfcache.json\n $ git commit spfcache.json", len(changed), strings.Join(changed, ","))})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package normalize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
|
@ -16,7 +15,7 @@ import (
|
|||
// Returns false if target does not validate.
|
||||
func checkIPv4(label string) error {
|
||||
if net.ParseIP(label).To4() == nil {
|
||||
return fmt.Errorf("WARNING: target (%v) is not an IPv4 address", label)
|
||||
return errors.Errorf("WARNING: target (%v) is not an IPv4 address", label)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -24,7 +23,7 @@ func checkIPv4(label string) error {
|
|||
// Returns false if target does not validate.
|
||||
func checkIPv6(label string) error {
|
||||
if net.ParseIP(label).To16() == nil {
|
||||
return fmt.Errorf("WARNING: target (%v) is not an IPv6 address", label)
|
||||
return errors.Errorf("WARNING: target (%v) is not an IPv6 address", label)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -35,14 +34,14 @@ func checkTarget(target string) error {
|
|||
return nil
|
||||
}
|
||||
if len(target) < 1 {
|
||||
return fmt.Errorf("empty target")
|
||||
return errors.Errorf("empty target")
|
||||
}
|
||||
if strings.ContainsAny(target, `'" +,|!£$%&/()=?^*ç°§;:<>[]()@`) {
|
||||
return errors.Errorf("target (%v) includes invalid char", target)
|
||||
}
|
||||
// If it containts a ".", it must end in a ".".
|
||||
if strings.ContainsRune(target, '.') && target[len(target)-1] != '.' {
|
||||
return fmt.Errorf("target (%v) must end with a (.) [https://stackexchange.github.io/dnscontrol/why-the-dot]", target)
|
||||
return errors.Errorf("target (%v) must end with a (.) [https://stackexchange.github.io/dnscontrol/why-the-dot]", target)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -67,11 +66,11 @@ func validateRecordTypes(rec *models.RecordConfig, domain string, pTypes []strin
|
|||
if !ok {
|
||||
cType := providers.GetCustomRecordType(rec.Type)
|
||||
if cType == nil {
|
||||
return fmt.Errorf("Unsupported record type (%v) domain=%v name=%v", rec.Type, domain, rec.Name)
|
||||
return errors.Errorf("Unsupported record type (%v) domain=%v name=%v", rec.Type, domain, rec.Name)
|
||||
}
|
||||
for _, providerType := range pTypes {
|
||||
if providerType != cType.Provider {
|
||||
return fmt.Errorf("Custom record type %s is not compatible with provider type %s", rec.Type, providerType)
|
||||
return errors.Errorf("Custom record type %s is not compatible with provider type %s", rec.Type, providerType)
|
||||
}
|
||||
}
|
||||
// it is ok. Lets replace the type with real type and add metadata to say we checked it
|
||||
|
@ -95,14 +94,14 @@ func checkLabel(label string, rType string, domain string, meta map[string]strin
|
|||
return nil
|
||||
}
|
||||
if len(label) < 1 {
|
||||
return fmt.Errorf("empty %s label in %s", rType, domain)
|
||||
return errors.Errorf("empty %s label in %s", rType, domain)
|
||||
}
|
||||
if label[len(label)-1] == '.' {
|
||||
return fmt.Errorf("label %s.%s ends with a (.)", label, domain)
|
||||
return errors.Errorf("label %s.%s ends with a (.)", label, domain)
|
||||
}
|
||||
if strings.HasSuffix(label, domain) {
|
||||
if m := meta["skip_fqdn_check"]; m != "true" {
|
||||
return fmt.Errorf(`label %s ends with domain name %s. Record names should not be fully qualified. Add {skip_fqdn_check:"true"} to this record if you really want to make %s.%s`, label, domain, label, domain)
|
||||
return errors.Errorf(`label %s ends with domain name %s. Record names should not be fully qualified. Add {skip_fqdn_check:"true"} to this record if you really want to make %s.%s`, label, domain, label, domain)
|
||||
}
|
||||
}
|
||||
// check for underscores last
|
||||
|
@ -118,7 +117,7 @@ func checkLabel(label string, rType string, domain string, meta map[string]strin
|
|||
}
|
||||
// underscores are warnings
|
||||
if strings.ContainsRune(label, '_') {
|
||||
return Warning{fmt.Errorf("label %s.%s contains an underscore", label, domain)}
|
||||
return Warning{errors.Errorf("label %s.%s contains an underscore", label, domain)}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -130,7 +129,7 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
|
|||
target := rec.Target
|
||||
check := func(e error) {
|
||||
if e != nil {
|
||||
err := fmt.Errorf("In %s %s.%s: %s", rec.Type, rec.Name, domain, e.Error())
|
||||
err := errors.Errorf("In %s %s.%s: %s", rec.Type, rec.Name, domain, e.Error())
|
||||
if _, ok := e.(Warning); ok {
|
||||
err = Warning{err}
|
||||
}
|
||||
|
@ -145,14 +144,14 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
|
|||
case "CNAME":
|
||||
check(checkTarget(target))
|
||||
if label == "@" {
|
||||
check(fmt.Errorf("cannot create CNAME record for bare domain"))
|
||||
check(errors.Errorf("cannot create CNAME record for bare domain"))
|
||||
}
|
||||
case "MX":
|
||||
check(checkTarget(target))
|
||||
case "NS":
|
||||
check(checkTarget(target))
|
||||
if label == "@" {
|
||||
check(fmt.Errorf("cannot create NS record for bare domain. Use NAMESERVER instead"))
|
||||
check(errors.Errorf("cannot create NS record for bare domain. Use NAMESERVER instead"))
|
||||
}
|
||||
case "PTR":
|
||||
check(checkTarget(target))
|
||||
|
@ -166,7 +165,7 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) {
|
|||
// it is a valid custom type. We perform no validation on target
|
||||
return
|
||||
}
|
||||
errs = append(errs, fmt.Errorf("checkTargets: Unimplemented record type (%v) domain=%v name=%v",
|
||||
errs = append(errs, errors.Errorf("checkTargets: Unimplemented record type (%v) domain=%v name=%v",
|
||||
rec.Type, domain, rec.Name))
|
||||
}
|
||||
return
|
||||
|
@ -206,7 +205,7 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
|
|||
case "A":
|
||||
trs, err := transform.TransformIPToList(net.ParseIP(rec.Target), transforms)
|
||||
if err != nil {
|
||||
return fmt.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.Target, transforms, err)
|
||||
return errors.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.Target, transforms, err)
|
||||
}
|
||||
for _, tr := range trs {
|
||||
r := newRec()
|
||||
|
@ -221,7 +220,7 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
|
|||
// Not imported.
|
||||
continue
|
||||
default:
|
||||
return fmt.Errorf("import_transform: Unimplemented record type %v (%v)",
|
||||
return errors.Errorf("import_transform: Unimplemented record type %v (%v)",
|
||||
rec.Type, rec.Name)
|
||||
}
|
||||
}
|
||||
|
@ -253,7 +252,7 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
|
|||
pType := provider.ProviderType
|
||||
// If NO_PURGE is in use, make sure this *isn't* a provider that *doesn't* support NO_PURGE.
|
||||
if domain.KeepUnknown && providers.ProviderHasCabability(pType, providers.CantUseNOPURGE) {
|
||||
errs = append(errs, fmt.Errorf("%s uses NO_PURGE which is not supported by %s(%s)", domain.Name, provider.Name, pType))
|
||||
errs = append(errs, errors.Errorf("%s uses NO_PURGE which is not supported by %s(%s)", domain.Name, provider.Name, pType))
|
||||
}
|
||||
|
||||
// Record if any providers do not support TXTMulti:
|
||||
|
@ -296,26 +295,26 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
|
|||
}
|
||||
} else if rec.Type == "CAA" {
|
||||
if rec.CaaTag != "issue" && rec.CaaTag != "issuewild" && rec.CaaTag != "iodef" {
|
||||
errs = append(errs, fmt.Errorf("CAA tag %s is invalid", rec.CaaTag))
|
||||
errs = append(errs, errors.Errorf("CAA tag %s is invalid", rec.CaaTag))
|
||||
}
|
||||
} else if rec.Type == "TLSA" {
|
||||
if rec.TlsaUsage < 0 || rec.TlsaUsage > 3 {
|
||||
errs = append(errs, fmt.Errorf("TLSA Usage %d is invalid in record %s (domain %s)",
|
||||
errs = append(errs, errors.Errorf("TLSA Usage %d is invalid in record %s (domain %s)",
|
||||
rec.TlsaUsage, rec.Name, domain.Name))
|
||||
}
|
||||
if rec.TlsaSelector < 0 || rec.TlsaSelector > 1 {
|
||||
errs = append(errs, fmt.Errorf("TLSA Selector %d is invalid in record %s (domain %s)",
|
||||
errs = append(errs, errors.Errorf("TLSA Selector %d is invalid in record %s (domain %s)",
|
||||
rec.TlsaSelector, rec.Name, domain.Name))
|
||||
}
|
||||
if rec.TlsaMatchingType < 0 || rec.TlsaMatchingType > 2 {
|
||||
errs = append(errs, fmt.Errorf("TLSA MatchingType %d is invalid in record %s (domain %s)",
|
||||
errs = append(errs, errors.Errorf("TLSA MatchingType %d is invalid in record %s (domain %s)",
|
||||
rec.TlsaMatchingType, rec.Name, domain.Name))
|
||||
}
|
||||
} else if rec.Type == "TXT" && len(txtMultiDissenters) != 0 && len(rec.TxtStrings) > 1 {
|
||||
// There are providers that don't support TXTMulti yet there is
|
||||
// a TXT record with multiple strings:
|
||||
errs = append(errs,
|
||||
fmt.Errorf("TXT records with multiple strings (label %v domain: %v) not supported by %s",
|
||||
errors.Errorf("TXT records with multiple strings (label %v domain: %v) not supported by %s",
|
||||
rec.Name, domain.Name, strings.Join(txtMultiDissenters, ",")))
|
||||
}
|
||||
|
||||
|
@ -377,14 +376,14 @@ func checkCNAMEs(dc *models.DomainConfig) (errs []error) {
|
|||
for _, r := range dc.Records {
|
||||
if r.Type == "CNAME" {
|
||||
if cnames[r.Name] {
|
||||
errs = append(errs, fmt.Errorf("Cannot have multiple CNAMEs with same name: %s", r.NameFQDN))
|
||||
errs = append(errs, errors.Errorf("Cannot have multiple CNAMEs with same name: %s", r.NameFQDN))
|
||||
}
|
||||
cnames[r.Name] = true
|
||||
}
|
||||
}
|
||||
for _, r := range dc.Records {
|
||||
if cnames[r.Name] && r.Type != "CNAME" {
|
||||
errs = append(errs, fmt.Errorf("Cannot have CNAME and %s record with same name: %s", r.Type, r.NameFQDN))
|
||||
errs = append(errs, errors.Errorf("Cannot have CNAME and %s record with same name: %s", r.Type, r.NameFQDN))
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -414,7 +413,7 @@ func checkProviderCapabilities(dc *models.DomainConfig) error {
|
|||
}
|
||||
for _, provider := range dc.DNSProviderInstances {
|
||||
if !providers.ProviderHasCabability(provider.ProviderType, ty.cap) {
|
||||
return fmt.Errorf("Domain %s uses %s records, but DNS provider type %s does not support them", dc.Name, ty.rType, provider.ProviderType)
|
||||
return errors.Errorf("Domain %s uses %s records, but DNS provider type %s does not support them", dc.Name, ty.rType, provider.ProviderType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"bytes"
|
||||
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SPFRecord stores the parts of an SPF record.
|
||||
|
@ -46,7 +48,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.Errorf("Not an spf record")
|
||||
}
|
||||
parts := strings.Split(text, " ")
|
||||
rec := &SPFRecord{}
|
||||
|
@ -74,11 +76,11 @@ 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, errors.Errorf("In included spf: %s", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unsupported spf part %s", part)
|
||||
return nil, errors.Errorf("Unsupported spf part %s", part)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ package spflib
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Resolver looks up spf txt records associated with a FQDN.
|
||||
|
@ -27,13 +28,13 @@ func (l LiveResolver) GetSPF(name string) (string, error) {
|
|||
for _, v := range vals {
|
||||
if strings.HasPrefix(v, "v=spf1") {
|
||||
if spf != "" {
|
||||
return "", fmt.Errorf("%s has multiple SPF records", name)
|
||||
return "", errors.Errorf("%s has multiple SPF records", name)
|
||||
}
|
||||
spf = v
|
||||
}
|
||||
}
|
||||
if spf == "" {
|
||||
return "", fmt.Errorf("%s has no SPF record", name)
|
||||
return "", errors.Errorf("%s has no SPF record", name)
|
||||
}
|
||||
return spf, nil
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func ReverseDomainName(cidr string) (string, error) {
|
|||
bits, total := c.Mask.Size()
|
||||
var toTrim int
|
||||
if bits == 0 {
|
||||
return "", fmt.Errorf("Cannot use /0 in reverse cidr")
|
||||
return "", errors.Errorf("Cannot use /0 in reverse cidr")
|
||||
}
|
||||
|
||||
// Handle IPv4 "Classless in-addr.arpa delegation" RFC2317:
|
||||
|
@ -41,16 +41,16 @@ func ReverseDomainName(cidr string) (string, error) {
|
|||
// Handle IPv4 Class-full and IPv6:
|
||||
if total == 32 {
|
||||
if bits%8 != 0 {
|
||||
return "", fmt.Errorf("IPv4 mask must be multiple of 8 bits")
|
||||
return "", errors.Errorf("IPv4 mask must be multiple of 8 bits")
|
||||
}
|
||||
toTrim = (total - bits) / 8
|
||||
} else if total == 128 {
|
||||
if bits%4 != 0 {
|
||||
return "", fmt.Errorf("IPv6 mask must be multiple of 4 bits")
|
||||
return "", errors.Errorf("IPv6 mask must be multiple of 4 bits")
|
||||
}
|
||||
toTrim = (total - bits) / 4
|
||||
} else {
|
||||
return "", fmt.Errorf("Address is not IPv4 or IPv6: %v", cidr)
|
||||
return "", errors.Errorf("Address is not IPv4 or IPv6: %v", cidr)
|
||||
}
|
||||
|
||||
parts := strings.SplitN(base, ".", toTrim+1)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package transform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// IpConversion describes an IP conversion.
|
||||
|
@ -16,7 +17,7 @@ type IpConversion struct {
|
|||
func ipToUint(i net.IP) (uint32, error) {
|
||||
parts := i.To4()
|
||||
if parts == nil || len(parts) != 4 {
|
||||
return 0, fmt.Errorf("%s is not an ipv4 address", parts.String())
|
||||
return 0, errors.Errorf("%s is not an ipv4 address", parts.String())
|
||||
}
|
||||
r := uint32(parts[0])<<24 | uint32(parts[1])<<16 | uint32(parts[2])<<8 | uint32(parts[3])
|
||||
return r, nil
|
||||
|
@ -38,7 +39,7 @@ func DecodeTransformTable(transforms string) ([]IpConversion, error) {
|
|||
for ri, row := range rows {
|
||||
items := strings.Split(row, "~")
|
||||
if len(items) != 4 {
|
||||
return nil, fmt.Errorf("transform_table rows should have 4 elements. (%v) found in row (%v) of %#v", len(items), ri, transforms)
|
||||
return nil, errors.Errorf("transform_table rows should have 4 elements. (%v) found in row (%v) of %#v", len(items), ri, transforms)
|
||||
}
|
||||
for i, item := range items {
|
||||
items[i] = strings.TrimSpace(item)
|
||||
|
@ -57,7 +58,7 @@ func DecodeTransformTable(transforms string) ([]IpConversion, error) {
|
|||
}
|
||||
addr := net.ParseIP(ip)
|
||||
if addr == nil {
|
||||
return nil, fmt.Errorf("%s is not a valid ip address", ip)
|
||||
return nil, errors.Errorf("%s is not a valid ip address", ip)
|
||||
}
|
||||
ips = append(ips, addr)
|
||||
}
|
||||
|
@ -74,10 +75,10 @@ func DecodeTransformTable(transforms string) ([]IpConversion, error) {
|
|||
low, _ := ipToUint(con.Low)
|
||||
high, _ := ipToUint(con.High)
|
||||
if low > high {
|
||||
return nil, fmt.Errorf("transform_table Low should be less than High. row (%v) %v>%v (%v)", ri, con.Low, con.High, transforms)
|
||||
return nil, errors.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.Errorf("transform_table_rows should only specify one of NewBases or NewIPs, Not both")
|
||||
}
|
||||
result = append(result, con)
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ func TransformIP(address net.IP, transforms []IpConversion) (net.IP, error) {
|
|||
return nil, err
|
||||
}
|
||||
if len(ips) != 1 {
|
||||
return nil, fmt.Errorf("Expect exactly one ip for TransformIP result. Got: %s", ips)
|
||||
return nil, errors.Errorf("Expect exactly one ip for TransformIP result. Got: %s", ips)
|
||||
}
|
||||
return ips[0], err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"runtime"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// This is the struct that matches either (or both) of the Registrar and/or DNSProvider interfaces:
|
||||
|
@ -38,7 +39,7 @@ func newDNS(config map[string]string, metadata json.RawMessage) (providers.DNSSe
|
|||
if fVal := config["fakeps"]; fVal == "true" {
|
||||
fake = true
|
||||
} else if fVal != "" && fVal != "false" {
|
||||
return nil, fmt.Errorf("fakeps value must be 'true' or 'false'")
|
||||
return nil, errors.Errorf("fakeps value must be 'true' or 'false'")
|
||||
}
|
||||
|
||||
psOut, psLog := config["psout"], config["pslog"]
|
||||
|
@ -56,7 +57,7 @@ func newDNS(config map[string]string, metadata json.RawMessage) (providers.DNSSe
|
|||
if runtime.GOOS == "windows" {
|
||||
srv := config["ADServer"]
|
||||
if srv == "" {
|
||||
return nil, fmt.Errorf("ADServer required for Active Directory provider")
|
||||
return nil, errors.Errorf("ADServer required for Active Directory provider")
|
||||
}
|
||||
p.adServer = srv
|
||||
return p, nil
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/TomOnTime/utfutil"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
|
@ -44,7 +45,7 @@ func (c *adProvider) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Co
|
|||
// Read foundRecords:
|
||||
foundRecords, err := c.getExistingRecords(dc.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("c.getExistingRecords(%v) failed: %v", dc.Name, err)
|
||||
return nil, errors.Errorf("c.getExistingRecords(%v) failed: %v", dc.Name, err)
|
||||
}
|
||||
|
||||
// Normalize
|
||||
|
@ -110,14 +111,14 @@ func (c *adProvider) logErr(e error) error {
|
|||
func (c *adProvider) logHelper(s string) error {
|
||||
logfile, err := os.OpenFile(c.psLog, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0660)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error: Can not create/append to %#v: %v", c.psLog, err)
|
||||
return errors.Errorf("error: Can not create/append to %#v: %v", c.psLog, err)
|
||||
}
|
||||
_, err = fmt.Fprintln(logfile, s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Append to %#v failed: %v", c.psLog, err)
|
||||
return errors.Errorf("Append to %#v failed: %v", c.psLog, err)
|
||||
}
|
||||
if logfile.Close() != nil {
|
||||
return fmt.Errorf("Closing %#v failed: %v", c.psLog, err)
|
||||
return errors.Errorf("Closing %#v failed: %v", c.psLog, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -126,11 +127,11 @@ func (c *adProvider) logHelper(s string) error {
|
|||
func (c *adProvider) powerShellRecord(command string) error {
|
||||
recordfile, err := os.OpenFile(c.psOut, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0660)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not create/append to %#v: %v", c.psOut, err)
|
||||
return errors.Errorf("can not create/append to %#v: %v", c.psOut, err)
|
||||
}
|
||||
_, err = recordfile.WriteString(command)
|
||||
if err != nil {
|
||||
return fmt.Errorf("append to %#v failed: %v", c.psOut, err)
|
||||
return errors.Errorf("append to %#v failed: %v", c.psOut, err)
|
||||
}
|
||||
return recordfile.Close()
|
||||
}
|
||||
|
@ -141,13 +142,13 @@ func (c *adProvider) getExistingRecords(domainname string) ([]*models.RecordConf
|
|||
// Get the JSON either from adzonedump or by running a PowerShell script.
|
||||
data, err := c.getRecords(domainname)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getRecords failed on %#v: %v", domainname, err)
|
||||
return nil, errors.Errorf("getRecords failed on %#v: %v", domainname, err)
|
||||
}
|
||||
|
||||
var recs []*RecordConfigJson
|
||||
err = json.Unmarshal(data, &recs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("json.Unmarshal failed on %#v: %v", domainname, err)
|
||||
return nil, errors.Errorf("json.Unmarshal failed on %#v: %v", domainname, err)
|
||||
}
|
||||
|
||||
result := make([]*models.RecordConfig, 0, len(recs))
|
||||
|
@ -212,7 +213,7 @@ func (c *adProvider) generatePowerShellCreate(domainname string, rec *models.Rec
|
|||
case "NS":
|
||||
text = fmt.Sprintf("\r\n"+`echo "Skipping NS update (%v %v)"`+"\r\n", rec.Name, rec.Target)
|
||||
default:
|
||||
panic(fmt.Errorf("generatePowerShellCreate() does not yet handle recType=%s recName=%#v content=%#v)", rec.Type, rec.Name, content))
|
||||
panic(errors.Errorf("generatePowerShellCreate() does not yet handle recType=%s recName=%#v content=%#v)", rec.Type, rec.Name, content))
|
||||
// We panic so that we quickly find any switch statements
|
||||
// that have not been updated for a new RR type.
|
||||
}
|
||||
|
@ -234,7 +235,7 @@ func (c *adProvider) generatePowerShellModify(domainname, recName, recType, oldC
|
|||
queryField = "HostNameAlias"
|
||||
queryContent = `"` + oldContent + `"`
|
||||
default:
|
||||
panic(fmt.Errorf("generatePowerShellModify() does not yet handle recType=%s recName=%#v content=(%#v, %#v)", recType, recName, oldContent, newContent))
|
||||
panic(errors.Errorf("generatePowerShellModify() does not yet handle recType=%s recName=%#v content=(%#v, %#v)", recType, recName, oldContent, newContent))
|
||||
// We panic so that we quickly find any switch statements
|
||||
// that have not been updated for a new RR type.
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var checkPS sync.Once
|
||||
|
@ -29,7 +31,7 @@ func (c *adProvider) getRecords(domainname string) ([]byte, error) {
|
|||
}
|
||||
})
|
||||
if !psAvailible {
|
||||
return nil, fmt.Errorf("powershell module DnsServer not installed")
|
||||
return nil, errors.Errorf("powershell module DnsServer not installed")
|
||||
}
|
||||
|
||||
_, err := c.powerShellExec(c.generatePowerShellZoneDump(domainname), true)
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -78,7 +79,7 @@ func (c *CloudflareApi) GetNameservers(domain string) ([]*models.Nameserver, err
|
|||
}
|
||||
ns, ok := c.nameservers[domain]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Nameservers for %s not found in cloudflare account", domain)
|
||||
return nil, errors.Errorf("Nameservers for %s not found in cloudflare account", domain)
|
||||
}
|
||||
return models.StringsToNameservers(ns), nil
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ func (c *CloudflareApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models
|
|||
}
|
||||
id, ok := c.domainIndex[dc.Name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s not listed in zones for cloudflare account", dc.Name)
|
||||
return nil, errors.Errorf("%s not listed in zones for cloudflare account", dc.Name)
|
||||
}
|
||||
if err := c.preprocessConfig(dc); err != nil {
|
||||
return nil, err
|
||||
|
@ -201,7 +202,7 @@ const (
|
|||
func checkProxyVal(v string) (string, error) {
|
||||
v = strings.ToLower(v)
|
||||
if v != "on" && v != "off" && v != "full" {
|
||||
return "", fmt.Errorf("Bad metadata value for cloudflare_proxy: '%s'. Use on/off/full", v)
|
||||
return "", errors.Errorf("Bad metadata value for cloudflare_proxy: '%s'. Use on/off/full", v)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
@ -239,7 +240,7 @@ func (c *CloudflareApi) preprocessConfig(dc *models.DomainConfig) error {
|
|||
}
|
||||
if rec.Type != "A" && rec.Type != "CNAME" && rec.Type != "AAAA" && rec.Type != "ALIAS" {
|
||||
if rec.Metadata[metaProxy] != "" {
|
||||
return fmt.Errorf("cloudflare_proxy set on %v record: %#v cloudflare_proxy=%#v", rec.Type, rec.Name, rec.Metadata[metaProxy])
|
||||
return errors.Errorf("cloudflare_proxy set on %v record: %#v cloudflare_proxy=%#v", rec.Type, rec.Name, rec.Metadata[metaProxy])
|
||||
}
|
||||
// Force it to off.
|
||||
rec.Metadata[metaProxy] = "off"
|
||||
|
@ -257,11 +258,11 @@ func (c *CloudflareApi) preprocessConfig(dc *models.DomainConfig) error {
|
|||
// CF_REDIRECT record types. Encode target as $FROM,$TO,$PRIO,$CODE
|
||||
if rec.Type == "CF_REDIRECT" || rec.Type == "CF_TEMP_REDIRECT" {
|
||||
if !c.manageRedirects {
|
||||
return fmt.Errorf("you must add 'manage_redirects: true' metadata to cloudflare provider to use CF_REDIRECT records")
|
||||
return errors.Errorf("you must add 'manage_redirects: true' metadata to cloudflare provider to use CF_REDIRECT records")
|
||||
}
|
||||
parts := strings.Split(rec.Target, ",")
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("Invalid data specified for cloudflare redirect record")
|
||||
return errors.Errorf("Invalid data specified for cloudflare redirect record")
|
||||
}
|
||||
code := 301
|
||||
if rec.Type == "CF_TEMP_REDIRECT" {
|
||||
|
@ -284,7 +285,7 @@ func (c *CloudflareApi) preprocessConfig(dc *models.DomainConfig) error {
|
|||
}
|
||||
ip := net.ParseIP(rec.Target)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("%s is not a valid ip address", rec.Target)
|
||||
return errors.Errorf("%s is not a valid ip address", rec.Target)
|
||||
}
|
||||
newIP, err := transform.TransformIP(ip, c.ipConversions)
|
||||
if err != nil {
|
||||
|
@ -302,7 +303,7 @@ func newCloudflare(m map[string]string, metadata json.RawMessage) (providers.DNS
|
|||
api.ApiUser, api.ApiKey = m["apiuser"], m["apikey"]
|
||||
// check api keys from creds json file
|
||||
if api.ApiKey == "" || api.ApiUser == "" {
|
||||
return nil, fmt.Errorf("cloudflare apikey and apiuser must be provided")
|
||||
return nil, errors.Errorf("cloudflare apikey and apiuser must be provided")
|
||||
}
|
||||
|
||||
err := api.fetchDomainList()
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,10 +33,10 @@ func (c *CloudflareApi) fetchDomainList() error {
|
|||
zr := &zoneResponse{}
|
||||
url := fmt.Sprintf("%s?page=%d&per_page=50", zonesURL, page)
|
||||
if err := c.get(url, zr); err != nil {
|
||||
return fmt.Errorf("Error fetching domain list from cloudflare: %s", err)
|
||||
return errors.Errorf("Error fetching domain list from cloudflare: %s", err)
|
||||
}
|
||||
if !zr.Success {
|
||||
return fmt.Errorf("Error fetching domain list from cloudflare: %s", stringifyErrors(zr.Errors))
|
||||
return errors.Errorf("Error fetching domain list from cloudflare: %s", stringifyErrors(zr.Errors))
|
||||
}
|
||||
for _, zone := range zr.Result {
|
||||
c.domainIndex[zone.Name] = zone.ID
|
||||
|
@ -61,10 +62,10 @@ func (c *CloudflareApi) getRecordsForDomain(id string, domain string) ([]*models
|
|||
reqURL := fmt.Sprintf("%s?page=%d&per_page=100", url, page)
|
||||
var data recordsResponse
|
||||
if err := c.get(reqURL, &data); err != nil {
|
||||
return nil, fmt.Errorf("Error fetching record list from cloudflare: %s", err)
|
||||
return nil, errors.Errorf("Error fetching record list from cloudflare: %s", err)
|
||||
}
|
||||
if !data.Success {
|
||||
return nil, fmt.Errorf("Error fetching record list cloudflare: %s", stringifyErrors(data.Errors))
|
||||
return nil, errors.Errorf("Error fetching record list cloudflare: %s", stringifyErrors(data.Errors))
|
||||
}
|
||||
for _, rec := range data.Result {
|
||||
// fmt.Printf("REC: %+v\n", rec)
|
||||
|
@ -202,7 +203,7 @@ func (c *CloudflareApi) createRec(rec *models.RecordConfig, domainID string) []*
|
|||
|
||||
func (c *CloudflareApi) modifyRecord(domainID, recID string, proxied bool, rec *models.RecordConfig) error {
|
||||
if domainID == "" || recID == "" {
|
||||
return fmt.Errorf("cannot modify record if domain or record id are empty")
|
||||
return errors.Errorf("cannot modify record if domain or record id are empty")
|
||||
}
|
||||
type record struct {
|
||||
ID string `json:"id"`
|
||||
|
@ -247,10 +248,10 @@ func handleActionResponse(resp *http.Response, err error) (id string, e error) {
|
|||
result := &basicResponse{}
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
if err = decoder.Decode(result); err != nil {
|
||||
return "", fmt.Errorf("Unknown error. Status code: %d", resp.StatusCode)
|
||||
return "", errors.Errorf("Unknown error. Status code: %d", resp.StatusCode)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return "", fmt.Errorf(stringifyErrors(result.Errors))
|
||||
return "", errors.Errorf(stringifyErrors(result.Errors))
|
||||
}
|
||||
return result.Result.ID, nil
|
||||
}
|
||||
|
@ -273,7 +274,7 @@ func (c *CloudflareApi) get(endpoint string, target interface{}) error {
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("bad status code from cloudflare: %d not 200", resp.StatusCode)
|
||||
return errors.Errorf("bad status code from cloudflare: %d not 200", resp.StatusCode)
|
||||
}
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
return decoder.Decode(target)
|
||||
|
@ -283,10 +284,10 @@ func (c *CloudflareApi) getPageRules(id string, domain string) ([]*models.Record
|
|||
url := fmt.Sprintf(pageRulesURL, id)
|
||||
data := pageRuleResponse{}
|
||||
if err := c.get(url, &data); err != nil {
|
||||
return nil, fmt.Errorf("Error fetching page rule list from cloudflare: %s", err)
|
||||
return nil, errors.Errorf("Error fetching page rule list from cloudflare: %s", err)
|
||||
}
|
||||
if !data.Success {
|
||||
return nil, fmt.Errorf("Error fetching page rule list cloudflare: %s", stringifyErrors(data.Errors))
|
||||
return nil, errors.Errorf("Error fetching page rule list cloudflare: %s", stringifyErrors(data.Errors))
|
||||
}
|
||||
recs := []*models.RecordConfig{}
|
||||
for _, pr := range data.Result {
|
||||
|
|
|
@ -6,12 +6,12 @@ package config
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/DisposaBoy/JsonConfigReader"
|
||||
"github.com/TomOnTime/utfutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// LoadProviderConfigs will open the specified file name, and parse its contents. It will replace environment variables it finds if any value matches $[A-Za-z_-0-9]+
|
||||
|
@ -23,13 +23,13 @@ func LoadProviderConfigs(fname string) (map[string]map[string]string, error) {
|
|||
if os.IsNotExist(err) {
|
||||
return results, nil
|
||||
}
|
||||
return nil, fmt.Errorf("While reading provider credentials file %v: %v", fname, err)
|
||||
return nil, errors.Errorf("While reading provider credentials file %v: %v", fname, err)
|
||||
}
|
||||
s := string(dat)
|
||||
r := JsonConfigReader.New(strings.NewReader(s))
|
||||
err = json.NewDecoder(r).Decode(&results)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("While parsing provider credentials file %v: %v", fname, err)
|
||||
return nil, errors.Errorf("While parsing provider credentials file %v: %v", fname, err)
|
||||
}
|
||||
if err = replaceEnvVars(results); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/digitalocean/godo"
|
||||
"golang.org/x/oauth2"
|
||||
|
@ -38,7 +39,7 @@ var defaultNameServerNames = []string{
|
|||
// NewDo creates a DO-specific DNS provider.
|
||||
func NewDo(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||
if m["token"] == "" {
|
||||
return nil, fmt.Errorf("no Digitalocean token provided")
|
||||
return nil, errors.Errorf("no Digitalocean token provided")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -56,7 +57,7 @@ func NewDo(m map[string]string, metadata json.RawMessage) (providers.DNSServiceP
|
|||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("token for digitalocean is not valid")
|
||||
return nil, errors.Errorf("token for digitalocean is not valid")
|
||||
}
|
||||
|
||||
return api, nil
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
dnsimpleapi "github.com/dnsimple/dnsimple-go/dnsimple"
|
||||
)
|
||||
|
@ -180,7 +181,7 @@ func (c *DnsimpleApi) getAccountID() (string, error) {
|
|||
return "", err
|
||||
}
|
||||
if whoamiResponse.Data.User != nil && whoamiResponse.Data.Account == nil {
|
||||
return "", fmt.Errorf("DNSimple token appears to be a user token. Please supply an account token")
|
||||
return "", errors.Errorf("DNSimple token appears to be a user token. Please supply an account token")
|
||||
}
|
||||
c.accountID = strconv.Itoa(whoamiResponse.Data.Account.ID)
|
||||
}
|
||||
|
@ -349,7 +350,7 @@ func newProvider(m map[string]string, metadata json.RawMessage) (*DnsimpleApi, e
|
|||
api := &DnsimpleApi{}
|
||||
api.AccountToken = m["token"]
|
||||
if api.AccountToken == "" {
|
||||
return nil, fmt.Errorf("missing DNSimple token")
|
||||
return nil, errors.Errorf("missing DNSimple token")
|
||||
}
|
||||
|
||||
if m["baseurl"] != "" {
|
||||
|
|
|
@ -58,7 +58,7 @@ func (c *GandiApi) getDomainInfo(domain string) (*gandidomain.DomainInfo, error)
|
|||
}
|
||||
_, ok := c.domainIndex[domain]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s not listed in zones for gandi account", domain)
|
||||
return nil, errors.Errorf("%s not listed in zones for gandi account", domain)
|
||||
}
|
||||
return c.fetchDomainInfo(domain)
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ func newGandi(m map[string]string, metadata json.RawMessage) (*GandiApi, error)
|
|||
api := &GandiApi{}
|
||||
api.ApiKey = m["apikey"]
|
||||
if api.ApiKey == "" {
|
||||
return nil, fmt.Errorf("missing Gandi apikey")
|
||||
return nil, errors.Errorf("missing Gandi apikey")
|
||||
}
|
||||
|
||||
return api, nil
|
||||
|
|
|
@ -3,10 +3,11 @@ package linode
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -22,7 +23,7 @@ func (c *LinodeApi) fetchDomainList() error {
|
|||
dr := &domainResponse{}
|
||||
endpoint := fmt.Sprintf("%s?page=%d", domainsPath, page)
|
||||
if err := c.get(endpoint, dr); err != nil {
|
||||
return fmt.Errorf("Error fetching domain list from Linode: %s", err)
|
||||
return errors.Errorf("Error fetching domain list from Linode: %s", err)
|
||||
}
|
||||
for _, domain := range dr.Data {
|
||||
c.domainIndex[domain.Domain] = domain.ID
|
||||
|
@ -42,7 +43,7 @@ func (c *LinodeApi) getRecords(id int) ([]domainRecord, error) {
|
|||
dr := &recordResponse{}
|
||||
endpoint := fmt.Sprintf("%s/%d/records?page=%d", domainsPath, id, page)
|
||||
if err := c.get(endpoint, dr); err != nil {
|
||||
return nil, fmt.Errorf("Error fetching record list from Linode: %s", err)
|
||||
return nil, errors.Errorf("Error fetching record list from Linode: %s", err)
|
||||
}
|
||||
|
||||
records = append(records, dr.Data...)
|
||||
|
@ -173,7 +174,7 @@ func (c *LinodeApi) handleErrors(resp *http.Response) error {
|
|||
errs := &errorResponse{}
|
||||
|
||||
if err := decoder.Decode(errs); err != nil {
|
||||
return fmt.Errorf("bad status code from Linode: %d not 200. Failed to decode response", resp.StatusCode)
|
||||
return errors.Errorf("bad status code from Linode: %d not 200. Failed to decode response", resp.StatusCode)
|
||||
}
|
||||
|
||||
buf := bytes.NewBufferString(fmt.Sprintf("bad status code from Linode: %d not 200", resp.StatusCode))
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"net/url"
|
||||
|
||||
|
@ -63,7 +64,7 @@ var defaultNameServerNames = []string{
|
|||
// NewLinode creates the provider.
|
||||
func NewLinode(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||
if m["token"] == "" {
|
||||
return nil, fmt.Errorf("Missing Linode token")
|
||||
return nil, errors.Errorf("Missing Linode token")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
@ -74,7 +75,7 @@ func NewLinode(m map[string]string, metadata json.RawMessage) (providers.DNSServ
|
|||
|
||||
baseURL, err := url.Parse(defaultBaseURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Linode base URL not valid")
|
||||
return nil, errors.Errorf("Linode base URL not valid")
|
||||
}
|
||||
|
||||
api := &LinodeApi{client: client, baseURL: baseURL}
|
||||
|
@ -118,7 +119,7 @@ func (api *LinodeApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models.C
|
|||
}
|
||||
domainID, ok := api.domainIndex[dc.Name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s not listed in domains for Linode account", dc.Name)
|
||||
return nil, errors.Errorf("%s not listed in domains for Linode account", dc.Name)
|
||||
}
|
||||
|
||||
records, err := api.getRecords(domainID)
|
||||
|
@ -273,7 +274,7 @@ func toReq(dc *models.DomainConfig, rc *models.RecordConfig) (*recordEditRequest
|
|||
result := srvRegexp.FindStringSubmatch(req.Name)
|
||||
|
||||
if len(result) != 3 {
|
||||
return nil, fmt.Errorf("SRV Record must match format \"_service._protocol\" not %s", req.Name)
|
||||
return nil, errors.Errorf("SRV Record must match format \"_service._protocol\" not %s", req.Name)
|
||||
}
|
||||
|
||||
var serviceName, protocol string = result[1], strings.ToLower(result[2])
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
nc "github.com/billputer/go-namecheap"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// NamecheapDefaultNs lists the default nameservers for this provider.
|
||||
|
@ -59,7 +60,7 @@ func newProvider(m map[string]string, metadata json.RawMessage) (*Namecheap, err
|
|||
api := &Namecheap{}
|
||||
api.ApiUser, api.ApiKey = m["apiuser"], m["apikey"]
|
||||
if api.ApiKey == "" || api.ApiUser == "" {
|
||||
return nil, fmt.Errorf("missing Namecheap apikey and apiuser")
|
||||
return nil, errors.Errorf("missing Namecheap apikey and apiuser")
|
||||
}
|
||||
api.client = nc.NewClient(api.ApiUser, api.ApiKey, api.ApiUser)
|
||||
// if BaseURL is specified in creds, use that url
|
||||
|
|
|
@ -3,10 +3,10 @@ package namedotcom
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/namedotcom/go/namecom"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const defaultAPIBase = "api.name.com"
|
||||
|
@ -43,7 +43,7 @@ func newProvider(conf map[string]string) (*NameCom, error) {
|
|||
api.client.Server = conf["apiurl"]
|
||||
api.APIUser, api.APIKey, api.APIUrl = conf["apiuser"], conf["apikey"], conf["apiurl"]
|
||||
if api.APIKey == "" || api.APIUser == "" {
|
||||
return nil, fmt.Errorf("missing Name.com apikey or apiuser")
|
||||
return nil, errors.Errorf("missing Name.com apikey or apiuser")
|
||||
}
|
||||
if api.APIUrl == "" {
|
||||
api.APIUrl = defaultAPIBase
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"net/http"
|
||||
|
||||
|
@ -34,7 +35,7 @@ type nsone struct {
|
|||
|
||||
func newProvider(creds map[string]string, meta json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||
if creds["api_token"] == "" {
|
||||
return nil, fmt.Errorf("api_token required for ns1")
|
||||
return nil, errors.Errorf("api_token required for ns1")
|
||||
}
|
||||
return &nsone{rest.NewClient(http.DefaultClient, rest.SetAPIKey(creds["api_token"]))}, nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/xlucas/go-ovh/ovh"
|
||||
)
|
||||
|
||||
|
@ -61,7 +62,7 @@ func (c *ovhProvider) GetNameservers(domain string) ([]*models.Nameserver, error
|
|||
}
|
||||
_, ok := c.zones[domain]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s not listed in zones for ovh account", domain)
|
||||
return nil, errors.Errorf("%s not listed in zones for ovh account", domain)
|
||||
}
|
||||
|
||||
ns, err := c.fetchNS(domain)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Void an empty structure.
|
||||
|
@ -253,7 +254,7 @@ func (c *ovhProvider) updateNS(fqdn string, ns []string) error {
|
|||
}
|
||||
|
||||
if task.Status == "error" {
|
||||
return fmt.Errorf("API error while updating ns for %s: %s", fqdn, task.Comment)
|
||||
return errors.Errorf("API error while updating ns for %s: %s", fqdn, task.Comment)
|
||||
}
|
||||
|
||||
// we don't wait for the task execution. One of the reason is that
|
||||
|
|
|
@ -2,10 +2,10 @@ package providers
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Registrar is an interface for a domain registrar. It can return a list of needed corrections to be applied in the future.
|
||||
|
@ -58,7 +58,7 @@ func RegisterDomainServiceProviderType(name string, init DspInitializer, pm ...P
|
|||
func CreateRegistrar(rType string, config map[string]string) (Registrar, error) {
|
||||
initer, ok := RegistrarTypes[rType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("registrar type %s not declared", rType)
|
||||
return nil, errors.Errorf("registrar type %s not declared", rType)
|
||||
}
|
||||
return initer(config)
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func CreateRegistrar(rType string, config map[string]string) (Registrar, error)
|
|||
func CreateDNSProvider(dType string, config map[string]string, meta json.RawMessage) (DNSServiceProvider, error) {
|
||||
initer, ok := DNSProviderTypes[dType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("DSP type %s not declared", dType)
|
||||
return nil, errors.Errorf("DSP type %s not declared", dType)
|
||||
}
|
||||
return initer(config, meta)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/softlayer/softlayer-go/datatypes"
|
||||
"github.com/softlayer/softlayer-go/filter"
|
||||
|
@ -34,7 +35,7 @@ func newReg(conf map[string]string, _ json.RawMessage) (providers.DNSServiceProv
|
|||
s := session.New(conf["username"], conf["api_key"], conf["endpoint_url"], conf["timeout"])
|
||||
|
||||
if len(s.UserName) == 0 || len(s.APIKey) == 0 {
|
||||
return nil, fmt.Errorf("SoftLayer UserName and APIKey must be provided")
|
||||
return nil, errors.Errorf("SoftLayer UserName and APIKey must be provided")
|
||||
}
|
||||
|
||||
// s.Debug = true
|
||||
|
@ -108,9 +109,9 @@ func (s *SoftLayer) getDomain(name *string) (*datatypes.Dns_Domain, error) {
|
|||
}
|
||||
|
||||
if len(domains) == 0 {
|
||||
return nil, fmt.Errorf("Didn't find a domain matching %s", *name)
|
||||
return nil, errors.Errorf("Didn't find a domain matching %s", *name)
|
||||
} else if len(domains) > 1 {
|
||||
return nil, fmt.Errorf("Found %d domains matching %s", len(domains), *name)
|
||||
return nil, errors.Errorf("Found %d domains matching %s", len(domains), *name)
|
||||
}
|
||||
|
||||
return &domains[0], nil
|
||||
|
@ -210,7 +211,7 @@ func (s *SoftLayer) createRecordFunc(desired *models.RecordConfig, domain *datat
|
|||
result := srvRegexp.FindStringSubmatch(host)
|
||||
|
||||
if len(result) != 3 {
|
||||
return fmt.Errorf("SRV Record must match format \"_service._protocol\" not %s", host)
|
||||
return errors.Errorf("SRV Record must match format \"_service._protocol\" not %s", host)
|
||||
}
|
||||
|
||||
var serviceName, protocol string = result[1], strings.ToLower(result[2])
|
||||
|
@ -280,7 +281,7 @@ func (s *SoftLayer) updateRecordFunc(existing *datatypes.Dns_Domain_ResourceReco
|
|||
}
|
||||
|
||||
if !changes {
|
||||
return fmt.Errorf("didn't find changes when I expect some")
|
||||
return errors.Errorf("didn't find changes when I expect some")
|
||||
}
|
||||
|
||||
_, err = service.Id(*existing.Id).EditObject(&updated)
|
||||
|
@ -323,7 +324,7 @@ func (s *SoftLayer) updateRecordFunc(existing *datatypes.Dns_Domain_ResourceReco
|
|||
// delete and recreate?
|
||||
|
||||
if !changes {
|
||||
return fmt.Errorf("didn't find changes when I expect some")
|
||||
return errors.Errorf("didn't find changes when I expect some")
|
||||
}
|
||||
|
||||
_, err = service.Id(*existing.Id).EditObject(&updated)
|
||||
|
@ -348,7 +349,7 @@ func (s *SoftLayer) updateRecordFunc(existing *datatypes.Dns_Domain_ResourceReco
|
|||
}
|
||||
|
||||
if !changes {
|
||||
return fmt.Errorf("didn't find changes when I expect some")
|
||||
return errors.Errorf("didn't find changes when I expect some")
|
||||
}
|
||||
|
||||
_, err = service.Id(*existing.Id).EditObject(&updated)
|
||||
|
|
|
@ -2,17 +2,16 @@ package vultr
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
vultr "github.com/JamesClonk/vultr/lib"
|
||||
"github.com/StackExchange/dnscontrol/models"
|
||||
"github.com/StackExchange/dnscontrol/providers"
|
||||
"github.com/StackExchange/dnscontrol/providers/diff"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
|
||||
vultr "github.com/JamesClonk/vultr/lib"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -57,7 +56,7 @@ func NewVultr(m map[string]string, metadata json.RawMessage) (providers.DNSServi
|
|||
}
|
||||
|
||||
if api.token == "" {
|
||||
return nil, fmt.Errorf("Vultr API token is required")
|
||||
return nil, errors.Errorf("Vultr API token is required")
|
||||
}
|
||||
|
||||
api.client = vultr.NewClient(api.token, nil)
|
||||
|
@ -81,7 +80,7 @@ func (api *VultrApi) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Co
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s is not a domain in the Vultr account", dc.Name)
|
||||
return nil, errors.Errorf("%s is not a domain in the Vultr account", dc.Name)
|
||||
}
|
||||
|
||||
records, err := api.client.GetDNSRecords(dc.Name)
|
||||
|
@ -166,7 +165,7 @@ func (api *VultrApi) EnsureDomainExists(domain string) error {
|
|||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("Unexpected error adding domain %s to Vultr account", domain)
|
||||
return errors.Errorf("Unexpected error adding domain %s to Vultr account", domain)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +232,7 @@ func toRecordConfig(dc *models.DomainConfig, r *vultr.DNSRecord) (*models.Record
|
|||
// Vultr returns in the format "[weight] [port] [target]"
|
||||
splitData := strings.SplitN(rc.Target, " ", 3)
|
||||
if len(splitData) != 3 {
|
||||
return nil, fmt.Errorf("Unexpected data for SRV record returned by Vultr")
|
||||
return nil, errors.Errorf("Unexpected data for SRV record returned by Vultr")
|
||||
}
|
||||
|
||||
weight, err := strconv.ParseUint(splitData[0], 10, 16)
|
||||
|
@ -264,7 +263,7 @@ func toRecordConfig(dc *models.DomainConfig, r *vultr.DNSRecord) (*models.Record
|
|||
|
||||
splitData := strings.SplitN(rc.Target, " ", 3)
|
||||
if len(splitData) != 3 {
|
||||
return nil, fmt.Errorf("Unexpected data for CAA record returned by Vultr")
|
||||
return nil, errors.Errorf("Unexpected data for CAA record returned by Vultr")
|
||||
}
|
||||
|
||||
flag, err := strconv.ParseUint(splitData[0], 10, 8)
|
||||
|
|
Loading…
Reference in a new issue