Skip to content

Commit

Permalink
fix: Synchronize API requests
Browse files Browse the repository at this point in the history
Turned out that the Hetzner DNS API doesn't like multiple DNS records
created at the same time. And if there is now implicit dependency
between two resources, Terraform assumes it is safe to create more than
one resource at a time.

There is a bulk create endpoint, which might be the "right" way to
implement the resource. However, it would be neccessary to add a DNS
record group resource or something that groups a list of DNS records and
this make the CRUD operations of this resource more complicated.

I think having one resource per DNS record is good for now. Added a
Mutex to synchronize all API requests. I hope this is an acceptable
slow down. If there is demand for a DNS record set resources, let me
know. It shouldn't be hard to and probably a good first issue for a
contributer :-).

fixes #5
  • Loading branch information
timohirt committed Jul 14, 2020
1 parent 6b966d2 commit 3109ecf
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions hetznerdns/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"log"
"net/http"
"strings"
"sync"
)

// UnauthorizedError represents the message of a HTTP 401 response
Expand All @@ -32,6 +33,7 @@ func defaultCreateHTTPClient() *http.Client {

// Client for the Hetzner DNS API.
type Client struct {
requestLock sync.Mutex
apiToken string
createHTTPClient createHTTPClient
}
Expand All @@ -55,7 +57,16 @@ func (c *Client) doHTTPRequest(apiToken string, method string, url string, body
req.Header.Set("Content-Type", "application/json; charset=utf-8")
}

// This lock ensures that only one request is sent to Hetzber API
// at a time. See issue #5 for context.
// It seems that Terraform creates multiple resources simultanously
// and the API can't handle this right now.
c.requestLock.Lock()

resp, err := client.Do(req)

c.requestLock.Unlock()

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -85,8 +96,6 @@ func parseUnprocessableEntityError(resp *http.Response) (*UnprocessableEntityErr
if err != nil {
return nil, fmt.Errorf("Error reading HTTP response body: %e", err)
}
log.Printf("[DEBUG] 422 Unprocessable Entity error response body: %s", string(body))

var unprocessableEntityError UnprocessableEntityError
err = parseJSON(body, &unprocessableEntityError)
if err != nil {
Expand Down

0 comments on commit 3109ecf

Please sign in to comment.