1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

HETZNER: handle a 404 from listing zones gracefully (#1371)

The API docs do not mention this, but we saw a case in the wild (1370).

Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
This commit is contained in:
Jakob Ackermann
2022-01-10 21:08:15 +00:00
committed by GitHub
parent 6e29b556a0
commit 2e28dcd644

View File

@@ -78,7 +78,7 @@ func (api *hetznerProvider) bulkCreateRecords(records []record) error {
request := bulkCreateRecordsRequest{
Records: records,
}
return api.request("/records/bulk", "POST", request, nil)
return api.request("/records/bulk", "POST", request, nil, nil)
}
func (api *hetznerProvider) bulkUpdateRecords(records []record) error {
@@ -91,7 +91,7 @@ func (api *hetznerProvider) bulkUpdateRecords(records []record) error {
request := bulkUpdateRecordsRequest{
Records: records,
}
return api.request("/records/bulk", "PUT", request, nil)
return api.request("/records/bulk", "PUT", request, nil, nil)
}
func (api *hetznerProvider) createRecord(record record) error {
@@ -106,14 +106,14 @@ func (api *hetznerProvider) createRecord(record record) error {
Value: record.Value,
ZoneID: record.ZoneID,
}
return api.request("/records", "POST", request, nil)
return api.request("/records", "POST", request, nil, nil)
}
func (api *hetznerProvider) createZone(name string) error {
request := createZoneRequest{
Name: name,
}
return api.request("/zones", "POST", request, nil)
return api.request("/zones", "POST", request, nil, nil)
}
func (api *hetznerProvider) deleteRecord(record record) error {
@@ -122,7 +122,7 @@ func (api *hetznerProvider) deleteRecord(record record) error {
}
url := fmt.Sprintf("/records/%s", record.ID)
return api.request(url, "DELETE", nil, nil)
return api.request(url, "DELETE", nil, nil, nil)
}
func (api *hetznerProvider) getAllRecords(domain string) ([]record, error) {
@@ -135,7 +135,7 @@ func (api *hetznerProvider) getAllRecords(domain string) ([]record, error) {
for {
response := &getAllRecordsResponse{}
url := fmt.Sprintf("/records?zone_id=%s&per_page=100&page=%d", zone.ID, page)
if err := api.request(url, "GET", nil, response); err != nil {
if err := api.request(url, "GET", nil, response, nil); err != nil {
return nil, fmt.Errorf("failed fetching zone records for %q: %w", domain, err)
}
for _, record := range response.Records {
@@ -165,10 +165,21 @@ func (api *hetznerProvider) getAllZones() error {
}
zones := map[string]zone{}
page := 1
statusOK := func(code int) bool {
switch code {
case http.StatusOK:
return true
case http.StatusNotFound:
// Accept a 404 when requesting the first page
return page == 1
default:
return false
}
}
for {
response := &getAllZonesResponse{}
url := fmt.Sprintf("/zones?per_page=100&page=%d", page)
if err := api.request(url, "GET", nil, response); err != nil {
if err := api.request(url, "GET", nil, response, statusOK); err != nil {
return fmt.Errorf("failed fetching zones: %w", err)
}
for _, zone := range response.Zones {
@@ -195,7 +206,12 @@ func (api *hetznerProvider) getZone(name string) (*zone, error) {
return &zone, nil
}
func (api *hetznerProvider) request(endpoint string, method string, request interface{}, target interface{}) error {
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 {
return code == http.StatusOK
}
}
for {
var requestBody io.Reader
if request != nil {
@@ -233,7 +249,7 @@ func (api *hetznerProvider) request(endpoint string, method string, request inte
}
defer cleanupResponseBody()
if resp.StatusCode != 200 {
if !statusOK(resp.StatusCode) {
data, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(data))
return fmt.Errorf("bad status code from HETZNER: %d not 200", resp.StatusCode)
@@ -261,7 +277,7 @@ func (api *hetznerProvider) updateRecord(record record) error {
}
url := fmt.Sprintf("/records/%s", record.ID)
return api.request(url, "PUT", record, nil)
return api.request(url, "PUT", record, nil, nil)
}
type requestRateLimiter struct {