Skip to content

Commit a7377ff

Browse files
committed
Add support for rich libdns structs
This change implements support to return DNS API responses not just as `libdns.RR`, but as rich types with parsed contents, as available/[recommended as of libdns v1.0.0](#9 (comment)). It also adjusts an existing test case to check for whether we do this, and fixes a bug in that test where it would pass if the sought record was actually missing.
1 parent c174894 commit a7377ff

File tree

5 files changed

+80
-81
lines changed

5 files changed

+80
-81
lines changed

client-get.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package googleclouddns
22

33
import (
44
"context"
5+
"fmt"
56

67
"github.com/libdns/libdns"
78
"google.golang.org/api/dns/v1"
@@ -22,7 +23,11 @@ func (p *Provider) getCloudDNSRecords(ctx context.Context, zone string) ([]libdn
2223
records := make([]libdns.Record, 0)
2324
if err := rrsReq.Pages(ctx, func(page *dns.ResourceRecordSetsListResponse) error {
2425
for _, googleRecord := range page.Rrsets {
25-
records = append(records, convertToLibDNS(googleRecord, zone)...)
26+
convertedRecords, err := convertToLibDNS(googleRecord, zone)
27+
if err != nil {
28+
return fmt.Errorf("error converting to libdns records: %w", err)
29+
}
30+
records = append(records, convertedRecords...)
2631
}
2732
return nil
2833
}); err != nil {
@@ -46,5 +51,5 @@ func (p *Provider) getCloudDNSRecord(ctx context.Context, zone, name, recordType
4651
if err != nil {
4752
return nil, err
4853
}
49-
return convertToLibDNS(rrs, zone), nil
54+
return convertToLibDNS(rrs, zone)
5055
}

client-post.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ func (p *Provider) postCloudDNSRecord(ctx context.Context, zone string, recordsT
4343
return nil, err
4444
}
4545
}
46-
return convertToLibDNS(googleRecord, zone), nil
46+
return convertToLibDNS(googleRecord, zone)
4747
}

provider.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []lib
117117

118118
// Interface guards
119119
var (
120-
_ libdns.RecordGetter = (*Provider)(nil)
121-
_ libdns.RecordAppender = (*Provider)(nil)
122-
_ libdns.RecordSetter = (*Provider)(nil)
123-
_ libdns.RecordDeleter = (*Provider)(nil)
120+
_ libdns.RecordGetter = new(Provider)
121+
_ libdns.RecordAppender = new(Provider)
122+
_ libdns.RecordSetter = new(Provider)
123+
_ libdns.RecordDeleter = new(Provider)
124124
)

provider_test.go

Lines changed: 59 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package googleclouddns
22

33
import (
44
"context"
5+
"net/netip"
56
"testing"
67
"time"
78

@@ -20,7 +21,7 @@ func Test_GetRecords(t *testing.T) {
2021
t.Fatal(err)
2122
}
2223
defer rs.Close()
23-
t.Run("retrieve existing records", func(t *testing.T) {
24+
t.Run("retrieve existing records and parse to rich type", func(t *testing.T) {
2425
expectedTXTRecordData := `Hi there! This is a TXT record!`
2526
p.Project = testProject
2627
records, err := p.GetRecords(context.Background(), testZone)
@@ -30,15 +31,24 @@ func Test_GetRecords(t *testing.T) {
3031
if len(records) != 6 {
3132
t.Fatal("expected six records back, received", len(records))
3233
}
34+
35+
found := false
36+
expectedName := "hello"
3337
for _, record := range records {
34-
rr := record.RR()
35-
if rr.Type != "TXT" && rr.Name != "hello" {
36-
continue
37-
}
38-
if rr.Data != expectedTXTRecordData {
39-
t.Fatalf("Expected TXT record '%s', received '%s'", expectedTXTRecordData, rr.Data)
38+
switch r := record.(type) {
39+
case libdns.TXT:
40+
found = r.Name == expectedName
41+
if found && r.Text != expectedTXTRecordData {
42+
t.Fatalf("Expected TXT record '%s', received '%s'", expectedTXTRecordData, r.Text)
43+
}
44+
default:
45+
continue // Redundant but be explicit
4046
}
4147
}
48+
49+
if !found {
50+
t.Fatalf("Expected TXT record named '%s', found none", expectedName)
51+
}
4252
})
4353
t.Run("attempt to request non-existent zone", func(t *testing.T) {
4454
p.Project = testProject
@@ -59,22 +69,19 @@ func Test_AppendRecords(t *testing.T) {
5969
}
6070
defer rs.Close()
6171
recordsToAppend := []libdns.Record{
62-
libdns.RR{
63-
Type: "TXT",
72+
libdns.TXT{
6473
Name: "caddy-validation",
65-
Data: `I SHOULD NOT HAVE EXTRA QUOTES`,
74+
Text: `I SHOULD NOT HAVE EXTRA QUOTES`,
6675
TTL: time.Minute,
6776
},
68-
libdns.RR{
69-
Type: "TXT",
77+
libdns.TXT{
7078
Name: "caddy-validation",
71-
Data: `1234567890abcdef`,
79+
Text: `1234567890abcdef`,
7280
TTL: time.Minute,
7381
},
74-
libdns.RR{
75-
Type: "A",
82+
libdns.Address{
7683
Name: "www",
77-
Data: "127.0.0.1",
84+
IP: netip.MustParseAddr("127.0.0.1"),
7885
TTL: time.Minute * 5,
7986
},
8087
}
@@ -104,10 +111,9 @@ func Test_AppendRecords(t *testing.T) {
104111
t.Run("appending creates new entries on existing records", func(t *testing.T) {
105112
p.Project = testProject
106113
recordsToAppend := []libdns.Record{
107-
libdns.RR{
108-
Type: "TXT",
114+
libdns.TXT{
109115
Name: "caddy-validation",
110-
Data: `I provide new information to the cloud`,
116+
Text: `I provide new information to the cloud`,
111117
TTL: time.Minute,
112118
},
113119
}
@@ -123,10 +129,9 @@ func Test_AppendRecords(t *testing.T) {
123129
if err != nil {
124130
t.Fatal("error retrieving TXT record for comparison", err)
125131
}
126-
fullRecord := append(recordsToAppend, libdns.RR{
127-
Type: "TXT",
132+
fullRecord := append(recordsToAppend, libdns.TXT{
128133
Name: "caddy-validation",
129-
Data: `I provide new information to the cloud`,
134+
Text: `I provide new information to the cloud`,
130135
TTL: time.Minute,
131136
},
132137
)
@@ -136,10 +141,9 @@ func Test_AppendRecords(t *testing.T) {
136141
t.Run("appending returns no records where entries exist in existing Cloud DNS entry", func(t *testing.T) {
137142
p.Project = testProject
138143
recordsToAppend := []libdns.Record{
139-
libdns.RR{
140-
Type: "TXT",
144+
libdns.TXT{
141145
Name: "caddy-validation",
142-
Data: `I provide new information to the cloud`,
146+
Text: `I provide new information to the cloud`,
143147
TTL: time.Minute,
144148
},
145149
}
@@ -169,16 +173,14 @@ func Test_SetRecords(t *testing.T) {
169173
t.Run("setting creates new records", func(t *testing.T) {
170174
p.Project = testProject
171175
recordsToCreate := []libdns.Record{
172-
libdns.RR{
173-
Type: "TXT",
176+
libdns.TXT{
174177
Name: "caddy-validation-mark2",
175-
Data: `I SHOULD NOT HAVE EXTRA QUOTES`,
178+
Text: `I SHOULD NOT HAVE EXTRA QUOTES`,
176179
TTL: time.Minute,
177180
},
178-
libdns.RR{
179-
Type: "TXT",
181+
libdns.TXT{
180182
Name: "caddy-validation-mark2",
181-
Data: `1234567890abcdef`,
183+
Text: `1234567890abcdef`,
182184
TTL: time.Minute,
183185
},
184186
}
@@ -200,10 +202,9 @@ func Test_SetRecords(t *testing.T) {
200202
t.Run("setting overwrites existing records", func(t *testing.T) {
201203
p.Project = testProject
202204
recordsToOverwrite := []libdns.Record{
203-
libdns.RR{
204-
Type: "TXT",
205+
libdns.TXT{
205206
Name: "caddy-validation-mark2",
206-
Data: `I provide new information to the cloud`,
207+
Text: `I provide new information to the cloud`,
207208
TTL: time.Minute,
208209
},
209210
}
@@ -232,10 +233,9 @@ func Test_DeleteRecords(t *testing.T) {
232233
t.Run("delete entire record", func(t *testing.T) {
233234
p.Project = testProject
234235
recordsToDelete := []libdns.Record{
235-
libdns.RR{
236-
Type: "TXT",
236+
libdns.TXT{
237237
Name: "caddy-validation-mark2",
238-
Data: `I provide new information to the cloud`,
238+
Text: `I provide new information to the cloud`,
239239
TTL: time.Minute,
240240
},
241241
}
@@ -256,24 +256,21 @@ func Test_DeleteRecords(t *testing.T) {
256256
t.Run("deletes a single record from a multi record entry", func(t *testing.T) {
257257
p.Project = testProject
258258
recordsToDelete := []libdns.Record{
259-
libdns.RR{
260-
Type: "TXT",
259+
libdns.TXT{
261260
Name: "caddy-validation",
262-
Data: `I SHOULD NOT HAVE EXTRA QUOTES`,
261+
Text: `I SHOULD NOT HAVE EXTRA QUOTES`,
263262
TTL: time.Minute,
264263
},
265264
}
266265
recordsCleaned := []libdns.Record{
267-
libdns.RR{
268-
Type: "TXT",
266+
libdns.TXT{
269267
Name: "caddy-validation",
270-
Data: `I provide new information to the cloud`,
268+
Text: `I provide new information to the cloud`,
271269
TTL: time.Minute,
272270
},
273-
libdns.RR{
274-
Type: "TXT",
271+
libdns.TXT{
275272
Name: "caddy-validation",
276-
Data: `1234567890abcdef`,
273+
Text: `1234567890abcdef`,
277274
TTL: time.Minute,
278275
},
279276
}
@@ -295,24 +292,21 @@ func Test_DeleteRecords(t *testing.T) {
295292
t.Run("deletes no records when a non-existent one is specified", func(t *testing.T) {
296293
p.Project = testProject
297294
recordsToDelete := []libdns.Record{
298-
libdns.RR{
299-
Type: "TXT",
295+
libdns.TXT{
300296
Name: "caddy-validation",
301-
Data: `I SHOULD NOT HAVE EXTRA QUOTES`,
297+
Text: `I SHOULD NOT HAVE EXTRA QUOTES`,
302298
TTL: time.Minute,
303299
},
304300
}
305301
recordsCleaned := []libdns.Record{
306-
libdns.RR{
307-
Type: "TXT",
302+
libdns.TXT{
308303
Name: "caddy-validation",
309-
Data: `I provide new information to the cloud`,
304+
Text: `I provide new information to the cloud`,
310305
TTL: time.Minute,
311306
},
312-
libdns.RR{
313-
Type: "TXT",
307+
libdns.TXT{
314308
Name: "caddy-validation",
315-
Data: `1234567890abcdef`,
309+
Text: `1234567890abcdef`,
316310
TTL: time.Minute,
317311
},
318312
}
@@ -333,24 +327,21 @@ func Test_DeleteRecords(t *testing.T) {
333327
t.Run("deletes one record when two are specified", func(t *testing.T) {
334328
p.Project = testProject
335329
recordsToDelete := []libdns.Record{
336-
libdns.RR{
337-
Type: "TXT",
330+
libdns.TXT{
338331
Name: "caddy-validation",
339-
Data: `I SHOULD NOT HAVE EXTRA QUOTES`,
332+
Text: `I SHOULD NOT HAVE EXTRA QUOTES`,
340333
TTL: time.Minute,
341334
},
342-
libdns.RR{
343-
Type: "TXT",
335+
libdns.TXT{
344336
Name: "caddy-validation",
345-
Data: `I provide new information to the cloud`,
337+
Text: `I provide new information to the cloud`,
346338
TTL: time.Minute,
347339
},
348340
}
349341
recordsCleaned := []libdns.Record{
350-
libdns.RR{
351-
Type: "TXT",
342+
libdns.TXT{
352343
Name: "caddy-validation",
353-
Data: `1234567890abcdef`,
344+
Text: `1234567890abcdef`,
354345
TTL: time.Minute,
355346
},
356347
}
@@ -378,18 +369,16 @@ func Test_EndToEnd(t *testing.T) {
378369
defer rs.Close()
379370
p.Project = testProject
380371
requestsOne := []libdns.Record{
381-
libdns.RR{
382-
Type: "TXT",
372+
libdns.TXT{
383373
Name: "_acme-challenge",
384-
Data: `1234567890abcdef`,
374+
Text: `1234567890abcdef`,
385375
TTL: 0,
386376
},
387377
}
388378
requestsTwo := []libdns.Record{
389-
libdns.RR{
390-
Type: "TXT",
379+
libdns.TXT{
391380
Name: "_acme-challenge",
392-
Data: `fedcba0987654321`,
381+
Text: `fedcba0987654321`,
393382
TTL: 0,
394383
},
395384
}

util.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,24 @@ func (l libdnsRecords) prepValuesForCloudDNS() []string {
7474

7575
// convertToLibDNS takes Cloud DNS record set and converts it into a set of libdns
7676
// records. Note that this will remove the quotes around a value.
77-
func convertToLibDNS(googleRecord *dns.ResourceRecordSet, zone string) libdnsRecords {
77+
func convertToLibDNS(googleRecord *dns.ResourceRecordSet, zone string) (libdnsRecords, error) {
7878
records := make([]libdns.Record, 0)
7979
for _, value := range googleRecord.Rrdatas {
8080
// there can be multiple values per record so
8181
// let's treat each one as a separate libdns Record
82-
// TODO: switch on `value.Type` here to populate proper `libdns` type of RR
83-
record := libdns.RR{
82+
83+
record, err := libdns.RR{
8484
Type: googleRecord.Type,
8585
Name: libdns.RelativeName(googleRecord.Name, zone),
8686
Data: strings.Trim(value, `"`),
8787
TTL: time.Duration(googleRecord.Ttl) * time.Second,
88+
}.Parse()
89+
90+
if err != nil {
91+
return nil, fmt.Errorf("error parsing record of type '%s': %w", googleRecord.Type, err)
8892
}
93+
8994
records = append(records, record)
9095
}
91-
return records
96+
return records, nil
9297
}

0 commit comments

Comments
 (0)