diff --git a/providers/dns/excedo/internal/client.go b/providers/dns/excedo/internal/client.go index 061fb3852..a5d8be88b 100644 --- a/providers/dns/excedo/internal/client.go +++ b/providers/dns/excedo/internal/client.go @@ -19,21 +19,9 @@ import ( querystring "github.com/google/go-querystring/query" ) -// Response codes: -// - 1000: Command completed successfully -// - 1300: Command completed successfully; no messages -// - 2001: Command syntax error -// - 2002: Command use error -// - 2003: Required parameter missing -// - 2004: Parameter value range error -// - 2104: Billing failure -// - 2200: Authentication error -// - 2201: Authorization error -// - 2303: Object does not exist -// - 2304: Object status prohibits operation -// - 2309: Object duplicate found -// - 2400: Command failed -// - 2500: Command failed; server closing connection +type responseChecker interface { + Check() error +} // Client the Excedo API client. type Client struct { @@ -84,10 +72,6 @@ func (c *Client) AddRecord(ctx context.Context, record Record) (int64, error) { return 0, err } - if result.Code != 1000 && result.Code != 1300 { - return 0, fmt.Errorf("%d: %s", result.Code, result.Description) - } - return result.RecordID, nil } @@ -111,10 +95,6 @@ func (c *Client) DeleteRecord(ctx context.Context, zone, recordID string) error return err } - if result.Code != 1000 && result.Code != 1300 { - return fmt.Errorf("%d: %s", result.Code, result.Description) - } - return nil } @@ -123,6 +103,7 @@ func (c *Client) GetRecords(ctx context.Context, zone string) (map[string]Zone, query := endpoint.Query() query.Set("domainname", zone) + endpoint.RawQuery = query.Encode() req, err := newFormRequest(ctx, http.MethodGet, endpoint, nil) @@ -137,14 +118,10 @@ func (c *Client) GetRecords(ctx context.Context, zone string) (map[string]Zone, return nil, err } - if result.Code != 1000 && result.Code != 1300 { - return nil, fmt.Errorf("%d: %s", result.Code, result.Description) - } - return result.DNS, nil } -func (c *Client) do(req *http.Request, result any) error { +func (c *Client) do(req *http.Request, result responseChecker) error { useragent.SetHeader(req.Header) resp, err := c.HTTPClient.Do(req) @@ -174,7 +151,7 @@ func (c *Client) do(req *http.Request, result any) error { return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err) } - return nil + return result.Check() } func newMultipartRequest(ctx context.Context, method string, endpoint *url.URL, data map[string]string) (*http.Request, error) { diff --git a/providers/dns/excedo/internal/client_test.go b/providers/dns/excedo/internal/client_test.go index 546827a41..f4fd52c00 100644 --- a/providers/dns/excedo/internal/client_test.go +++ b/providers/dns/excedo/internal/client_test.go @@ -59,6 +59,30 @@ func TestClient_AddRecord(t *testing.T) { assert.EqualValues(t, 19695822, recordID) } +func TestClient_AddRecord_error(t *testing.T) { + client := mockBuilder(). + Route("POST /dns/addrecord/", + servermock.ResponseFromFixture("error.json"), + ). + Build(t) + + client.token = &ExpirableToken{ + Token: "session-token", + Expires: time.Now().Add(6 * time.Hour), + } + + record := Record{ + DomainName: "example.com", + Name: "_acme-challenge", + Type: "TXT", + Content: "ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY", + TTL: "60", + } + + _, err := client.AddRecord(t.Context(), record) + require.EqualError(t, err, "2003: Required parameter missing") +} + func TestClient_DeleteRecord(t *testing.T) { client := mockBuilder(). Route("POST /dns/deleterecord/", diff --git a/providers/dns/excedo/internal/identity.go b/providers/dns/excedo/internal/identity.go index 38501ef7d..5c9ca119d 100644 --- a/providers/dns/excedo/internal/identity.go +++ b/providers/dns/excedo/internal/identity.go @@ -61,7 +61,7 @@ func (c *Client) authenticate(ctx context.Context) (string, error) { return c.token.Token, nil } -func (c *Client) doAuthenticated(ctx context.Context, req *http.Request, result any) error { +func (c *Client) doAuthenticated(ctx context.Context, req *http.Request, result responseChecker) error { token, err := c.authenticate(ctx) if err != nil { return err diff --git a/providers/dns/excedo/internal/identity_test.go b/providers/dns/excedo/internal/identity_test.go index deff429c3..86b7eb9d8 100644 --- a/providers/dns/excedo/internal/identity_test.go +++ b/providers/dns/excedo/internal/identity_test.go @@ -22,3 +22,14 @@ func TestClient_Login(t *testing.T) { assert.Equal(t, "session-token", token) } + +func TestClient_Login_error(t *testing.T) { + client := mockBuilder(). + Route("GET /authenticate/login/", + servermock.ResponseFromFixture("error.json"), + ). + Build(t) + + _, err := client.Login(t.Context()) + require.EqualError(t, err, "2003: Required parameter missing") +} diff --git a/providers/dns/excedo/internal/types.go b/providers/dns/excedo/internal/types.go index 7e42ac46a..eb6ce8462 100644 --- a/providers/dns/excedo/internal/types.go +++ b/providers/dns/excedo/internal/types.go @@ -1,10 +1,35 @@ package internal +import "fmt" + type BaseResponse struct { Code int `json:"code"` Description string `json:"desc"` } +func (r BaseResponse) Check() error { + // Response codes: + // - 1000: Command completed successfully + // - 1300: Command completed successfully; no messages + // - 2001: Command syntax error + // - 2002: Command use error + // - 2003: Required parameter missing + // - 2004: Parameter value range error + // - 2104: Billing failure + // - 2200: Authentication error + // - 2201: Authorization error + // - 2303: Object does not exist + // - 2304: Object status prohibits operation + // - 2309: Object duplicate found + // - 2400: Command failed + // - 2500: Command failed; server closing connection + if r.Code != 1000 && r.Code != 1300 { + return fmt.Errorf("%d: %s", r.Code, r.Description) + } + + return nil +} + type GetRecordsResponse struct { BaseResponse