Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

HETZNER: adopt ZoneCache #3372

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 11 additions & 29 deletions providers/hetzner/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/StackExchange/dnscontrol/v4/pkg/printer"
"github.com/StackExchange/dnscontrol/v4/pkg/zoneCache"
)

const (
Expand All @@ -19,8 +20,7 @@ const (

type hetznerProvider struct {
apiKey string
mu sync.Mutex
cachedZones map[string]zone
zoneCache zoneCache.ZoneCache[zone]
requestRateLimiter requestRateLimiter
}

Expand Down Expand Up @@ -62,7 +62,13 @@ func (api *hetznerProvider) createZone(name string) error {
request := createZoneRequest{
Name: name,
}
return api.request("/zones", "POST", request, nil, nil)
response := createZoneResponse{}
err := api.request("/zones", "POST", request, &response, nil)
if err != nil {
return err
}
api.zoneCache.SetZone(name, response.Zone)
return nil
}

func (api *hetznerProvider) deleteRecord(record *record) error {
Expand All @@ -71,7 +77,7 @@ func (api *hetznerProvider) deleteRecord(record *record) error {
}

func (api *hetznerProvider) getAllRecords(domain string) ([]record, error) {
z, err := api.getZone(domain)
z, err := api.zoneCache.GetZone(domain)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -105,18 +111,7 @@ func (api *hetznerProvider) getAllRecords(domain string) ([]record, error) {
return records, nil
}

func (api *hetznerProvider) resetZoneCache() {
api.mu.Lock()
defer api.mu.Unlock()
api.cachedZones = nil
}

func (api *hetznerProvider) getAllZones() (map[string]zone, error) {
api.mu.Lock()
defer api.mu.Unlock()
if api.cachedZones != nil {
return api.cachedZones, nil
}
func (api *hetznerProvider) fetchAllZones() (map[string]zone, error) {
var zones map[string]zone
page := 1
statusOK := func(code int) bool {
Expand Down Expand Up @@ -148,22 +143,9 @@ func (api *hetznerProvider) getAllZones() (map[string]zone, error) {
}
page++
}
api.cachedZones = zones
return zones, nil
}

func (api *hetznerProvider) getZone(name string) (*zone, error) {
zones, err := api.getAllZones()
if err != nil {
return nil, err
}
z, ok := zones[name]
if !ok {
return nil, fmt.Errorf("%q is not a zone in this HETZNER account", name)
}
return &z, nil
}

func (api *hetznerProvider) request(endpoint string, method string, request interface{}, target interface{}, statusOK func(code int) bool) error {
if statusOK == nil {
statusOK = func(code int) bool {
Expand Down
33 changes: 9 additions & 24 deletions providers/hetzner/hetznerProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/diff"
"github.com/StackExchange/dnscontrol/v4/pkg/zoneCache"
"github.com/StackExchange/dnscontrol/v4/providers"
)

Expand Down Expand Up @@ -50,28 +51,20 @@ func New(settings map[string]string, _ json.RawMessage) (providers.DNSServicePro
return nil, errors.New("missing HETZNER api_key")
}

return &hetznerProvider{
apiKey: apiKey,
}, nil
api := &hetznerProvider{apiKey: apiKey}
api.zoneCache = zoneCache.New(api.fetchAllZones)
return api, nil
}

// EnsureZoneExists creates a zone if it does not exist
func (api *hetznerProvider) EnsureZoneExists(domain string) error {
domains, err := api.ListZones()
if err != nil {
if ok, err := api.zoneCache.HasZone(domain); err != nil || ok {
return err
}

for _, d := range domains {
if d == domain {
return nil
}
}

if err = api.createZone(domain); err != nil {
if err := api.createZone(domain); err != nil {
return err
}
api.resetZoneCache()
return nil
}

Expand All @@ -86,7 +79,7 @@ func (api *hetznerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, e
// Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport)

z, err := api.getZone(domain)
z, err := api.zoneCache.GetZone(domain)
if err != nil {
return nil, 0, err
}
Expand Down Expand Up @@ -143,7 +136,7 @@ func (api *hetznerProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, e

// GetNameservers returns the nameservers for a domain.
func (api *hetznerProvider) GetNameservers(domain string) ([]*models.Nameserver, error) {
z, err := api.getZone(domain)
z, err := api.zoneCache.GetZone(domain)
if err != nil {
return nil, err
}
Expand All @@ -169,13 +162,5 @@ func (api *hetznerProvider) GetZoneRecords(domain string, meta map[string]string

// ListZones lists the zones on this account.
func (api *hetznerProvider) ListZones() ([]string, error) {
zones, err := api.getAllZones()
if err != nil {
return nil, err
}
domains := make([]string, 0, len(zones))
for domain := range zones {
domains = append(domains, domain)
}
return domains, nil
return api.zoneCache.GetZoneNames()
}
6 changes: 5 additions & 1 deletion providers/hetzner/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ type createZoneRequest struct {
Name string `json:"name"`
}

type createZoneResponse struct {
Zone zone `json:"zone"`
}

type getAllRecordsResponse struct {
Records []record `json:"records"`
Meta struct {
Expand Down Expand Up @@ -53,7 +57,7 @@ type zone struct {
TTL uint32 `json:"ttl"`
}

func fromRecordConfig(in *models.RecordConfig, zone *zone) record {
func fromRecordConfig(in *models.RecordConfig, zone zone) record {
r := record{
Name: in.GetLabel(),
Type: in.Type,
Expand Down