Skip to content
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
5 changes: 3 additions & 2 deletions providers/dns/autodns/autodns.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
Value: info.Value,
}}

_, err := d.client.AddTxtRecords(context.Background(), info.EffectiveFQDN, records)
_, err := d.client.AddRecords(context.Background(), info.EffectiveFQDN, records)
if err != nil {
return fmt.Errorf("autodns: %w", err)
}
Expand All @@ -147,7 +147,8 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
Value: info.Value,
}}

if err := d.client.RemoveTXTRecords(context.Background(), info.EffectiveFQDN, records); err != nil {
_, err := d.client.RemoveRecords(context.Background(), info.EffectiveFQDN, records)
if err != nil {
return fmt.Errorf("autodns: %w", err)
}

Expand Down
35 changes: 23 additions & 12 deletions providers/dns/autodns/internal/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,37 +43,35 @@ func NewClient(username, password string, clientContext int) *Client {
}
}

// AddTxtRecords adds TXT records.
func (c *Client) AddTxtRecords(ctx context.Context, domain string, records []*ResourceRecord) (*Zone, error) {
// AddRecords adds records.
func (c *Client) AddRecords(ctx context.Context, domain string, records []*ResourceRecord) (*DataZoneResponse, error) {
zoneStream := &ZoneStream{Adds: records}

return c.updateZone(ctx, domain, zoneStream)
}

// RemoveTXTRecords removes TXT records.
func (c *Client) RemoveTXTRecords(ctx context.Context, domain string, records []*ResourceRecord) error {
// RemoveRecords removes records.
func (c *Client) RemoveRecords(ctx context.Context, domain string, records []*ResourceRecord) (*DataZoneResponse, error) {
zoneStream := &ZoneStream{Removes: records}

_, err := c.updateZone(ctx, domain, zoneStream)

return err
return c.updateZone(ctx, domain, zoneStream)
}

// https://github.com/InterNetX/domainrobot-api/blob/bdc8fe92a2f32fcbdb29e30bf6006ab446f81223/src/domainrobot.json#L21090
func (c *Client) updateZone(ctx context.Context, domain string, zoneStream *ZoneStream) (*Zone, error) {
func (c *Client) updateZone(ctx context.Context, domain string, zoneStream *ZoneStream) (*DataZoneResponse, error) {
endpoint := c.BaseURL.JoinPath("zone", domain, "_stream")

req, err := newJSONRequest(ctx, http.MethodPost, endpoint, zoneStream)
if err != nil {
return nil, err
}

var zone *Zone
if err := c.do(req, &zone); err != nil {
var resp *DataZoneResponse
if err := c.do(req, &resp); err != nil {
return nil, err
}

return zone, nil
return resp, nil
}

func (c *Client) do(req *http.Request, result any) error {
Expand All @@ -88,7 +86,7 @@ func (c *Client) do(req *http.Request, result any) error {
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode/100 != 2 {
return errutils.NewUnexpectedResponseStatusCodeError(req, resp)
return parseError(req, resp)
}

if result == nil {
Expand Down Expand Up @@ -131,3 +129,16 @@ func newJSONRequest(ctx context.Context, method string, endpoint *url.URL, paylo

return req, nil
}

func parseError(req *http.Request, resp *http.Response) error {
raw, _ := io.ReadAll(resp.Body)

var errAPI APIError

err := json.Unmarshal(raw, &errAPI)
if err != nil {
return errutils.NewUnexpectedStatusCodeError(req, resp.StatusCode, raw)
}

return &errAPI
}
140 changes: 122 additions & 18 deletions providers/dns/autodns/internal/client_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"net/http"
"net/http/httptest"
"net/url"
"testing"
Expand All @@ -24,7 +25,7 @@ func mockBuilder() *servermock.Builder[*Client] {
WithJSONHeaders())
}

func TestClient_AddTxtRecords(t *testing.T) {
func TestClient_AddRecords(t *testing.T) {
client := mockBuilder().
Route("POST /zone/example.com/_stream",
servermock.ResponseFromFixture("add_record.json"),
Expand All @@ -33,28 +34,81 @@ func TestClient_AddTxtRecords(t *testing.T) {
With("X-Domainrobot-Context", "123")).
Build(t)

records := []*ResourceRecord{{}}
records := []*ResourceRecord{{
Name: "example.com",
TTL: 600,
Type: "TXT",
Value: "txtTXTtxt",
}}

zone, err := client.AddTxtRecords(t.Context(), "example.com", records)
resp, err := client.AddRecords(t.Context(), "example.com", records)
require.NoError(t, err)

expected := &Zone{
Name: "example.com",
ResourceRecords: []*ResourceRecord{{
Name: "example.com",
TTL: 120,
Type: "TXT",
Value: "txt",
Pref: 1,
}},
Action: "xxx",
VirtualNameServer: "yyy",
expected := &DataZoneResponse{
STID: "20251121-appf4923-126284",
CTID: "",
Messages: []ResponseMessage{
{
Text: "string",
Messages: []string{
"string",
},
Objects: []GenericObject{
{
Type: "string",
Value: "string",
},
},
Code: "string",
Status: "SUCCESS",
},
},
Status: &ResponseStatus{
Code: "S0301",
Text: "Zone was updated successfully on the name server.",
Type: "SUCCESS",
},
Object: nil,
Data: []Zone{
{
Name: "example.com",
ResourceRecords: []ResourceRecord{
{
Name: "example.com",
TTL: 120,
Type: "TXT",
Value: "txt",
Pref: 1,
},
},
Action: "xxx",
VirtualNameServer: "yyy",
},
},
}

assert.Equal(t, expected, zone)
assert.Equal(t, expected, resp)
}

func TestClient_AddRecords_error(t *testing.T) {
client := mockBuilder().
Route("POST /zone/example.com/_stream",
servermock.ResponseFromFixture("error.json").
WithStatusCode(http.StatusBadRequest)).
Build(t)

records := []*ResourceRecord{{
Name: "example.com",
TTL: 600,
Type: "TXT",
Value: "txtTXTtxt",
}}

_, err := client.AddRecords(t.Context(), "example.com", records)
require.EqualError(t, err, `STID: 20251121-appf4923-126284, status: code: E0202002, text: Zone konnte auf dem Nameserver nicht aktualisiert werden., type: ERROR, message: code: EF02022, text: Der Zusatzeintrag wurde doppelt eingetragen., status: ERROR, object: OURDOMAIN.TLD@nsa7.schlundtech.de/rr[17]: _acme-challenge.www.whoami.int.OURDOMAIN.TLD TXT "rK2SJb_ZcrYefbfCKU6jZEANfEAJeOtSh1Fv8hkUoVc"`)
}

func TestClient_RemoveTXTRecords(t *testing.T) {
func TestClient_RemoveRecords(t *testing.T) {
client := mockBuilder().
Route("POST /zone/example.com/_stream",
servermock.ResponseFromFixture("remove_record.json"),
Expand All @@ -63,8 +117,58 @@ func TestClient_RemoveTXTRecords(t *testing.T) {
With("X-Domainrobot-Context", "123")).
Build(t)

records := []*ResourceRecord{{}}
records := []*ResourceRecord{{
Name: "example.com",
TTL: 600,
Type: "TXT",
Value: "txtTXTtxt",
}}

err := client.RemoveTXTRecords(t.Context(), "example.com", records)
resp, err := client.RemoveRecords(t.Context(), "example.com", records)
require.NoError(t, err)

expected := &DataZoneResponse{
STID: "20251121-appf4923-126284",
CTID: "",
Messages: []ResponseMessage{
{
Text: "string",
Messages: []string{
"string",
},
Objects: []GenericObject{
{
Type: "string",
Value: "string",
},
},
Code: "string",
Status: "SUCCESS",
},
},
Status: &ResponseStatus{
Code: "S0301",
Text: "Zone was updated successfully on the name server.",
Type: "SUCCESS",
},
Object: nil,
Data: []Zone{
{
Name: "example.com",
ResourceRecords: []ResourceRecord{
{
Name: "example.com",
TTL: 120,
Type: "TXT",
Value: "txt",
Pref: 1,
},
},
Action: "xxx",
VirtualNameServer: "yyy",
},
},
}

assert.Equal(t, expected, resp)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"adds": [
{
"name": "",
"ttl": 0,
"type": "",
"value": ""
"name": "example.com",
"ttl": 600,
"type": "TXT",
"value": "txtTXTtxt"
}
],
"rems": null
Expand Down
45 changes: 36 additions & 9 deletions providers/dns/autodns/internal/fixtures/add_record.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
{
"origin": "example.com",
"resourceRecords": [
"stid": "20251121-appf4923-126284",
"messages": [
{
"name": "example.com",
"ttl": 120,
"type": "TXT",
"value": "txt",
"pref": 1
"text": "string",
"notice": "string",
"messages": [
"string"
],
"objects": [
{
"type": "string",
"value": "string"
}
],
"code": "string",
"status": "SUCCESS"
}
],
"action": "xxx",
"virtualNameServer": "yyy"
"status": {
"code": "S0301",
"text": "Zone was updated successfully on the name server.",
"type": "SUCCESS"
},
"data": [
{
"origin": "example.com",
"resourceRecords": [
{
"name": "example.com",
"ttl": 120,
"type": "TXT",
"value": "txt",
"pref": 1
}
],
"action": "xxx",
"virtualNameServer": "yyy"
}
]
}
21 changes: 21 additions & 0 deletions providers/dns/autodns/internal/fixtures/error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"stid": "20251121-appf4923-126284",
"messages": [
{
"text": "Der Zusatzeintrag wurde doppelt eingetragen.",
"objects": [
{
"type": "OURDOMAIN.TLD@nsa7.schlundtech.de/rr[17]",
"value": "_acme-challenge.www.whoami.int.OURDOMAIN.TLD TXT \"rK2SJb_ZcrYefbfCKU6jZEANfEAJeOtSh1Fv8hkUoVc\""
}
],
"code": "EF02022",
"status": "ERROR"
}
],
"status": {
"code": "E0202002",
"text": "Zone konnte auf dem Nameserver nicht aktualisiert werden.",
"type": "ERROR"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"adds": null,
"rems": [
{
"name": "",
"ttl": 0,
"type": "",
"value": ""
"name": "example.com",
"ttl": 600,
"type": "TXT",
"value": "txtTXTtxt"
}
]
}
Loading