mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-09-07 21:54:59 +08:00
Merge branch 'main' into tlim_puny
This commit is contained in:
commit
2689cd88bd
23 changed files with 1119 additions and 149 deletions
2
.github/workflows/pr_test.yml
vendored
2
.github/workflows/pr_test.yml
vendored
|
@ -96,7 +96,7 @@ jobs:
|
|||
if: github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: golang:1.21
|
||||
image: golang:1.22
|
||||
needs:
|
||||
- integration-test-providers
|
||||
env:
|
||||
|
|
2
.github/workflows/release_draft.yml
vendored
2
.github/workflows/release_draft.yml
vendored
|
@ -42,7 +42,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.21
|
||||
go-version: ^1.22
|
||||
|
||||
# Stringer is needed because .goreleaser includes "go generate ./..."
|
||||
- name: Install stringer
|
||||
|
|
|
@ -159,9 +159,9 @@ release:
|
|||
## Deprecation warnings
|
||||
|
||||
> [!WARNING]
|
||||
> - **32-bit binaries will no longer be distributed after September 10, 2023.** There is a proposal to stop shipping 32-bit binaries (packages and containers). If no objections are raised by Sept 10, 2023, new releases will not include them. See https://github.com/StackExchange/dnscontrol/issues/2461 for details.
|
||||
> - **MSDNS maintainer needed!** Without a new volunteer, this DNS provider will lose support after April 2025. See https://github.com/StackExchange/dnscontrol/issues/2878
|
||||
> - **Call for new volunteer maintainers for NAMEDOTCOM and SOFTLAYER.** These providers have no maintainer. Maintainers respond to PRs and fix bugs in a timely manner, and try to stay on top of protocol changes.
|
||||
> - **ACME/Let's Encrypt support is frozen and will be removed after December 31, 2022.** The `get-certs` command (renews certs via Let's Encrypt) has no maintainer. There are other projects that do a better job. If you don't use this feature, please do not start. If you do use this feature, please plan on migrating to something else. See discussion in [issues/1400](https://github.com/StackExchange/dnscontrol/issues/1400)
|
||||
> - **ACME/Let's Encrypt support is frozen and will be removed without notice between now and April 2025.** It has been unsupported since December 2022. If you don't use this feature, do not start. If you do use this feature, migrate ASAP. See discussion in [issues/1400](https://github.com/StackExchange/dnscontrol/issues/1400)
|
||||
|
||||
## Install
|
||||
|
||||
|
|
|
@ -158,11 +158,11 @@ DNSControl can be installed via packages for macOS, Linux and Windows, or from s
|
|||
|
||||
See [dnscontrol-action](https://github.com/koenrh/dnscontrol-action) or [gacts/install-dnscontrol](https://github.com/gacts/install-dnscontrol).
|
||||
|
||||
## Deprecation warnings (updated 2024-02-24)
|
||||
## Deprecation warnings (updated 2024-03-25)
|
||||
|
||||
- **32-bit binaries will no longer be distributed after September 10, 2023.** There is a proposal to stop shipping 32-bit binaries (packages and containers). If no objections are raised by Sept 10, 2023, new releases will not include them. See https://github.com/StackExchange/dnscontrol/issues/2461 for details.
|
||||
- **MSDNS maintainer needed!** Without a new volunteer, this DNS provider will lose support after April 2025. See https://github.com/StackExchange/dnscontrol/issues/2878
|
||||
- **Call for new volunteer maintainers for NAMEDOTCOM and SOFTLAYER.** These providers have no maintainer. Maintainers respond to PRs and fix bugs in a timely manner, and try to stay on top of protocol changes.
|
||||
- **ACME/Let's Encrypt support is frozen and will be removed after December 31, 2022.** The `get-certs` command (renews certs via Let's Encrypt) has no maintainer. There are other projects that do a better job. If you don't use this feature, please do not start. If you do use this feature, please plan on migrating to something else. See discussion in [issues/1400](https://github.com/StackExchange/dnscontrol/issues/1400)
|
||||
- **ACME/Let's Encrypt support is frozen and will be removed without notice between now and April 2025.** It has been unsupported since December 2022. If you don't use this feature, do not start. If you do use this feature, migrate ASAP. See discussion in [issues/1400](https://github.com/StackExchange/dnscontrol/issues/1400)
|
||||
|
||||
## More info at our website
|
||||
|
||||
|
|
783
commands/ppreviewPush.go
Normal file
783
commands/ppreviewPush.go
Normal file
|
@ -0,0 +1,783 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v4/models"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/bindserial"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/credsfile"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/nameservers"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/normalize"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/notifications"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/zonerecs"
|
||||
"github.com/StackExchange/dnscontrol/v4/providers"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
type zoneCache struct {
|
||||
cache map[string]*[]string
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var _ = cmd(catMain, func() *cli.Command {
|
||||
var args PPreviewArgs
|
||||
return &cli.Command{
|
||||
Name: "ppreview",
|
||||
Usage: "read live configuration and identify changes to be made, without applying them",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
return exit(PPreview(args))
|
||||
},
|
||||
Flags: args.flags(),
|
||||
}
|
||||
}())
|
||||
|
||||
// PPreviewArgs contains all data/flags needed to run preview, independently of CLI
|
||||
type PPreviewArgs struct {
|
||||
GetDNSConfigArgs
|
||||
GetCredentialsArgs
|
||||
FilterArgs
|
||||
Notify bool
|
||||
WarnChanges bool
|
||||
ConcurMode string
|
||||
NoPopulate bool
|
||||
DePopulate bool
|
||||
Full bool
|
||||
}
|
||||
|
||||
// ReportItem is a record of corrections for a particular domain/provider/registrar.
|
||||
//type ReportItem struct {
|
||||
// Domain string `json:"domain"`
|
||||
// Corrections int `json:"corrections"`
|
||||
// Provider string `json:"provider,omitempty"`
|
||||
// Registrar string `json:"registrar,omitempty"`
|
||||
//}
|
||||
|
||||
func (args *PPreviewArgs) flags() []cli.Flag {
|
||||
flags := args.GetDNSConfigArgs.flags()
|
||||
flags = append(flags, args.GetCredentialsArgs.flags()...)
|
||||
flags = append(flags, args.FilterArgs.flags()...)
|
||||
flags = append(flags, &cli.BoolFlag{
|
||||
Name: "notify",
|
||||
Destination: &args.Notify,
|
||||
Usage: `set to true to send notifications to configured destinations`,
|
||||
})
|
||||
flags = append(flags, &cli.BoolFlag{
|
||||
Name: "expect-no-changes",
|
||||
Destination: &args.WarnChanges,
|
||||
Usage: `set to true for non-zero return code if there are changes`,
|
||||
})
|
||||
flags = append(flags, &cli.StringFlag{
|
||||
Name: "cmode",
|
||||
Destination: &args.ConcurMode,
|
||||
Value: "default",
|
||||
Usage: `Which providers to run concurrently: all, default, none`,
|
||||
Action: func(c *cli.Context, s string) error {
|
||||
if !slices.Contains([]string{"all", "default", "none"}, s) {
|
||||
fmt.Printf("%q is not a valid option for --cmode. Valie are: all, default, none", s)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
flags = append(flags, &cli.BoolFlag{
|
||||
Name: "no-populate",
|
||||
Destination: &args.NoPopulate,
|
||||
Usage: `Do not auto-create zones at the provider`,
|
||||
})
|
||||
flags = append(flags, &cli.BoolFlag{
|
||||
Name: "depopulate",
|
||||
Destination: &args.NoPopulate,
|
||||
Usage: `Delete unknown zones at provider (dangerous!)`,
|
||||
})
|
||||
flags = append(flags, &cli.BoolFlag{
|
||||
Name: "full",
|
||||
Destination: &args.Full,
|
||||
Usage: `Add headings, providers names, notifications of no changes, etc`,
|
||||
})
|
||||
flags = append(flags, &cli.IntFlag{
|
||||
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
|
||||
return nil
|
||||
},
|
||||
})
|
||||
flags = append(flags, &cli.Int64Flag{
|
||||
Name: "bindserial",
|
||||
Destination: &bindserial.ForcedValue,
|
||||
Usage: `Force BIND serial numbers to this value (for reproducibility)`,
|
||||
})
|
||||
return flags
|
||||
}
|
||||
|
||||
var _ = cmd(catMain, func() *cli.Command {
|
||||
var args PPushArgs
|
||||
return &cli.Command{
|
||||
Name: "ppush",
|
||||
Usage: "identify changes to be made, and perform them",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
return exit(PPush(args))
|
||||
},
|
||||
Flags: args.flags(),
|
||||
}
|
||||
}())
|
||||
|
||||
// PPushArgs contains all data/flags needed to run push, independently of CLI
|
||||
type PPushArgs struct {
|
||||
PPreviewArgs
|
||||
Interactive bool
|
||||
Report string
|
||||
}
|
||||
|
||||
func (args *PPushArgs) flags() []cli.Flag {
|
||||
flags := args.PPreviewArgs.flags()
|
||||
flags = append(flags, &cli.BoolFlag{
|
||||
Name: "i",
|
||||
Destination: &args.Interactive,
|
||||
Usage: "Interactive. Confirm or Exclude each correction before they run",
|
||||
})
|
||||
flags = append(flags, &cli.StringFlag{
|
||||
Name: "report",
|
||||
Destination: &args.Report,
|
||||
Usage: `Generate a machine-parseable report of performed corrections.`,
|
||||
})
|
||||
return flags
|
||||
}
|
||||
|
||||
// PPreview implements the preview subcommand.
|
||||
func PPreview(args PPreviewArgs) error {
|
||||
return prun(args, false, false, printer.DefaultPrinter, "")
|
||||
}
|
||||
|
||||
// PPush implements the push subcommand.
|
||||
func PPush(args PPushArgs) error {
|
||||
return prun(args.PPreviewArgs, true, args.Interactive, printer.DefaultPrinter, args.Report)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
if pobsoleteDiff2FlagUsed {
|
||||
printer.Println("WARNING: Please remove obsolete --diff2 flag. This will be an error in v5 or later. See https://github.com/StackExchange/dnscontrol/issues/2262")
|
||||
}
|
||||
|
||||
out.PrintfIf(fullMode, "Reading dnsconfig.js or equiv.\n")
|
||||
cfg, err := GetDNSConfig(args.GetDNSConfigArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.PrintfIf(fullMode, "Reading creds.json or equiv.\n")
|
||||
providerConfigs, err := credsfile.LoadProviderConfigs(args.CredsFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.PrintfIf(fullMode, "Creating an in-memory model of 'desired'...\n")
|
||||
notifier, err := PInitializeProviders(cfg, providerConfigs, args.Notify)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.PrintfIf(fullMode, "Normalizing and validating 'desired'..\n")
|
||||
errs := normalize.ValidateAndNormalizeConfig(cfg)
|
||||
if PrintValidationErrors(errs) {
|
||||
return fmt.Errorf("exiting due to validation errors")
|
||||
}
|
||||
|
||||
zcache := NewZoneCache()
|
||||
|
||||
// Loop over all (or some) zones:
|
||||
zonesToProcess := whichZonesToProcess(cfg.Domains, args.Domains)
|
||||
zonesSerial, zonesConcurrent := splitConcurrent(zonesToProcess, args.ConcurMode)
|
||||
out.PrintfIf(fullMode, "PHASE 1: GATHERING data\n")
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(zonesConcurrent))
|
||||
out.Printf("CONCURRENTLY gathering %d zone(s)\n", len(zonesConcurrent))
|
||||
for _, zone := range optimizeOrder(zonesConcurrent) {
|
||||
out.PrintfIf(fullMode, "Concurrently gathering: %q\n", zone.Name)
|
||||
go func(zone *models.DomainConfig, args PPreviewArgs, zcache *zoneCache) {
|
||||
defer wg.Done()
|
||||
oneZone(zone, args, zcache)
|
||||
}(zone, args, zcache)
|
||||
}
|
||||
out.Printf("SERIALLY gathering %d zone(s)\n", len(zonesSerial))
|
||||
for _, zone := range zonesSerial {
|
||||
out.Printf("Serially Gathering: %q\n", zone.Name)
|
||||
oneZone(zone, args, zcache)
|
||||
}
|
||||
out.PrintfIf(len(zonesConcurrent) > 0, "Waiting for concurrent gathering(s) to complete...")
|
||||
wg.Wait()
|
||||
out.PrintfIf(len(zonesConcurrent) > 0, "DONE\n")
|
||||
|
||||
// Now we know what to do, print or do the tasks.
|
||||
out.PrintfIf(fullMode, "PHASE 2: CORRECTIONS\n")
|
||||
var totalCorrections int
|
||||
var reportItems []*ReportItem
|
||||
var anyErrors bool
|
||||
for _, zone := range zonesToProcess {
|
||||
out.StartDomain(zone.GetUniqueName())
|
||||
providersToProcess := whichProvidersToProcess(zone.DNSProviderInstances, args.Providers)
|
||||
for _, provider := range zone.DNSProviderInstances {
|
||||
skip := skipProvider(provider.Name, providersToProcess)
|
||||
out.StartDNSProvider(provider.Name, skip)
|
||||
if !skip {
|
||||
corrections := zone.GetCorrections(provider.Name)
|
||||
totalCorrections += len(corrections)
|
||||
reportItems = append(reportItems, genReportItem(zone.Name, corrections, provider.Name))
|
||||
anyErrors = cmp.Or(anyErrors, pprintOrRunCorrections(zone.Name, provider.Name, corrections, out, push, interactive, notifier, report))
|
||||
out.EndProvider(provider.Name, len(corrections), nil)
|
||||
}
|
||||
}
|
||||
skip := skipProvider(zone.RegistrarInstance.Name, providersToProcess)
|
||||
out.StartRegistrar(zone.RegistrarName, !skip)
|
||||
if skip {
|
||||
corrections := zone.GetCorrections(zone.RegistrarInstance.Name)
|
||||
totalCorrections += len(corrections)
|
||||
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))
|
||||
out.EndProvider(zone.RegistrarName, len(corrections), nil)
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("TEAMCITY_VERSION") != "" {
|
||||
fmt.Fprintf(os.Stderr, "##teamcity[buildStatus status='SUCCESS' text='%d corrections']", totalCorrections)
|
||||
}
|
||||
notifier.Done()
|
||||
out.Printf("Done. %d corrections.\n", totalCorrections)
|
||||
err = writeReport(report, reportItems)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write report")
|
||||
}
|
||||
if anyErrors {
|
||||
return fmt.Errorf("completed with errors")
|
||||
}
|
||||
if totalCorrections != 0 && args.WarnChanges {
|
||||
return fmt.Errorf("there are pending changes")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func whichZonesToProcess(domains []*models.DomainConfig, filter string) []*models.DomainConfig {
|
||||
if filter == "" || filter == "all" {
|
||||
return domains
|
||||
}
|
||||
|
||||
permitList := strings.Split(filter, ",")
|
||||
var picked []*models.DomainConfig
|
||||
for _, domain := range domains {
|
||||
if domainInList(domain.Name, permitList) {
|
||||
picked = append(picked, domain)
|
||||
}
|
||||
}
|
||||
return picked
|
||||
}
|
||||
|
||||
// splitConcurrent takes a list of DomainConfigs and returns two lists. The
|
||||
// first list is the items that do NOT support concurrency. The second is list
|
||||
// the items that DO support concurrency.
|
||||
func splitConcurrent(domains []*models.DomainConfig, filter string) (serial []*models.DomainConfig, concurrent []*models.DomainConfig) {
|
||||
if filter == "none" {
|
||||
return domains, nil
|
||||
} else if filter == "all" {
|
||||
return nil, domains
|
||||
}
|
||||
for _, dc := range domains {
|
||||
if allConcur(dc) {
|
||||
concurrent = append(concurrent, dc)
|
||||
} else {
|
||||
serial = append(serial, dc)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// allConcur returns true if its registrar and all DNS providers support
|
||||
// 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)
|
||||
return false
|
||||
}
|
||||
for _, p := range dc.DNSProviderInstances {
|
||||
if !providers.ProviderHasCapability(p.ProviderType, providers.CanConcur) {
|
||||
//fmt.Printf("WHY? %q: %+v\n", dc.Name, p)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// optimizeOrder returns a list of DomainConfigs so that they gather fastest.
|
||||
//
|
||||
// The current algorithm is based on the heuistic that larger zones (zones with
|
||||
// the most records) need the most time to be processed. Therefore, the largest
|
||||
// zones are moved to the front of the list.
|
||||
// This isn't perfect but it is good enough.
|
||||
func optimizeOrder(zones []*models.DomainConfig) []*models.DomainConfig {
|
||||
slices.SortFunc(zones, func(a, b *models.DomainConfig) int {
|
||||
return len(b.Records) - len(a.Records) // Biggest to smallest.
|
||||
})
|
||||
|
||||
// // For benchmarking. Randomize the list. If you aren't better
|
||||
// // than random, you might as well not play.
|
||||
// rand.Shuffle(len(zones), func(i, j int) {
|
||||
// zones[i], zones[j] = zones[j], zones[i]
|
||||
// })
|
||||
|
||||
return zones
|
||||
}
|
||||
|
||||
func oneZone(zone *models.DomainConfig, args PPreviewArgs, zc *zoneCache) {
|
||||
// Fix the parent zone's delegation: (if able/needed)
|
||||
//zone.NameserversMutex.Lock()
|
||||
delegationCorrections := generateDelegationCorrections(zone, zone.DNSProviderInstances, zone.RegistrarInstance)
|
||||
//zone.NameserversMutex.Unlock()
|
||||
|
||||
// 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)
|
||||
zone.StoreCorrections(provider.Name, populateCorrections)
|
||||
}
|
||||
|
||||
// Update the zone's records at the provider:
|
||||
zoneCor, rep := generateZoneCorrections(zone, provider)
|
||||
zone.StoreCorrections(provider.Name, rep)
|
||||
zone.StoreCorrections(provider.Name, zoneCor)
|
||||
}
|
||||
|
||||
// Do the delegation corrections after the zones are updated.
|
||||
zone.StoreCorrections(zone.RegistrarInstance.Name, delegationCorrections)
|
||||
}
|
||||
|
||||
func whichProvidersToProcess(providers []*models.DNSProviderInstance, filter string) []*models.DNSProviderInstance {
|
||||
|
||||
if filter == "all" { // all
|
||||
return providers
|
||||
}
|
||||
|
||||
permitList := strings.Split(filter, ",")
|
||||
var picked []*models.DNSProviderInstance
|
||||
|
||||
// Just the default providers:
|
||||
if filter == "" {
|
||||
for _, provider := range providers {
|
||||
if provider.IsDefault {
|
||||
picked = append(picked, provider)
|
||||
}
|
||||
}
|
||||
return picked
|
||||
}
|
||||
|
||||
// Just the exact matches:
|
||||
for _, provider := range providers {
|
||||
for _, filterItem := range permitList {
|
||||
if provider.Name == filterItem {
|
||||
picked = append(picked, provider)
|
||||
}
|
||||
}
|
||||
}
|
||||
return picked
|
||||
}
|
||||
|
||||
func skipProvider(name string, providers []*models.DNSProviderInstance) bool {
|
||||
return !slices.ContainsFunc(providers, func(p *models.DNSProviderInstance) bool {
|
||||
return p.Name == name
|
||||
})
|
||||
}
|
||||
|
||||
func genReportItem(zname string, corrections []*models.Correction, pname string) *ReportItem {
|
||||
|
||||
// Only count the actions, not the messages.
|
||||
cnt := 0
|
||||
for _, cor := range corrections {
|
||||
if cor.F != nil {
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
|
||||
r := ReportItem{
|
||||
Domain: zname,
|
||||
Corrections: cnt,
|
||||
Provider: pname,
|
||||
}
|
||||
return &r
|
||||
}
|
||||
|
||||
func pprintOrRunCorrections(zoneName string, providerName string, corrections []*models.Correction, out printer.CLI, push bool, interactive bool, notifier notifications.Notifier, report string) bool {
|
||||
if len(corrections) == 0 {
|
||||
return false
|
||||
}
|
||||
var anyErrors bool
|
||||
for i, correction := range corrections {
|
||||
out.PrintCorrection(i, correction)
|
||||
var err error
|
||||
if push {
|
||||
if interactive && !out.PromptToRun() {
|
||||
continue
|
||||
}
|
||||
if correction.F != nil {
|
||||
err = correction.F()
|
||||
if err != nil {
|
||||
anyErrors = true
|
||||
}
|
||||
}
|
||||
out.EndCorrection(err)
|
||||
}
|
||||
notifier.Notify(zoneName, providerName, correction.Msg, err, !push)
|
||||
}
|
||||
|
||||
_ = report // File name to write report to.
|
||||
return anyErrors
|
||||
}
|
||||
|
||||
func writeReport(report string, reportItems []*ReportItem) error {
|
||||
// No filename? No report.
|
||||
if report == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(report, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
b, err := json.MarshalIndent(reportItems, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
z, err := zcache.zoneList(provider.Name, lister)
|
||||
if err != nil {
|
||||
return []*models.Correction{{Msg: fmt.Sprintf("zoneList failed for %q: %s", provider.Name, err)}}
|
||||
}
|
||||
zones := *z
|
||||
|
||||
aceZoneName, _ := idna.ToASCII(zoneName)
|
||||
if slices.Contains(zones, aceZoneName) {
|
||||
return nil // zone exists. Nothing to do.
|
||||
}
|
||||
|
||||
creator, ok := provider.Driver.(providers.ZoneCreator)
|
||||
if !ok {
|
||||
return []*models.Correction{{Msg: fmt.Sprintf("Zone %q does not exist. Can not create because %q does not implement ZoneCreator", aceZoneName, provider.Name)}}
|
||||
}
|
||||
|
||||
return []*models.Correction{{
|
||||
Msg: fmt.Sprintf("Create zone '%s' in the '%s' profile", aceZoneName, provider.Name),
|
||||
F: func() error { return creator.EnsureZoneExists(aceZoneName) },
|
||||
}}
|
||||
}
|
||||
|
||||
func generateZoneCorrections(zone *models.DomainConfig, provider *models.DNSProviderInstance) ([]*models.Correction, []*models.Correction) {
|
||||
reports, zoneCorrections, err := zonerecs.CorrectZoneRecords(provider.Driver, zone)
|
||||
if err != nil {
|
||||
return []*models.Correction{{Msg: fmt.Sprintf("Domain %q provider %s Error: %s", zone.Name, provider.Name, err)}}, nil
|
||||
}
|
||||
return zoneCorrections, reports
|
||||
}
|
||||
|
||||
func generateDelegationCorrections(zone *models.DomainConfig, providers []*models.DNSProviderInstance, _ *models.RegistrarInstance) []*models.Correction {
|
||||
//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("DtermineNS: zone %q; Error: %s", zone.Name, err))
|
||||
}
|
||||
zone.Nameservers = nsList
|
||||
nameservers.AddNSRecords(zone)
|
||||
|
||||
if len(zone.Nameservers) == 0 && zone.Metadata["no_ns"] != "true" {
|
||||
return []*models.Correction{{Msg: fmt.Sprintf("No nameservers declared for domain %q; skipping registrar. Add {no_ns:'true'} to force", zone.Name)}}
|
||||
}
|
||||
|
||||
corrections, err := zone.RegistrarInstance.Driver.GetRegistrarCorrections(zone)
|
||||
if err != nil {
|
||||
return msg(fmt.Sprintf("zone %q; Rprovider %q; Error: %s", zone.Name, zone.RegistrarInstance.Name, err))
|
||||
}
|
||||
return corrections
|
||||
}
|
||||
|
||||
func msg(s string) []*models.Correction {
|
||||
return []*models.Correction{{Msg: s}}
|
||||
}
|
||||
|
||||
// PInitializeProviders takes (fully processed) configuration and instantiates all providers and returns them.
|
||||
func PInitializeProviders(cfg *models.DNSConfig, providerConfigs map[string]map[string]string, notifyFlag bool) (notify notifications.Notifier, err error) {
|
||||
var notificationCfg map[string]string
|
||||
defer func() {
|
||||
notify = notifications.Init(notificationCfg)
|
||||
}()
|
||||
if notifyFlag {
|
||||
notificationCfg = providerConfigs["notifications"]
|
||||
}
|
||||
isNonDefault := map[string]bool{}
|
||||
for name, vals := range providerConfigs {
|
||||
// add "_exclude_from_defaults":"true" to a provider to exclude it from being run unless
|
||||
// -providers=all or -providers=name
|
||||
if vals["_exclude_from_defaults"] == "true" {
|
||||
isNonDefault[name] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Populate provider type ids based on values from creds.json:
|
||||
msgs, err := ppopulateProviderTypes(cfg, providerConfigs)
|
||||
if len(msgs) != 0 {
|
||||
fmt.Fprintln(os.Stderr, strings.Join(msgs, "\n"))
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
registrars := map[string]providers.Registrar{}
|
||||
dnsProviders := map[string]providers.DNSServiceProvider{}
|
||||
for _, d := range cfg.Domains {
|
||||
if registrars[d.RegistrarName] == nil {
|
||||
rCfg := cfg.RegistrarsByName[d.RegistrarName]
|
||||
r, err := providers.CreateRegistrar(rCfg.Type, providerConfigs[d.RegistrarName])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registrars[d.RegistrarName] = r
|
||||
}
|
||||
d.RegistrarInstance.Driver = registrars[d.RegistrarName]
|
||||
d.RegistrarInstance.IsDefault = !isNonDefault[d.RegistrarName]
|
||||
for _, pInst := range d.DNSProviderInstances {
|
||||
if dnsProviders[pInst.Name] == nil {
|
||||
dCfg := cfg.DNSProvidersByName[pInst.Name]
|
||||
prov, err := providers.CreateDNSProvider(dCfg.Type, providerConfigs[dCfg.Name], dCfg.Metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dnsProviders[pInst.Name] = prov
|
||||
}
|
||||
pInst.Driver = dnsProviders[pInst.Name]
|
||||
pInst.IsDefault = !isNonDefault[pInst.Name]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// pproviderTypeFieldName is the name of the field in creds.json that specifies the provider type id.
|
||||
const pproviderTypeFieldName = "TYPE"
|
||||
|
||||
// ppurl is the documentation URL to list in the warnings related to missing provider type ids.
|
||||
const purl = "https://docs.dnscontrol.org/commands/creds-json"
|
||||
|
||||
// ppopulateProviderTypes scans a DNSConfig for blank provider types and fills them in based on providerConfigs.
|
||||
// That is, if the provider type is "-" or "", we take that as an flag
|
||||
// that means this value should be replaced by the type found in creds.json.
|
||||
func ppopulateProviderTypes(cfg *models.DNSConfig, providerConfigs map[string]map[string]string) ([]string, error) {
|
||||
var msgs []string
|
||||
|
||||
for i := range cfg.Registrars {
|
||||
pType := cfg.Registrars[i].Type
|
||||
pName := cfg.Registrars[i].Name
|
||||
nt, warnMsg, err := prefineProviderType(pName, pType, providerConfigs[pName], "NewRegistrar")
|
||||
cfg.Registrars[i].Type = nt
|
||||
if warnMsg != "" {
|
||||
msgs = append(msgs, warnMsg)
|
||||
}
|
||||
if err != nil {
|
||||
return msgs, err
|
||||
}
|
||||
}
|
||||
|
||||
for i := range cfg.DNSProviders {
|
||||
pName := cfg.DNSProviders[i].Name
|
||||
pType := cfg.DNSProviders[i].Type
|
||||
nt, warnMsg, err := prefineProviderType(pName, pType, providerConfigs[pName], "NewDnsProvider")
|
||||
cfg.DNSProviders[i].Type = nt
|
||||
if warnMsg != "" {
|
||||
msgs = append(msgs, warnMsg)
|
||||
}
|
||||
if err != nil {
|
||||
return msgs, err
|
||||
}
|
||||
}
|
||||
|
||||
// Update these fields set by
|
||||
// commands/commands.go:preloadProviders().
|
||||
// This is probably a layering violation. That said, the
|
||||
// fundamental problem here is that we're storing the provider
|
||||
// instances by string name, not by a pointer to a struct. We
|
||||
// should clean that up someday.
|
||||
for _, domain := range cfg.Domains { // For each domain..
|
||||
for _, provider := range domain.DNSProviderInstances { // For each provider...
|
||||
pName := provider.ProviderBase.Name
|
||||
pType := provider.ProviderBase.ProviderType
|
||||
nt, warnMsg, err := prefineProviderType(pName, pType, providerConfigs[pName], "NewDnsProvider")
|
||||
provider.ProviderBase.ProviderType = nt
|
||||
if warnMsg != "" {
|
||||
msgs = append(msgs, warnMsg)
|
||||
}
|
||||
if err != nil {
|
||||
return msgs, err
|
||||
}
|
||||
}
|
||||
p := domain.RegistrarInstance
|
||||
pName := p.Name
|
||||
pType := p.ProviderType
|
||||
nt, warnMsg, err := prefineProviderType(pName, pType, providerConfigs[pName], "NewRegistrar")
|
||||
p.ProviderType = nt
|
||||
if warnMsg != "" {
|
||||
msgs = append(msgs, warnMsg)
|
||||
}
|
||||
if err != nil {
|
||||
return msgs, err
|
||||
}
|
||||
}
|
||||
|
||||
return puniqueStrings(msgs), nil
|
||||
}
|
||||
|
||||
// puniqueStrings takes an unsorted slice of strings and returns the
|
||||
// unique strings, in the order they first appeared in the list.
|
||||
func puniqueStrings(stringSlice []string) []string {
|
||||
keys := make(map[string]bool)
|
||||
list := []string{}
|
||||
for _, entry := range stringSlice {
|
||||
if _, ok := keys[entry]; !ok {
|
||||
keys[entry] = true
|
||||
list = append(list, entry)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
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 = "-"
|
||||
}
|
||||
|
||||
// Use cases:
|
||||
//
|
||||
// type credsType
|
||||
// ---- ---------
|
||||
// - 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 NAMEDOT ERROR "error mismatched: please fix as follows..."
|
||||
|
||||
// ERROR: Invalid.
|
||||
// WARNING: Required change to remain compatible with 4.0
|
||||
// INFO: Post-4.0 cleanups or other non-required changes.
|
||||
|
||||
if t != "-" {
|
||||
// Old-style, dnsconfig.js specifies the type explicitly.
|
||||
// This is supported but we suggest updates for future compatibility.
|
||||
|
||||
// If credFields is nil, that means there was no entry in creds.json:
|
||||
if credFields == nil {
|
||||
// Warn the user to update creds.json in preparation for 4.0:
|
||||
// In 4.0 this should be an error. We could default to a
|
||||
// provider such as "NONE" but I suspect it would be confusing
|
||||
// to users to see references to a provider name that they did
|
||||
// not specify.
|
||||
return t, fmt.Sprintf(`WARNING: For future compatibility, add this entry creds.json: %q: { %q: %q }, (See %s#missing)`,
|
||||
credEntryName, pproviderTypeFieldName, t,
|
||||
purl,
|
||||
), nil
|
||||
}
|
||||
|
||||
switch ct := credFields[pproviderTypeFieldName]; ct {
|
||||
case "":
|
||||
// Warn the user to update creds.json in preparation for 4.0:
|
||||
// In 4.0 this should be an error.
|
||||
return t, fmt.Sprintf(`WARNING: For future compatibility, update the %q entry in creds.json by adding: %q: %q, (See %s#missing)`,
|
||||
credEntryName,
|
||||
pproviderTypeFieldName, t,
|
||||
purl,
|
||||
), nil
|
||||
case "-":
|
||||
// This should never happen. The user is specifying "-" in a place that it shouldn't be used.
|
||||
return "-", "", fmt.Errorf(`ERROR: creds.json entry %q has invalid %q value %q (See %s#hyphen)`,
|
||||
credEntryName, pproviderTypeFieldName, ct,
|
||||
purl,
|
||||
)
|
||||
case t:
|
||||
// creds.json file is compatible with and dnsconfig.js can be updated.
|
||||
return ct, fmt.Sprintf(`INFO: In dnsconfig.js %s(%q, %q) can be simplified to %s(%q) (See %s#cleanup)`,
|
||||
source, credEntryName, t,
|
||||
source, credEntryName,
|
||||
purl,
|
||||
), nil
|
||||
default:
|
||||
// creds.json lists a TYPE but it doesn't match what's in dnsconfig.js!
|
||||
return t, "", fmt.Errorf(`ERROR: Mismatch found! creds.json entry %q has %q set to %q but dnsconfig.js specifies %s(%q, %q) (See %s#mismatch)`,
|
||||
credEntryName,
|
||||
pproviderTypeFieldName, ct,
|
||||
source, credEntryName, t,
|
||||
purl,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// t == "-"
|
||||
// New-style, dnsconfig.js does not specify the type (t == "") or a
|
||||
// command line tool accepted "-" as a positional argument for
|
||||
// backwards compatibility.
|
||||
|
||||
// If credFields is nil, that means there was no entry in creds.json:
|
||||
if credFields == nil {
|
||||
return "", "", fmt.Errorf(`ERROR: creds.json is missing an entry called %q. Suggestion: %q: { %q: %q }, (See %s#missing)`,
|
||||
credEntryName,
|
||||
credEntryName, pproviderTypeFieldName, "FILL_IN_PROVIDER_TYPE",
|
||||
purl,
|
||||
)
|
||||
}
|
||||
|
||||
// New-style, dnsconfig.js doesn't specifies the type. It will be
|
||||
// looked up in creds.json.
|
||||
switch ct := credFields[pproviderTypeFieldName]; ct {
|
||||
case "":
|
||||
return ct, "", fmt.Errorf(`ERROR: creds.json entry %q is missing: %q: %q, (See %s#fixcreds)`,
|
||||
credEntryName,
|
||||
pproviderTypeFieldName, "FILL_IN_PROVIDER_TYPE",
|
||||
purl,
|
||||
)
|
||||
case "-":
|
||||
// This should never happen. The user is confused and specified "-" in the wrong place!
|
||||
return "-", "", fmt.Errorf(`ERROR: creds.json entry %q has invalid %q value %q (See %s#hyphen)`,
|
||||
credEntryName,
|
||||
pproviderTypeFieldName, ct,
|
||||
purl,
|
||||
)
|
||||
default:
|
||||
// use the value in creds.json (this should be the normal case)
|
||||
return ct, "", nil
|
||||
}
|
||||
|
||||
}
|
|
@ -230,7 +230,7 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI, report
|
|||
|
||||
// Correct the registrar...
|
||||
|
||||
nsList, err := nameservers.DetermineNameserversForProviders(domain, providersWithExistingZone)
|
||||
nsList, err := nameservers.DetermineNameserversForProviders(domain, providersWithExistingZone, false)
|
||||
if err != nil {
|
||||
out.Errorf("ERROR: %s\n", err.Error())
|
||||
return
|
||||
|
|
27
commands/zonecache.go
Normal file
27
commands/zonecache.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package commands
|
||||
|
||||
import "github.com/StackExchange/dnscontrol/v4/providers"
|
||||
|
||||
func NewZoneCache() *zoneCache {
|
||||
return &zoneCache{}
|
||||
}
|
||||
|
||||
func (zc *zoneCache) zoneList(name string, lister providers.ZoneLister) (*[]string, error) {
|
||||
zc.Lock()
|
||||
defer zc.Unlock()
|
||||
|
||||
if zc.cache == nil {
|
||||
zc.cache = map[string]*[]string{}
|
||||
}
|
||||
|
||||
if v, ok := zc.cache[name]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
zones, err := lister.ListZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zc.cache[name] = &zones
|
||||
return &zones, nil
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
* [Examples](examples.md)
|
||||
* [Migrating zones to DNSControl](migrating.md)
|
||||
* [TypeScript autocomplete and type checking](typescript.md)
|
||||
* [Disabling Colors](colors.md)
|
||||
|
||||
## Language Reference
|
||||
|
||||
|
@ -150,10 +149,14 @@
|
|||
|
||||
## Commands
|
||||
|
||||
* [creds.json](creds-json.md)
|
||||
* [preview/push](preview-push.md)
|
||||
* [check-creds](check-creds.md)
|
||||
* [get-certs](get-certs.md)
|
||||
* [get-zones](get-zones.md)
|
||||
* [get-certs](get-certs.md)
|
||||
* [fmt](fmt.md)
|
||||
* [creds.json](creds-json.md)
|
||||
* [Global Flag](globalflags.md)
|
||||
* [Disabling Colors](colors.md)
|
||||
|
||||
## Advanced features
|
||||
|
||||
|
|
100
documentation/preview-push.md
Normal file
100
documentation/preview-push.md
Normal file
|
@ -0,0 +1,100 @@
|
|||
# preview/push
|
||||
|
||||
`preview` reads the dnsconfig.js file (or equivalent), determines what changes are to be made, and
|
||||
prints them. `push` is the same but executes the changes.
|
||||
|
||||
```shell
|
||||
NAME:
|
||||
dnscontrol preview - read live configuration and identify changes to be made, without applying them
|
||||
|
||||
USAGE:
|
||||
dnscontrol preview [command options] [arguments...]
|
||||
|
||||
CATEGORY:
|
||||
main
|
||||
|
||||
OPTIONS:
|
||||
--config value File containing dns config in javascript DSL (default: "dnsconfig.js")
|
||||
--dev Use helpers.js from disk instead of embedded copy (default: false)
|
||||
--variable value, -v value [ --variable value, -v value ] Add variable that is passed to JS
|
||||
--ir value Read IR (json) directly from this file. Do not process DSL at all
|
||||
--creds value Provider credentials JSON file (or !program to execute program that outputs json) (default: "creds.json")
|
||||
--providers value Providers to enable (comma separated list); default is all. Can exclude individual providers from default by adding '"_exclude_from_defaults": "true"' to the credentials file for a provider
|
||||
--domains value Comma separated list of domain names to include
|
||||
--notify set to true to send notifications to configured destinations (default: false)
|
||||
--expect-no-changes set to true for non-zero return code if there are changes (default: false)
|
||||
--no-populate Use this flag to not auto-create non-existing zones at the provider (default: false)
|
||||
--full Add headings, providers names, notifications of no changes, etc (default: false)
|
||||
--bindserial value Force BIND serial numbers to this value (for reproducibility) (default: 0)
|
||||
--report value (push) Generate a JSON-formatted report of the number of changes made.
|
||||
--help, -h show help
|
||||
```
|
||||
|
||||
`--config name` -- Specifies the name of the main configuration file, normally
|
||||
`dnsconfig.js`.
|
||||
|
||||
`--dev` -- Developer mode. Normally `helpers.js` is embedded in the dnscontrol
|
||||
executable. With this flag, the local file `helpers.js` is read instead.
|
||||
|
||||
`--v foo=bar` -- Sets the variable `foo` to the value `bar` prior to
|
||||
interpreting the configuration file. Multiple `-v` options can be used.
|
||||
|
||||
`--creds name` -- Specifies the name of the credentials file, normally
|
||||
`creds.json`. Typically the file is read. If the executable bit is set, the
|
||||
file is executed and the output is used as the configuration. (That feature may
|
||||
or may not work on Windows.) If the filename begins with a `|` (for example:
|
||||
`|runme.sh`) the `|` is removed and the remaining string is used as the name of
|
||||
the program.
|
||||
|
||||
`--providers name,name2` -- Specifies a comma-separated list of providers to
|
||||
enable. The default is all providers. A provider can opt out of being in the
|
||||
default list by `"_exclude_from_defaults": "true"` to the credentials entry for
|
||||
that provider. In that case, the provider will only be activated if it is
|
||||
included in `--providers`.
|
||||
|
||||
`--domains value` -- Specifies a comma-separated list of domains to include.
|
||||
Typically all domains are included in `preview`/`push`. Wildcards are not
|
||||
permitted except `*` at the start of the entry. For example, `--domains
|
||||
example.com,*.in-addr.arpa` would include `example.com` plus all reverse lookup
|
||||
domains.
|
||||
|
||||
`--notify` -- Enables sending notifications to the destinations configured in
|
||||
`creds.json`.
|
||||
|
||||
`--expect-no-changes` -- If set, a non-zero exit code is returned if there are
|
||||
changes. Normally DNSControl sets the exit code based on whether or not there
|
||||
were protocol errors or other reasons the program can not continue. With this
|
||||
flag set, the exit code indicates if any changes were required. This is
|
||||
typically used with `preview` to allow scripts to determine if changes would
|
||||
happen if `push` was used. For example, one might want to run `dnscontrol
|
||||
preview --expect-no-changes` daily to determine if changes have been made to
|
||||
a domain outside of DNSControl.
|
||||
|
||||
`--no-populate` -- Do not auto-create non-existing zones at the provider.
|
||||
Normally non-existent zones are automatically created at a provider (unless the
|
||||
provider does not implement zone creation). This flag disables that feature.
|
||||
|
||||
`--full` -- Add headings, providers names, notifications of no changes, etc. to
|
||||
the output. Normally the output of `preview`/`push` is extremely brief. This
|
||||
makes the output more verbose. Useful for debugging.
|
||||
|
||||
`--bindserial value` -- Force BIND serial numbers to this value. Normally the
|
||||
BIND provider generates SOA serial numbers automatically. This flag forces the
|
||||
serial number generator to output the value specified for all domains. This is
|
||||
generally used for reproducibility in testing pipelines.
|
||||
|
||||
`--report name` -- (`push` only!) Generate a machine-parseable report of
|
||||
performed corrections in the file named `name`. If no name is specified, no
|
||||
report is generated.
|
||||
|
||||
## Experimental
|
||||
|
||||
The `ppreview`/`ppush` subcommands are a preview of a future feature where zone
|
||||
data is gathered concurrently. The commands will go away when
|
||||
they replace the existing `preview`/`push` commands.
|
||||
|
||||
`--cmode value` -- Concurrency mode. Specifies what kind of providers should be run concurrently. This flag onl
|
||||
|
||||
* `default` -- Providers are run sequentially or concurrently depending on whether the provider is marked as having been tested to run concurrently.
|
||||
* `none` -- All providers are run sequentially. This is the safest mode. It can be used if a concurrency bug is discovered.
|
||||
* `all` -- This is unsafe. It runs all providers concurrently, even the ones that have not be validated to run concurrently. It is generally only used for demonstrating bugs.
|
|
@ -17,13 +17,13 @@ If a feature is definitively not supported for whatever reason, we would also li
|
|||
| [`AKAMAIEDGEDNS`](providers/akamaiedgedns.md) | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`AUTODNS`](providers/autodns.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❔ | ❔ | ❔ | ❌ | ❔ | ✅ | ❌ | ❌ | ❌ | ❔ | ❌ | ❌ | ✅ |
|
||||
| [`AXFRDDNS`](providers/axfrddns.md) | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ❌ | ❌ |
|
||||
| [`AZURE_DNS`](providers/azure_dns.md) | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❔ | ❌ | ❌ | ✅ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`AZURE_DNS`](providers/azure_dns.md) | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❔ | ❌ | ❌ | ✅ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`AZURE_PRIVATE_DNS`](providers/azure_private_dns.md) | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❔ | ❌ | ❌ | ✅ | ❔ | ✅ | ❌ | ❌ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`BIND`](providers/bind.md) | ✅ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [`BUNNY_DNS`](providers/bunny_dns.md) | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||
| [`CLOUDFLAREAPI`](providers/cloudflareapi.md) | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❔ | ❌ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ❌ | ✅ | ✅ |
|
||||
| [`CLOUDFLAREAPI`](providers/cloudflareapi.md) | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❔ | ❌ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ❌ | ✅ | ✅ |
|
||||
| [`CLOUDNS`](providers/cloudns.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ❔ | ✅ | ✅ |
|
||||
| [`CSCGLOBAL`](providers/cscglobal.md) | ✅ | ✅ | ✅ | ❌ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ |
|
||||
| [`CSCGLOBAL`](providers/cscglobal.md) | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ✅ |
|
||||
| [`DESEC`](providers/desec.md) | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ |
|
||||
| [`DIGITALOCEAN`](providers/digitalocean.md) | ❌ | ✅ | ❌ | ❌ | ❔ | ✅ | ❔ | ❌ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ✅ | ✅ |
|
||||
| [`DNSIMPLE`](providers/dnsimple.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❔ | ✅ | ✅ | ❌ | ❌ | ❔ | ❌ | ❌ | ✅ |
|
||||
|
@ -34,7 +34,7 @@ If a feature is definitively not supported for whatever reason, we would also li
|
|||
| [`EASYNAME`](providers/easyname.md) | ❌ | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ❔ |
|
||||
| [`EXOSCALE`](providers/exoscale.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ❌ | ❔ | ❔ | ❌ | ❌ | ❔ |
|
||||
| [`GANDI_V5`](providers/gandi_v5.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ❔ | ❔ | ❌ | ✅ |
|
||||
| [`GCLOUD`](providers/gcloud.md) | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`GCLOUD`](providers/gcloud.md) | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`GCORE`](providers/gcore.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❔ | ✅ | ❌ | ❌ | ❌ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`HEDNS`](providers/hedns.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`HETZNER`](providers/hetzner.md) | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ |
|
||||
|
@ -59,7 +59,7 @@ If a feature is definitively not supported for whatever reason, we would also li
|
|||
| [`PORKBUN`](providers/porkbun.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ❔ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ |
|
||||
| [`POWERDNS`](providers/powerdns.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`REALTIMEREGISTER`](providers/realtimeregister.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||
| [`ROUTE53`](providers/route53.md) | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`ROUTE53`](providers/route53.md) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ |
|
||||
| [`RWTH`](providers/rwth.md) | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❔ | ❌ | ❌ | ✅ | ❔ | ✅ | ✅ | ❌ | ❔ | ❔ | ❌ | ❌ | ✅ |
|
||||
| [`SOFTLAYER`](providers/softlayer.md) | ❌ | ✅ | ❌ | ❌ | ❔ | ❔ | ❔ | ❌ | ❔ | ❔ | ❔ | ✅ | ❔ | ❔ | ❔ | ❔ | ❔ | ❌ | ❔ |
|
||||
| [`TRANSIP`](providers/transip.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ❔ | ❔ | ✅ | ✅ | ✅ | ❌ | ❔ | ❔ | ❌ | ✅ |
|
||||
|
|
50
go.mod
50
go.mod
|
@ -1,8 +1,6 @@
|
|||
module github.com/StackExchange/dnscontrol/v4
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.1
|
||||
go 1.22.1
|
||||
|
||||
retract v4.8.0
|
||||
|
||||
|
@ -20,16 +18,16 @@ require (
|
|||
github.com/TomOnTime/utfutil v0.0.0-20230223141146-125e65197b36
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/aws/aws-sdk-go-v2 v1.25.3
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.7
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.7
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.2
|
||||
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.2
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.9
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.9
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.3
|
||||
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.3
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6
|
||||
github.com/billputer/go-namecheap v0.0.0-20210108011502-994a912fb7f9
|
||||
github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v3 v3.5.6
|
||||
github.com/cloudflare/cloudflare-go v0.89.0
|
||||
github.com/digitalocean/godo v1.109.0
|
||||
github.com/cloudflare/cloudflare-go v0.91.0
|
||||
github.com/digitalocean/godo v1.110.0
|
||||
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c
|
||||
github.com/dnsimple/dnsimple-go v1.5.1
|
||||
github.com/exoscale/egoscale v0.90.2
|
||||
|
@ -37,7 +35,7 @@ require (
|
|||
github.com/go-gandi/go-gandi v0.7.0
|
||||
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe
|
||||
github.com/gopherjs/jquery v0.0.0-20191017083323-73f4c7416038
|
||||
github.com/hashicorp/vault/api v1.12.0
|
||||
github.com/hashicorp/vault/api v1.12.2
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/mittwald/go-powerdns v0.6.2
|
||||
|
@ -58,7 +56,7 @@ require (
|
|||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/oauth2 v0.18.0
|
||||
google.golang.org/api v0.169.0
|
||||
google.golang.org/api v0.171.0
|
||||
gopkg.in/ns1/ns1-go.v2 v2.7.11
|
||||
)
|
||||
|
||||
|
@ -73,7 +71,7 @@ require (
|
|||
github.com/kylelemons/godebug v1.1.0
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/vultr/govultr/v2 v2.17.2
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81
|
||||
golang.org/x/text v0.14.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
@ -85,15 +83,15 @@ require (
|
|||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect
|
||||
github.com/aws/smithy-go v1.20.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
|
@ -115,7 +113,7 @@ require (
|
|||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
|
@ -128,6 +126,7 @@ require (
|
|||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
|
@ -140,6 +139,7 @@ require (
|
|||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
|
@ -148,14 +148,14 @@ require (
|
|||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
golang.org/x/mod v0.15.0 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 // indirect
|
||||
google.golang.org/grpc v1.62.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
|
|
105
go.sum
105
go.sum
|
@ -39,34 +39,34 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
|
|||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.25.3 h1:xYiLpZTQs1mzvz5PaI6uR0Wh57ippuEthxS4iK5v0n0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.7 h1:JSfb5nOQF01iOgxFI5OIKWwDiEXWTyTgg1Mm1mHi0A4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.7/go.mod h1:PH0/cNpoMO+B04qET699o5W92Ca79fVtbUnvMIZro4I=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.7 h1:WJd+ubWKoBeRh7A5iNMnxEOs982SyVKOJD+K8HIezu4=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.7/go.mod h1:UQi7LMR0Vhvs+44w5ec8Q+VS+cd10cjwgHwiVkE0YGU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 h1:p+y7FvkK2dxS+FEwRIDHDe//ZX+jDhP8HHE50ppj4iI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3/go.mod h1:/fYB+FZbDlwlAiynK9KDXlzZl3ANI9JkD0Uhz5FjNT4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 h1:ifbIbHZyGl1alsAhPIYsHOg5MuApgqOvVeI8wIugXfs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3/go.mod h1:oQZXg3c6SNeY6OZrDY+xHcF4VGIEoNotX2B4PrDeoJI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 h1:Qvodo9gHG9F3E8SfYOspPeBt0bjSbsevK8WhRAUHcoY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3/go.mod h1:vCKrdLXtybdf/uQd/YfVR2r5pcbNuEYKzMQpcxmeSJw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA=
|
||||
github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.9 h1:gRx/NwpNEFSk+yQlgmk1bmxxvQ5TyJ76CWXs9XScTqg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.9/go.mod h1:dK1FQfpwpql83kbD873E9vz4FyAxuJtR22wzoXn3qq0=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMNQVNtNdUqf6cItao=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 h1:af5YzcLf80tv4Em4jWVD75lpnOHSBkPUZxZfGkrI3HI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 h1:0ScVK/4qZ8CIW0k8jOeFVsyS/sAiXpYxRBLolMkuLQM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4/go.mod h1:84KyjNZdHC6QZW08nfHI6yZgPd+qRgaWcYsyLUo3QY8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 h1:sHmMWWX5E7guWEFQ9SVo6A3S4xpPrWnd77a6y4WM6PU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4/go.mod h1:WjpDrhWisWOIoS9n3nk67A3Ll1vfULJ9Kq6h29HTD48=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 h1:K/NXvIftOlX+oGgWGIa3jDyYLDNsdVhsjHmsBH2GLAQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5/go.mod h1:cl9HGLV66EnCmMNzq4sYOti+/xo8w34CsgzVtm2GgsY=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.2 h1:YXQQJm3KnxabBHGNU8iC0GSvKRLtUSNUfP2R7L+Z/Tg=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.2/go.mod h1:ORinaAeDvAI7L7zPyE2RmG0RpwHKZDaQ7ALO8/dXFtY=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.2 h1:TypWfzHKes0zADvTyJEwGsb0BAscUE8Ty0xs/jQM4Dk=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.2/go.mod h1:jVbk98+jKo/JiX+qt028oGR6yApccx4ij5FaFUjiIAg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 h1:XOPfar83RIRPEzfihnp+U6udOveKZJvPQ76SKWrLRHc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.2/go.mod h1:Vv9Xyk1KMHXrR3vNQe8W5LMFdTjSeWk0gBZBzvf3Qa0=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 h1:pi0Skl6mNl2w8qWZXcdOyg197Zsf4G97U7Sso9JXGZE=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2/go.mod h1:JYzLoEVeLXk+L4tn1+rrkfhkxl6mLDEVaDSvGq9og90=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 h1:Ppup1nVNAOWbBOrcoOxaxPeEnSFB2RnnQdguhXpmeQk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4/go.mod h1:+K1rNPVyGxkRuv9NNiaZ4YhBFuyw2MMA9SlIJ1Zlpz8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.3 h1:wr5gulbwbb8PSRMWjCROoP0TIMccpF8x5A7hEk2SjpA=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.3/go.mod h1:/Gyl9xjGcjIVe80ar75YlmA8m6oFh0A4XfLciBmdS8s=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.3 h1:iuBYHWv0+2pF2qbM+UmnSwvcdOknXRi4yE9KBHhAItQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53domains v1.23.3/go.mod h1:Ijqatnvuyx5IE/FmFJWJyWTcUY5XrlXgc6G7z1Fqk6o=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 h1:mnbuWHOcM70/OFUlZZ5rcdfA8PflGXXiefU/O+1S3+8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.3/go.mod h1:5HFu51Elk+4oRBZVxmHrSds5jFXmFj8C3w7DVF2gnrs=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 h1:uLq0BKatTmDzWa/Nu4WO0M1AaQDaPpwTKAeByEc6WFM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3/go.mod h1:b+qdhjnxj8GSR6t5YfphOffeoQSQ1KmpoVVuBn+PWxs=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 h1:J/PpTf/hllOjx8Xu9DMflff3FajfLxqM5+tepvVXmxg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.5/go.mod h1:0ih0Z83YDH/QeQ6Ori2yGE2XvWYv/Xm+cZc01LC6oK0=
|
||||
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
|
||||
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
|
||||
|
@ -87,8 +87,8 @@ github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v3 v3.5.6/go.mod
|
|||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cloudflare-go v0.89.0 h1:3zoVntC8xmUR/weFEcNE1RizdW4LRZdQnJ/AN8DDa1U=
|
||||
github.com/cloudflare/cloudflare-go v0.89.0/go.mod h1:eyuehb1i6BNRc+ZwaTZAiRHeE+4jbKvHAns19oGeakg=
|
||||
github.com/cloudflare/cloudflare-go v0.91.0 h1:L7IR+86qrZuEMSjGFg4cwRwtHqC8uCPmMUkP7BD4CPw=
|
||||
github.com/cloudflare/cloudflare-go v0.91.0/go.mod h1:nUqvBUUDRxNzsDSQjbqUNWHEIYAoUlgRmcAzMKlFdKs=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
|
@ -101,8 +101,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn
|
|||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
|
||||
github.com/deepmap/oapi-codegen v1.9.1 h1:yHmEnA7jSTUMQgV+uN02WpZtwHnz2CBW3mZRIxr1vtI=
|
||||
github.com/deepmap/oapi-codegen v1.9.1/go.mod h1:PLqNAhdedP8ttRpBBkzLKU3bp+Fpy+tTgeAMlztR2cw=
|
||||
github.com/digitalocean/godo v1.109.0 h1:4W97RJLJSUQ3veRZDNbp1Ol3Rbn6Lmt9bKGvfqYI5SU=
|
||||
github.com/digitalocean/godo v1.109.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs=
|
||||
github.com/digitalocean/godo v1.110.0 h1:EY+rewWCYrUNOPbk9wI2Ytf0TBSRTJcZ6BINCb5dfmQ=
|
||||
github.com/digitalocean/godo v1.110.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs=
|
||||
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c h1:+Zo5Ca9GH0RoeVZQKzFJcTLoAixx5s5Gq3pTIS+n354=
|
||||
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c/go.mod h1:HJGU9ULdREjOcVGZVPB5s6zYmHi1RxzT71l2wQyLmnE=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
|
@ -206,8 +206,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA=
|
||||
github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc=
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=
|
||||
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||
|
@ -240,8 +240,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S
|
|||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/vault/api v1.12.0 h1:meCpJSesvzQyao8FCOgk2fGdoADAnbDu2WPJN1lDLJ4=
|
||||
github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck=
|
||||
github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGbQb/rE=
|
||||
github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE=
|
||||
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
|
||||
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
|
@ -261,8 +261,9 @@ github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZ
|
|||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
|
@ -344,8 +345,8 @@ github.com/robertkrimen/otto v0.3.0 h1:5RI+8860NSxvXywDY9ddF5HcPw0puRsd8EgbXV0oq
|
|||
github.com/robertkrimen/otto v0.3.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
|
@ -358,8 +359,9 @@ github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
|
|||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
||||
|
@ -426,8 +428,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
|||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc=
|
||||
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
|
@ -435,8 +437,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -526,14 +528,14 @@ golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4X
|
|||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY=
|
||||
google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg=
|
||||
google.golang.org/api v0.171.0 h1:w174hnBPqut76FzW5Qaupt7zY8Kql6fiVjgys4f58sU=
|
||||
google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
|
@ -541,19 +543,18 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ
|
|||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU=
|
||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 h1:Xs9lu+tLXxLIfuci70nG4cpwaRC+mRQPUL7LoIeDJC4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
|
|
@ -3,6 +3,7 @@ package models
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/qdm12/reprint"
|
||||
"golang.org/x/net/idna"
|
||||
|
@ -23,9 +24,10 @@ type DomainConfig struct {
|
|||
|
||||
// Metadata[DomainUniqueName] // .Name + "!" + .Tag
|
||||
// Metadata[DomainTag] // split horizon tag
|
||||
Metadata map[string]string `json:"meta,omitempty"`
|
||||
Records Records `json:"records"`
|
||||
Nameservers []*Nameserver `json:"nameservers,omitempty"`
|
||||
Metadata map[string]string `json:"meta,omitempty"`
|
||||
Records Records `json:"records"`
|
||||
Nameservers []*Nameserver `json:"nameservers,omitempty"`
|
||||
NameserversMutex sync.Mutex `json:"-"`
|
||||
|
||||
EnsureAbsent Records `json:"recordsabsent,omitempty"` // ENSURE_ABSENT
|
||||
KeepUnknown bool `json:"keepunknown,omitempty"` // NO_PURGE
|
||||
|
@ -42,6 +44,12 @@ type DomainConfig struct {
|
|||
// 2. Final driver instances are loaded after we load credentials. Any actual provider interaction requires that.
|
||||
RegistrarInstance *RegistrarInstance `json:"-"`
|
||||
DNSProviderInstances []*DNSProviderInstance `json:"-"`
|
||||
|
||||
// Pending work to do for each provider. Provider may be a registrar or DSP.
|
||||
// pendingCorrectionsMutex sync.Mutex
|
||||
pendingCorrections map[string]([]*Correction) // Work to be done for each provider
|
||||
pendingCorrectionsOrder []string // Call the providers in this order
|
||||
pendingCorrectionsMutex sync.Mutex // Protect pendingCorrections*
|
||||
}
|
||||
|
||||
// GetSplitHorizonNames returns the domain's name, uniquename, and tag.
|
||||
|
@ -141,3 +149,38 @@ func (dc *DomainConfig) Punycode() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dc *DomainConfig) StoreCorrections(providerName string, corrections []*Correction) {
|
||||
dc.pendingCorrectionsMutex.Lock()
|
||||
defer dc.pendingCorrectionsMutex.Unlock()
|
||||
|
||||
if dc.pendingCorrections == nil {
|
||||
// First time storing anything.
|
||||
dc.pendingCorrections = make(map[string]([]*Correction))
|
||||
dc.pendingCorrections[providerName] = corrections
|
||||
dc.pendingCorrectionsOrder = []string{providerName}
|
||||
} else if c, ok := dc.pendingCorrections[providerName]; !ok {
|
||||
// First time key used
|
||||
dc.pendingCorrections[providerName] = corrections
|
||||
dc.pendingCorrectionsOrder = []string{providerName}
|
||||
} else {
|
||||
// Add to existing.
|
||||
dc.pendingCorrections[providerName] = append(c, corrections...)
|
||||
dc.pendingCorrectionsOrder = append(dc.pendingCorrectionsOrder, providerName)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (dc *DomainConfig) GetCorrections(providerName string) []*Correction {
|
||||
dc.pendingCorrectionsMutex.Lock()
|
||||
defer dc.pendingCorrectionsMutex.Unlock()
|
||||
|
||||
if dc.pendingCorrections == nil {
|
||||
// First time storing anything.
|
||||
return nil
|
||||
}
|
||||
if c, ok := dc.pendingCorrections[providerName]; ok {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,24 +14,26 @@ import (
|
|||
// 1. All explicitly defined NAMESERVER records will be used.
|
||||
// 2. Each DSP declares how many nameservers to use. Default is all. 0 indicates to use none.
|
||||
func DetermineNameservers(dc *models.DomainConfig) ([]*models.Nameserver, error) {
|
||||
return DetermineNameserversForProviders(dc, dc.DNSProviderInstances)
|
||||
return DetermineNameserversForProviders(dc, dc.DNSProviderInstances, false)
|
||||
}
|
||||
|
||||
// DetermineNameserversForProviders is like DetermineNameservers, for a subset of providers.
|
||||
func DetermineNameserversForProviders(dc *models.DomainConfig, providers []*models.DNSProviderInstance) ([]*models.Nameserver, error) {
|
||||
// always take explicit
|
||||
func DetermineNameserversForProviders(dc *models.DomainConfig, providers []*models.DNSProviderInstance, silent bool) ([]*models.Nameserver, error) {
|
||||
// start with the nameservers that have been explicitly added:
|
||||
ns := dc.Nameservers
|
||||
|
||||
for _, dnsProvider := range providers {
|
||||
n := dnsProvider.NumberOfNameservers
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
if !printer.SkinnyReport {
|
||||
if !silent && !printer.SkinnyReport {
|
||||
fmt.Printf("----- Getting nameservers from: %s\n", dnsProvider.Name)
|
||||
}
|
||||
|
||||
nss, err := dnsProvider.Driver.GetNameservers(dc.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error while getting Nameservers for zone=%q with provider=%q: %w", dc.Name, dnsProvider.Name, err)
|
||||
}
|
||||
// Clean up the nameservers due to
|
||||
// https://github.com/StackExchange/dnscontrol/issues/491
|
||||
|
|
|
@ -31,6 +31,7 @@ type Printer interface {
|
|||
Println(lines ...string)
|
||||
Warnf(fmt string, args ...interface{})
|
||||
Errorf(fmt string, args ...interface{})
|
||||
PrintfIf(print bool, fmt string, args ...interface{})
|
||||
}
|
||||
|
||||
// Debugf is called to print/format debug information.
|
||||
|
@ -58,6 +59,11 @@ func Warnf(fmt string, args ...interface{}) {
|
|||
// DefaultPrinter.Errorf(fmt, args...)
|
||||
// }
|
||||
|
||||
// PrintfIf is called to optionally print something.
|
||||
func PrintfIf(print bool, fmt string, args ...interface{}) {
|
||||
DefaultPrinter.PrintfIf(print, fmt, args...)
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultPrinter is the default Printer, used by Debugf, Printf, and Warnf.
|
||||
DefaultPrinter = &ConsolePrinter{
|
||||
|
@ -190,3 +196,10 @@ func (c ConsolePrinter) Warnf(format string, args ...interface{}) {
|
|||
func (c ConsolePrinter) Errorf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(c.Writer, "ERROR: "+format, args...)
|
||||
}
|
||||
|
||||
// Errorf is called to optionally print/format a message.
|
||||
func (c ConsolePrinter) PrintfIf(print bool, format string, args ...interface{}) {
|
||||
if print {
|
||||
fmt.Fprintf(c.Writer, format, args...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,15 +23,13 @@ type azurednsProvider struct {
|
|||
zones map[string]*adns.Zone
|
||||
resourceGroup *string
|
||||
subscriptionID *string
|
||||
rawRecords map[string][]*adns.RecordSet
|
||||
zoneName map[string]string
|
||||
}
|
||||
|
||||
func newAzureDNSDsp(conf map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||
return newAzureDNS(conf, metadata)
|
||||
}
|
||||
|
||||
func newAzureDNS(m map[string]string, metadata json.RawMessage) (*azurednsProvider, error) {
|
||||
func newAzureDNS(m map[string]string, _ json.RawMessage) (*azurednsProvider, error) {
|
||||
subID, rg := m["SubscriptionID"], m["ResourceGroup"]
|
||||
clientID, clientSecret, tenantID := m["ClientID"], m["ClientSecret"], m["TenantID"]
|
||||
credential, authErr := aauth.NewClientSecretCredential(tenantID, clientID, clientSecret, nil)
|
||||
|
@ -52,8 +50,6 @@ func newAzureDNS(m map[string]string, metadata json.RawMessage) (*azurednsProvid
|
|||
recordsClient: recordsClient,
|
||||
resourceGroup: to.StringPtr(rg),
|
||||
subscriptionID: to.StringPtr(subID),
|
||||
rawRecords: map[string][]*adns.RecordSet{},
|
||||
zoneName: map[string]string{},
|
||||
}
|
||||
err := api.getZones()
|
||||
if err != nil {
|
||||
|
@ -66,7 +62,7 @@ var features = providers.DocumentationNotes{
|
|||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanConcur: providers.Cannot(),
|
||||
providers.CanConcur: providers.Can(),
|
||||
providers.CanUseAlias: providers.Cannot("Azure DNS does not provide a generic ALIAS functionality. Use AZURE_ALIAS instead."),
|
||||
providers.CanUseAzureAlias: providers.Can(),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
|
@ -187,9 +183,6 @@ func (a *azurednsProvider) getExistingRecords(domain string) (models.Records, []
|
|||
existingRecords = append(existingRecords, nativeToRecords(set, zoneName)...)
|
||||
}
|
||||
|
||||
a.rawRecords[domain] = rawRecords
|
||||
a.zoneName[domain] = zoneName
|
||||
|
||||
return existingRecords, rawRecords, zoneName, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
package providers
|
||||
|
||||
import "log"
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
// Capability is a bitmasked set of "features" that a provider supports. Only use constants from this package.
|
||||
type Capability uint32
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/idna"
|
||||
|
||||
|
@ -43,7 +44,7 @@ var features = providers.DocumentationNotes{
|
|||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanConcur: providers.Cannot(),
|
||||
providers.CanConcur: providers.Can(),
|
||||
providers.CanUseAlias: providers.Can("CF automatically flattens CNAME records into A records dynamically"),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
providers.CanUseDSForChildren: providers.Can(),
|
||||
|
@ -79,6 +80,7 @@ type cloudflareProvider struct {
|
|||
manageWorkers bool
|
||||
accountID string
|
||||
cfClient *cloudflare.API
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// TODO(dlemenkov): remove this function after deleting all commented code referecing it
|
||||
|
@ -94,27 +96,29 @@ type cloudflareProvider struct {
|
|||
|
||||
// GetNameservers returns the nameservers for a domain.
|
||||
func (c *cloudflareProvider) GetNameservers(domain string) ([]*models.Nameserver, error) {
|
||||
if c.domainIndex == nil {
|
||||
if err := c.fetchDomainList(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.cacheDomainList(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Lock()
|
||||
ns, ok := c.nameservers[domain]
|
||||
c.Unlock()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("nameservers for %s not found in cloudflare account", domain)
|
||||
return nil, fmt.Errorf("nameservers for %s not found in cloudflare cache(%q)", domain, c.accountID)
|
||||
}
|
||||
return models.ToNameservers(ns)
|
||||
}
|
||||
|
||||
// ListZones returns a list of the DNS zones.
|
||||
func (c *cloudflareProvider) ListZones() ([]string, error) {
|
||||
if err := c.fetchDomainList(); err != nil {
|
||||
if err := c.cacheDomainList(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Lock()
|
||||
zones := make([]string, 0, len(c.domainIndex))
|
||||
for d := range c.domainIndex {
|
||||
zones = append(zones, d)
|
||||
}
|
||||
c.Unlock()
|
||||
return zones, nil
|
||||
}
|
||||
|
||||
|
@ -178,12 +182,12 @@ func (c *cloudflareProvider) GetZoneRecords(domain string, meta map[string]strin
|
|||
}
|
||||
|
||||
func (c *cloudflareProvider) getDomainID(name string) (string, error) {
|
||||
if c.domainIndex == nil {
|
||||
if err := c.fetchDomainList(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := c.cacheDomainList(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
c.Lock()
|
||||
id, ok := c.domainIndex[name]
|
||||
c.Unlock()
|
||||
if !ok {
|
||||
return "", fmt.Errorf("'%s' not a zone in cloudflare account", name)
|
||||
}
|
||||
|
@ -196,14 +200,6 @@ func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
|
|||
if err := c.preprocessConfig(dc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// for i := len(records) - 1; i >= 0; i-- {
|
||||
// rec := records[i]
|
||||
// // Delete ignore labels
|
||||
// if labelMatches(dnsutil.TrimDomainName(rec.Original.(cloudflare.DNSRecord).Name, dc.Name), c.ignoredLabels) {
|
||||
// printer.Debugf("ignored_label: %s\n", rec.Original.(cloudflare.DNSRecord).Name)
|
||||
// records = append(records[:i], records[i+1:]...)
|
||||
// }
|
||||
// }
|
||||
|
||||
checkNSModifications(dc)
|
||||
|
||||
|
@ -222,9 +218,6 @@ func (c *cloudflareProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
|
|||
if rec.Metadata[metaProxy] != "off" {
|
||||
rec.TTL = 1
|
||||
}
|
||||
// if labelMatches(rec.GetLabel(), c.ignoredLabels) {
|
||||
// log.Fatalf("FATAL: dnsconfig contains label that matches ignored_labels: %#v is in %v)\n", rec.GetLabel(), c.ignoredLabels)
|
||||
// }
|
||||
}
|
||||
|
||||
checkNSModifications(dc)
|
||||
|
@ -815,11 +808,14 @@ func getProxyMetadata(r *models.RecordConfig) map[string]string {
|
|||
|
||||
// EnsureZoneExists creates a zone if it does not exist
|
||||
func (c *cloudflareProvider) EnsureZoneExists(domain string) error {
|
||||
if c.domainIndex == nil {
|
||||
if err := c.fetchDomainList(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.cacheDomainList(); err != nil {
|
||||
return err
|
||||
}
|
||||
// if c.domainIndex == nil {
|
||||
// if err := c.fetchDomainList(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
if _, ok := c.domainIndex[domain]; ok {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -13,7 +13,10 @@ import (
|
|||
)
|
||||
|
||||
// get list of domains for account. Cache so the ids can be looked up from domain name
|
||||
func (c *cloudflareProvider) fetchDomainList() error {
|
||||
func (c *cloudflareProvider) cacheDomainList() error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.domainIndex = map[string]string{}
|
||||
c.nameservers = map[string][]string{}
|
||||
zones, err := c.cfClient.ListZones(context.Background())
|
||||
|
|
|
@ -28,7 +28,7 @@ var features = providers.DocumentationNotes{
|
|||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanConcur: providers.Cannot(),
|
||||
providers.CanConcur: providers.Can(),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
providers.CanUseSRV: providers.Can(),
|
||||
providers.DocOfficiallySupported: providers.Can(),
|
||||
|
|
|
@ -26,7 +26,7 @@ var features = providers.DocumentationNotes{
|
|||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanConcur: providers.Cannot(),
|
||||
providers.CanConcur: providers.Can(),
|
||||
providers.CanUseAlias: providers.Can(),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
providers.CanUseDSForChildren: providers.Can(),
|
||||
|
|
|
@ -171,10 +171,16 @@ func (n None) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correctio
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
var featuresNone = DocumentationNotes{
|
||||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
CanConcur: Can(),
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterRegistrarType("NONE", func(map[string]string) (Registrar, error) {
|
||||
return None{}, nil
|
||||
})
|
||||
}, featuresNone)
|
||||
}
|
||||
|
||||
// CustomRType stores an rtype that is only valid for this DSP.
|
||||
|
|
|
@ -27,12 +27,11 @@ import (
|
|||
)
|
||||
|
||||
type route53Provider struct {
|
||||
client *r53.Client
|
||||
registrar *r53d.Client
|
||||
delegationSet *string
|
||||
zonesByID map[string]r53Types.HostedZone
|
||||
zonesByDomain map[string]r53Types.HostedZone
|
||||
originalRecords []r53Types.ResourceRecordSet
|
||||
client *r53.Client
|
||||
registrar *r53d.Client
|
||||
delegationSet *string
|
||||
zonesByID map[string]r53Types.HostedZone
|
||||
zonesByDomain map[string]r53Types.HostedZone
|
||||
}
|
||||
|
||||
func newRoute53Reg(conf map[string]string) (providers.Registrar, error) {
|
||||
|
@ -79,7 +78,7 @@ var features = providers.DocumentationNotes{
|
|||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanConcur: providers.Cannot(),
|
||||
providers.CanConcur: providers.Can(),
|
||||
providers.CanUseAlias: providers.Cannot("R53 does not provide a generic ALIAS functionality. Use R53_ALIAS instead."),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
providers.CanUseLOC: providers.Cannot(),
|
||||
|
@ -267,7 +266,6 @@ func (r *route53Provider) getZoneRecords(zone r53Types.HostedZone) (models.Recor
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.originalRecords = records
|
||||
|
||||
var existingRecords = []*models.RecordConfig{}
|
||||
for _, set := range records {
|
||||
|
|
Loading…
Add table
Reference in a new issue