Skip to content

Commit 616046e

Browse files
authored
Revert "Fix root zone bug and add tests (#4)"
This reverts commit 9692f98.
1 parent 9692f98 commit 616046e

File tree

4 files changed

+63
-200
lines changed

4 files changed

+63
-200
lines changed

.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
LIBDNS_DA_TEST_ZONE=domain.com.
2-
LIBDNS_DA_NON_ROOT_TEST_ZONE=sub.domain.com
32
LIBDNS_DA_TEST_SERVER_URL=https://da.domain.com:2222
43
LIBDNS_DA_TEST_INSECURE_SERVER_URL=https://1.1.1.1:2222
54
LIBDNS_DA_TEST_USER=admin

README.md

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,4 @@ The `CMD_API_SHOW_DOMAINS` permission is needed to get the zone ID, the `CMD_API
3636

3737
If you're only using the `GetRecords()` method, you can remove the `CMD_API_DNS_CONTROL` permission to guarantee no changes will be made.
3838

39-
![Screenshot of login key settings](./assets/login-key-options.png)
40-
41-
## Running Tests
42-
43-
Please note that these tests **must** run against a real direct admin (DA) DNS API.
44-
45-
You should **_never_** run these tests against an in use, production zone.
46-
47-
To run these tests, you need to copy .env.example to .env and modify the values for your environment.
48-
49-
| ENV Var | Description |
50-
|--------------|--------------|
51-
| `LIBDNS_DA_TEST_ZONE` | should be a root zone on the DA server |
52-
| `LIBDNS_DA_NON_ROOT_TEST_ZONE` | should be a non existing subdomain off of a root zoon on the DA server |
53-
| `LIBDNS_DA_TEST_SERVER_URL` | should be a url with a valid TLS certificate |
54-
| `LIBDNS_DA_TEST_INSECURE_SERVER_URL` | should likely be the direct IP url for your DA server |
55-
| `LIBDNS_DA_TEST_USER` | user with API access |
56-
| `LIBDNS_DA_TEST_LOGIN_KEY` | key for user |
39+
![Screenshot of login key settings](./assets/login-key-options.png)

client.go

Lines changed: 53 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,40 @@ import (
44
"context"
55
"crypto/tls"
66
"encoding/json"
7-
"errors"
87
"fmt"
98
"github.com/libdns/libdns"
109
"io"
1110
"log"
1211
"net/http"
1312
"net/url"
13+
"runtime"
1414
"strconv"
1515
"strings"
1616
)
1717

1818
func (p *Provider) getZoneRecords(ctx context.Context, zone string) ([]libdns.Record, error) {
19+
callerSkipDepth := 2
20+
1921
reqURL, err := url.Parse(p.ServerURL)
2022
if err != nil {
21-
fmt.Printf("failed to parse server url: %v\n", err)
23+
fmt.Printf("[%s] failed to parse server url: %v\n", p.caller(callerSkipDepth), err)
2224
return nil, err
2325
}
2426

25-
rootZone, err := p.findRoot(ctx, zone)
26-
if err != nil {
27-
rootZone = zone
28-
}
29-
3027
reqURL.Path = "/CMD_API_DNS_CONTROL"
3128

3229
queryString := make(url.Values)
3330
queryString.Set("json", "yes")
3431
queryString.Set("full_mx_records", "yes")
3532
queryString.Set("allow_dns_underscore", "yes")
3633
queryString.Set("ttl", "yes")
37-
queryString.Set("domain", rootZone)
34+
queryString.Set("domain", zone)
3835

3936
reqURL.RawQuery = queryString.Encode()
4037

4138
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL.String(), nil)
4239
if err != nil {
43-
fmt.Printf("failed to build new request: %v\n", err)
40+
fmt.Printf("[%s] failed to build new request: %v\n", p.caller(callerSkipDepth), err)
4441
return nil, err
4542
}
4643

@@ -55,35 +52,35 @@ func (p *Provider) getZoneRecords(ctx context.Context, zone string) ([]libdns.Re
5552

5653
resp, err := client.Do(req)
5754
if err != nil {
58-
fmt.Printf("failed to execute request: %v\n", err)
55+
fmt.Printf("[%s] failed to execute request: %v\n", p.caller(callerSkipDepth), err)
5956
return nil, err
6057
}
6158
defer func(Body io.ReadCloser) {
6259
err := Body.Close()
6360
if err != nil {
64-
fmt.Printf("failed to close body: %v\n", err)
61+
fmt.Printf("[%s] failed to close body: %v\n", p.caller(callerSkipDepth), err)
6562
}
6663
}(resp.Body)
6764

6865
if resp.StatusCode != http.StatusOK {
69-
fmt.Printf("api response error, status code: %v\n", resp.StatusCode)
66+
fmt.Printf("[%s] api response error, status code: %v\n", p.caller(callerSkipDepth), resp.StatusCode)
7067
return nil, err
7168
}
7269

7370
var respData daZone
7471
err = json.NewDecoder(resp.Body).Decode(&respData)
7572
if err != nil {
76-
fmt.Printf("failed to json decode response: %v\n", err)
73+
fmt.Printf("[%s] failed to json decode response: %v\n", p.caller(callerSkipDepth), err)
7774
return nil, err
7875
}
7976

8077
recs := make([]libdns.Record, 0, len(respData.Records))
8178
for i := range respData.Records {
8279
libDnsRecord, err := respData.Records[i].libdnsRecord(zone)
8380
if err != nil {
84-
switch {
85-
case errors.Is(err, ErrUnsupported):
86-
fmt.Printf("unsupported record conversion of type %v: %v\n", libDnsRecord.Type, libDnsRecord.Name)
81+
switch err {
82+
case ErrUnsupported:
83+
fmt.Printf("[%s] unsupported record conversion of type %v: %v\n", p.caller(callerSkipDepth), libDnsRecord.Type, libDnsRecord.Name)
8784
continue
8885
default:
8986
return nil, err
@@ -101,23 +98,18 @@ func (p *Provider) appendZoneRecord(ctx context.Context, zone string, record lib
10198

10299
reqURL, err := url.Parse(p.ServerURL)
103100
if err != nil {
104-
fmt.Printf("failed to parse server url: %v\n", err)
101+
fmt.Printf("[%s] failed to parse server url: %v\n", p.caller(2), err)
105102
return libdns.Record{}, err
106103
}
107104

108-
rootZone, err := p.findRoot(ctx, zone)
109-
if err != nil {
110-
rootZone = zone
111-
}
112-
113105
reqURL.Path = "/CMD_API_DNS_CONTROL"
114106

115107
queryString := make(url.Values)
116108
queryString.Set("action", "add")
117109
queryString.Set("json", "yes")
118110
queryString.Set("full_mx_records", "yes")
119111
queryString.Set("allow_dns_underscore", "yes")
120-
queryString.Set("domain", rootZone)
112+
queryString.Set("domain", zone)
121113
queryString.Set("type", record.Type)
122114
queryString.Set("name", record.Name)
123115
queryString.Set("value", record.Value)
@@ -128,7 +120,7 @@ func (p *Provider) appendZoneRecord(ctx context.Context, zone string, record lib
128120

129121
reqURL.RawQuery = queryString.Encode()
130122

131-
err = p.executeJsonRequest(ctx, http.MethodGet, reqURL.String())
123+
err = p.executeRequest(ctx, http.MethodGet, reqURL.String())
132124
if err != nil {
133125
return libdns.Record{}, err
134126
}
@@ -144,21 +136,16 @@ func (p *Provider) setZoneRecord(ctx context.Context, zone string, record libdns
144136

145137
reqURL, err := url.Parse(p.ServerURL)
146138
if err != nil {
147-
fmt.Printf("failed to parse server url: %v\n", err)
139+
fmt.Printf("[%s] failed to parse server url: %v\n", p.caller(2), err)
148140
return libdns.Record{}, err
149141
}
150142

151-
rootZone, err := p.findRoot(ctx, zone)
152-
if err != nil {
153-
rootZone = zone
154-
}
155-
156143
reqURL.Path = "/CMD_API_DNS_CONTROL"
157144

158145
queryString := make(url.Values)
159146
queryString.Set("action", "edit")
160147
queryString.Set("json", "yes")
161-
queryString.Set("domain", rootZone)
148+
queryString.Set("domain", zone)
162149
queryString.Set("type", record.Type)
163150
queryString.Set("name", record.Name)
164151
queryString.Set("value", record.Value)
@@ -186,7 +173,7 @@ func (p *Provider) setZoneRecord(ctx context.Context, zone string, record libdns
186173

187174
reqURL.RawQuery = queryString.Encode()
188175

189-
err = p.executeJsonRequest(ctx, http.MethodGet, reqURL.String())
176+
err = p.executeRequest(ctx, http.MethodGet, reqURL.String())
190177
if err != nil {
191178
return libdns.Record{}, err
192179
}
@@ -202,114 +189,38 @@ func (p *Provider) deleteZoneRecord(ctx context.Context, zone string, record lib
202189

203190
reqURL, err := url.Parse(p.ServerURL)
204191
if err != nil {
205-
fmt.Printf("failed to parse server url: %v\n", err)
192+
fmt.Printf("[%s] failed to parse server url: %v\n", p.caller(2), err)
206193
return libdns.Record{}, err
207194
}
208195

209-
rootZone, err := p.findRoot(ctx, zone)
210-
if err != nil {
211-
rootZone = zone
212-
}
213-
214196
reqURL.Path = "/CMD_API_DNS_CONTROL"
215197

216198
queryString := make(url.Values)
217199
queryString.Set("action", "select")
218200
queryString.Set("json", "yes")
219-
queryString.Set("domain", rootZone)
201+
queryString.Set("domain", zone)
220202

221203
editKey := fmt.Sprintf("%vrecs0", strings.ToLower(record.Type))
222204
editValue := fmt.Sprintf("name=%v&value=%v", record.Name, record.Value)
223205
queryString.Set(editKey, editValue)
224206

225207
reqURL.RawQuery = queryString.Encode()
226208

227-
err = p.executeJsonRequest(ctx, http.MethodGet, reqURL.String())
209+
err = p.executeRequest(ctx, http.MethodGet, reqURL.String())
228210
if err != nil {
229211
return libdns.Record{}, err
230212
}
231213

232214
return record, nil
233215
}
234216

235-
func (p *Provider) findRoot(ctx context.Context, zone string) (string, error) {
236-
reqURL, err := url.Parse(p.ServerURL)
237-
if err != nil {
238-
fmt.Printf("failed to parse server url: %v\n", err)
239-
return "", err
240-
}
241-
242-
reqURL.Path = "/CMD_API_SHOW_DOMAINS"
243-
244-
resp, err := p.executeQueryRequest(ctx, http.MethodGet, reqURL.String())
245-
if err != nil {
246-
return "", err
247-
}
248-
249-
zoneParts := strings.Split(zone, ".")
250-
251-
// Limit to 100 rounds
252-
for i := 0; i < 100; i++ {
253-
for _, value := range resp {
254-
if value == strings.Join(zoneParts, ".") {
255-
return value, nil
256-
}
257-
}
258-
259-
zoneParts = zoneParts[1:]
260-
}
261-
262-
return "", errors.New("root zone not found")
263-
}
264-
265-
func (p *Provider) executeJsonRequest(ctx context.Context, method, requestUrl string) error {
266-
resp, err := p.doRequest(ctx, method, requestUrl)
267-
if err != nil {
268-
return err
269-
}
270-
271-
var respData daResponse
272-
err = json.Unmarshal(resp, &respData)
273-
if err != nil {
274-
fmt.Printf("failed to json decode response: %v\n", err)
275-
return err
276-
}
277-
278-
if len(respData.Error) > 0 {
279-
trimmedResult := strings.Split(respData.Result, "\n")[0]
280-
fmt.Printf("api response error: %v: %v\n", respData.Error, trimmedResult)
281-
return fmt.Errorf("api response error: %v: %v\n", respData.Error, trimmedResult)
282-
}
283-
284-
return nil
285-
}
286-
287-
func (p *Provider) executeQueryRequest(ctx context.Context, method, requestUrl string) ([]string, error) {
288-
resp, err := p.doRequest(ctx, method, requestUrl)
289-
if err != nil {
290-
return nil, err
291-
}
292-
293-
params, err := url.ParseQuery(string(resp))
294-
if err != nil {
295-
return nil, err
296-
}
297-
298-
var domains []string
299-
for _, param := range params {
300-
for _, domain := range param {
301-
domains = append(domains, domain)
302-
}
303-
}
304-
305-
return domains, nil
306-
}
217+
func (p *Provider) executeRequest(ctx context.Context, method, url string) error {
218+
callerSkipDepth := 3
307219

308-
func (p *Provider) doRequest(ctx context.Context, method, url string) ([]byte, error) {
309220
req, err := http.NewRequestWithContext(ctx, method, url, nil)
310221
if err != nil {
311-
fmt.Printf("failed to build new request: %v\n", err)
312-
return nil, err
222+
fmt.Printf("[%s] failed to build new request: %v\n", p.caller(callerSkipDepth), err)
223+
return err
313224
}
314225

315226
req.SetBasicAuth(p.User, p.LoginKey)
@@ -323,32 +234,48 @@ func (p *Provider) doRequest(ctx context.Context, method, url string) ([]byte, e
323234

324235
resp, err := client.Do(req)
325236
if err != nil {
326-
fmt.Printf("failed to execute request: %v\n", err)
327-
return nil, err
237+
fmt.Printf("[%s] failed to execute request: %v\n", p.caller(callerSkipDepth), err)
238+
return err
328239
}
329240
defer func(Body io.ReadCloser) {
330241
err := Body.Close()
331242
if err != nil {
332-
fmt.Printf("failed to close body: %v\n", err)
243+
fmt.Printf("[%s] failed to close body: %v\n", p.caller(callerSkipDepth), err)
333244
}
334245
}(resp.Body)
335246

247+
var respData daResponse
248+
err = json.NewDecoder(resp.Body).Decode(&respData)
249+
if err != nil {
250+
fmt.Printf("[%s] failed to json decode response: %v\n", p.caller(callerSkipDepth), err)
251+
return err
252+
}
253+
254+
if len(respData.Error) > 0 {
255+
trimmedResult := strings.Split(respData.Result, "\n")[0]
256+
fmt.Printf("[%s] api response error: %v: %v\n", p.caller(callerSkipDepth), respData.Error, trimmedResult)
257+
return fmt.Errorf("[%s] api response error: %v: %v\n", p.caller(callerSkipDepth), respData.Error, trimmedResult)
258+
}
259+
336260
if resp.StatusCode != http.StatusOK {
337261
bodyBytes, err := io.ReadAll(resp.Body)
338262
if err != nil {
339-
fmt.Printf("failed to read response body: %v\n", err)
340-
return nil, err
263+
fmt.Printf("[%s] failed to read response body: %v\n", p.caller(callerSkipDepth), err)
264+
return err
341265
}
342266
bodyString := string(bodyBytes)
343267
log.Println(bodyString)
344268

345-
return nil, err
269+
return err
346270
}
347271

348-
bodyBytes, err := io.ReadAll(resp.Body)
349-
if err != nil {
350-
return nil, err
351-
}
272+
return nil
273+
}
352274

353-
return bodyBytes, nil
275+
func (p *Provider) caller(skip int) string {
276+
pc := make([]uintptr, 15)
277+
n := runtime.Callers(skip, pc)
278+
frames := runtime.CallersFrames(pc[:n])
279+
frame, _ := frames.Next()
280+
return frame.Function
354281
}

0 commit comments

Comments
 (0)