From a00572af4a2d5b12f3a8bf387dcce7a35cfea3ee Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Mon, 1 Aug 2022 19:44:17 +0100 Subject: [PATCH] Create zone before use (#1642) * preview/push: ensure zones exists before querying them Signed-off-by: Jakob Ackermann * HETZNER: reset zone cache when creating a new zone Signed-off-by: Jakob Ackermann * ROUTE53: reset zone cache when creating a new zone Signed-off-by: Jakob Ackermann Co-authored-by: Tom Limoncelli --- commands/previewPush.go | 17 +++++++++------ pkg/nameservers/nameservers.go | 10 ++++++--- providers/hetzner/hetznerProvider.go | 2 ++ providers/route53/route53Provider.go | 31 ++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/commands/previewPush.go b/commands/previewPush.go index f02daecb8..167571bc6 100644 --- a/commands/previewPush.go +++ b/commands/previewPush.go @@ -129,12 +129,7 @@ DomainLoop: continue } out.StartDomain(domain.UniqueName) - nsList, err := nameservers.DetermineNameservers(domain) - if err != nil { - return err - } - domain.Nameservers = nsList - nameservers.AddNSRecords(domain) + var providersWithExistingZone []*models.DNSProviderInstance for _, provider := range domain.DNSProviderInstances { if !args.NoPopulate { @@ -156,7 +151,17 @@ DomainLoop: } } } + providersWithExistingZone = append(providersWithExistingZone, provider) + } + nsList, err := nameservers.DetermineNameserversForProviders(domain, providersWithExistingZone) + if err != nil { + return err + } + domain.Nameservers = nsList + nameservers.AddNSRecords(domain) + + for _, provider := range providersWithExistingZone { dc, err := domain.Copy() if err != nil { return err diff --git a/pkg/nameservers/nameservers.go b/pkg/nameservers/nameservers.go index 2c8b1f5cc..cfa8a7baa 100644 --- a/pkg/nameservers/nameservers.go +++ b/pkg/nameservers/nameservers.go @@ -3,9 +3,8 @@ package nameservers import ( "fmt" - "strings" - "strconv" + "strings" "github.com/StackExchange/dnscontrol/v3/models" ) @@ -14,9 +13,14 @@ 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) +} + +// DetermineNameserversForProviders is like DetermineNameservers, for a subset of providers. +func DetermineNameserversForProviders(dc *models.DomainConfig, providers []*models.DNSProviderInstance) ([]*models.Nameserver, error) { // always take explicit ns := dc.Nameservers - for _, dnsProvider := range dc.DNSProviderInstances { + for _, dnsProvider := range providers { n := dnsProvider.NumberOfNameservers if n == 0 { continue diff --git a/providers/hetzner/hetznerProvider.go b/providers/hetzner/hetznerProvider.go index 982657e3b..3526f81bd 100644 --- a/providers/hetzner/hetznerProvider.go +++ b/providers/hetzner/hetznerProvider.go @@ -73,6 +73,8 @@ func (api *hetznerProvider) EnsureDomainExists(domain string) error { } } + // reset zone cache + api.zones = nil return api.createZone(domain) } diff --git a/providers/route53/route53Provider.go b/providers/route53/route53Provider.go index 4ef9c6234..621163b1d 100644 --- a/providers/route53/route53Provider.go +++ b/providers/route53/route53Provider.go @@ -5,13 +5,14 @@ import ( "encoding/json" "errors" "fmt" - "github.com/StackExchange/dnscontrol/v3/pkg/printer" "log" "sort" "strings" "time" "unicode/utf8" + "github.com/StackExchange/dnscontrol/v3/pkg/printer" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" @@ -122,8 +123,10 @@ func withRetry(f func() error) { // ListZones lists the zones on this account. func (r *route53Provider) ListZones() ([]string, error) { + if err := r.getZones(); err != nil { + return nil, err + } var zones []string - // Assumes r.zones was filled already by newRoute53(). for i := range r.zonesByDomain { zones = append(zones, i) } @@ -131,6 +134,10 @@ func (r *route53Provider) ListZones() ([]string, error) { } func (r *route53Provider) getZones() error { + if r.zonesByDomain != nil { + return nil + } + var nextMarker *string r.zonesByDomain = make(map[string]r53Types.HostedZone) r.zonesByID = make(map[string]r53Types.HostedZone) @@ -178,6 +185,9 @@ func (e errZoneNoExist) Error() string { } func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, error) { + if err := r.getZones(); err != nil { + return nil, err + } zone, ok := r.zonesByDomain[domain] if !ok { @@ -201,6 +211,10 @@ func (r *route53Provider) GetNameservers(domain string) ([]*models.Nameserver, e } func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error) { + if err := r.getZones(); err != nil { + return nil, err + } + if zone, ok := r.zonesByDomain[domain]; ok { return r.getZoneRecords(zone) } @@ -209,6 +223,10 @@ func (r *route53Provider) GetZoneRecords(domain string) (models.Records, error) } func (r *route53Provider) getZone(dc *models.DomainConfig) (r53Types.HostedZone, error) { + if err := r.getZones(); err != nil { + return r53Types.HostedZone{}, err + } + if zoneID, ok := dc.Metadata["zone_id"]; ok { zone, ok := r.zonesByID[zoneID] if !ok { @@ -670,6 +688,10 @@ func unescape(s *string) string { } func (r *route53Provider) EnsureDomainExists(domain string) error { + if err := r.getZones(); err != nil { + return err + } + if _, ok := r.zonesByDomain[domain]; ok { return nil } @@ -683,6 +705,11 @@ func (r *route53Provider) EnsureDomainExists(domain string) error { DelegationSetId: r.delegationSet, CallerReference: aws.String(fmt.Sprint(time.Now().UnixNano())), } + + // reset zone cache + r.zonesByDomain = nil + r.zonesByID = nil + var err error withRetry(func() error { _, err := r.client.CreateHostedZone(context.Background(), in)