Skip to content

Commit 52cac96

Browse files
committed
add unit test and better help messages
1 parent 49a9901 commit 52cac96

File tree

4 files changed

+222
-13
lines changed

4 files changed

+222
-13
lines changed

internal/services/domain/helpers.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ func getRecordFromTypeAndData(dnsType domain.RecordType, data string, records []
3232
var currentRecord *domain.Record
3333

3434
for _, r := range records {
35-
flattedData := flattenDomainData(strings.ToLower(r.Data), r.Type).(string)
36-
flattenCurrentData := flattenDomainData(strings.ToLower(data), r.Type).(string)
35+
flattedData := FlattenDomainData(strings.ToLower(r.Data), r.Type).(string)
36+
flattenCurrentData := FlattenDomainData(strings.ToLower(data), r.Type).(string)
3737

3838
if dnsType == domain.RecordTypeSRV {
3939
if flattedData == flattenCurrentData {
4040
if currentRecord != nil {
41-
return nil, errors.New("multiple records found with same type and data")
41+
return nil, fmt.Errorf("multiple records found with same type and data: existing record %s (ID: %s) conflicts with new record data %s", currentRecord.Data, currentRecord.ID, data)
4242
}
4343

4444
currentRecord = r
@@ -48,7 +48,7 @@ func getRecordFromTypeAndData(dnsType domain.RecordType, data string, records []
4848
} else {
4949
if strings.HasPrefix(flattedData, flattenCurrentData) && r.Type == dnsType {
5050
if currentRecord != nil {
51-
return nil, errors.New("multiple records found with same type and data")
51+
return nil, fmt.Errorf("multiple records found with same type and data: existing record %s (ID: %s) conflicts with new record data %s", currentRecord.Data, currentRecord.ID, data)
5252
}
5353

5454
currentRecord = r

internal/services/domain/record.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func resourceRecordCreate(ctx context.Context, d *schema.ResourceData, m any) di
296296
return diag.FromErr(err)
297297
}
298298

299-
currentRecord, err := getRecordFromTypeAndData(recordType, flattenDomainData(recordData, recordType).(string), dnsZoneData.Records)
299+
currentRecord, err := getRecordFromTypeAndData(recordType, FlattenDomainData(recordData, recordType).(string), dnsZoneData.Records)
300300
if err != nil {
301301
return diag.FromErr(err)
302302
}
@@ -408,7 +408,7 @@ func resourceDomainRecordRead(ctx context.Context, d *schema.ResourceData, m any
408408
_ = d.Set("dns_zone", dnsZone)
409409
_ = d.Set("name", record.Name)
410410
_ = d.Set("type", record.Type.String())
411-
_ = d.Set("data", flattenDomainData(record.Data, record.Type).(string))
411+
_ = d.Set("data", FlattenDomainData(record.Data, record.Type).(string))
412412
_ = d.Set("ttl", int(record.TTL))
413413
_ = d.Set("priority", int(record.Priority))
414414
_ = d.Set("geo_ip", flattenDomainGeoIP(record.GeoIPConfig))

internal/services/domain/types.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import (
88
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
99
)
1010

11-
func flattenDomainData(data string, recordType domain.RecordType) any {
11+
// FlattenDomainData normalizes domain record data based on record type
12+
func FlattenDomainData(data string, recordType domain.RecordType) any {
1213
switch recordType {
1314
case domain.RecordTypeMX: // API return this format: "{priority} {data}"
1415
dataSplit := strings.SplitN(data, " ", 2)
@@ -18,19 +19,19 @@ func flattenDomainData(data string, recordType domain.RecordType) any {
1819
case domain.RecordTypeTXT:
1920
return strings.Trim(data, "\"")
2021
case domain.RecordTypeSRV:
21-
return normalizeSRVData(data)
22+
return NormalizeSRVData(data)
2223
}
2324

2425
return data
2526
}
2627

27-
// normalizeSRVData normalizes SRV record data by handling weight field and zone domain suffixes
28-
func normalizeSRVData(data string) string {
28+
// NormalizeSRVData normalizes SRV record data by handling weight field and zone domain suffixes
29+
func NormalizeSRVData(data string) string {
2930
parts := strings.Fields(data)
3031

3132
if len(parts) >= 4 {
3233
priority, weight, port, target := parts[0], parts[1], parts[2], parts[3]
33-
target = removeZoneDomainSuffix(target)
34+
target = RemoveZoneDomainSuffix(target)
3435

3536
return strings.Join([]string{priority, weight, port, target}, " ")
3637
}
@@ -44,8 +45,8 @@ func normalizeSRVData(data string) string {
4445
return data
4546
}
4647

47-
// removeZoneDomainSuffix removes the zone domain suffix from a target
48-
func removeZoneDomainSuffix(target string) string {
48+
// RemoveZoneDomainSuffix removes the zone domain suffix from a target
49+
func RemoveZoneDomainSuffix(target string) string {
4950
if !strings.Contains(target, ".") {
5051
return target
5152
}
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package domain_test
2+
3+
import (
4+
"testing"
5+
6+
domainSDK "github.com/scaleway/scaleway-sdk-go/api/domain/v2beta1"
7+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/domain"
8+
)
9+
10+
func TestFlattenDomainData(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
data string
14+
recordType domainSDK.RecordType
15+
expected string
16+
}{
17+
{
18+
name: "SRV record with domain duplication",
19+
data: "0 0 1234 foo.noet-ia.com.noet-ia.com.",
20+
recordType: domainSDK.RecordTypeSRV,
21+
expected: "0 0 1234 foo.noet-ia.",
22+
},
23+
{
24+
name: "SRV record without domain duplication",
25+
data: "0 0 1234 foo.noet-ia.com",
26+
recordType: domainSDK.RecordTypeSRV,
27+
expected: "0 0 1234 foo.noet-ia.com",
28+
},
29+
{
30+
name: "SRV record with complex domain duplication",
31+
data: "10 5 8080 service.example.com.example.com.",
32+
recordType: domainSDK.RecordTypeSRV,
33+
expected: "10 5 8080 service.example.",
34+
},
35+
{
36+
name: "SRV record with no duplication pattern",
37+
data: "0 0 1234 foo.bar.com",
38+
recordType: domainSDK.RecordTypeSRV,
39+
expected: "0 0 1234 foo.bar.com",
40+
},
41+
{
42+
name: "SRV record with trailing dot only",
43+
data: "0 0 1234 foo.example.com.",
44+
recordType: domainSDK.RecordTypeSRV,
45+
expected: "0 0 1234 foo.example.com.",
46+
},
47+
{
48+
name: "SRV record with real test case",
49+
data: "0 0 1234 foo.example.com.test-srv-duplication.scaleway-terraform.com.",
50+
recordType: domainSDK.RecordTypeSRV,
51+
expected: "0 0 1234 foo.example.com.",
52+
},
53+
{
54+
name: "SRV record with Terraform data (3 parts)",
55+
data: "0 1234 foo.example.com",
56+
recordType: domainSDK.RecordTypeSRV,
57+
expected: "0 0 1234 foo.example.com",
58+
},
59+
{
60+
name: "MX record",
61+
data: "10 mail.example.com",
62+
recordType: domainSDK.RecordTypeMX,
63+
expected: "mail.example.com",
64+
},
65+
{
66+
name: "TXT record",
67+
data: "\"v=spf1 include:_spf.example.com ~all\"",
68+
recordType: domainSDK.RecordTypeTXT,
69+
expected: "v=spf1 include:_spf.example.com ~all",
70+
},
71+
{
72+
name: "A record",
73+
data: "192.168.1.1",
74+
recordType: domainSDK.RecordTypeA,
75+
expected: "192.168.1.1",
76+
},
77+
}
78+
79+
for _, tt := range tests {
80+
t.Run(tt.name, func(t *testing.T) {
81+
result := domain.FlattenDomainData(tt.data, tt.recordType)
82+
if result != tt.expected {
83+
t.Errorf("flattenDomainData(%q, %v) = %q, want %q", tt.data, tt.recordType, result, tt.expected)
84+
}
85+
})
86+
}
87+
}
88+
89+
func TestNormalizeSRVData(t *testing.T) {
90+
tests := []struct {
91+
name string
92+
input string
93+
expected string
94+
}{
95+
{
96+
name: "SRV with weight 0",
97+
input: "0 0 8080 server.example.com",
98+
expected: "0 0 8080 server.example.com",
99+
},
100+
{
101+
name: "SRV with weight 1",
102+
input: "0 1 8080 server.example.com",
103+
expected: "0 1 8080 server.example.com",
104+
},
105+
{
106+
name: "SRV with high weight",
107+
input: "0 100 8080 server.example.com",
108+
expected: "0 100 8080 server.example.com",
109+
},
110+
{
111+
name: "SRV with priority 10",
112+
input: "10 0 8080 server.example.com",
113+
expected: "10 0 8080 server.example.com",
114+
},
115+
{
116+
name: "SRV with port 443",
117+
input: "0 0 443 server.example.com",
118+
expected: "0 0 443 server.example.com",
119+
},
120+
{
121+
name: "SRV with complex target",
122+
input: "0 0 8080 server.subdomain.example.com",
123+
expected: "0 0 8080 server.subdomain",
124+
},
125+
{
126+
name: "SRV with trailing dot",
127+
input: "0 0 8080 server.example.com.",
128+
expected: "0 0 8080 server.example.com.",
129+
},
130+
}
131+
132+
for _, tt := range tests {
133+
t.Run(tt.name, func(t *testing.T) {
134+
result := domain.NormalizeSRVData(tt.input)
135+
if result != tt.expected {
136+
t.Errorf("normalizeSRVData(%q) = %q, want %q", tt.input, result, tt.expected)
137+
}
138+
})
139+
}
140+
}
141+
142+
func TestRemoveZoneDomainSuffix(t *testing.T) {
143+
tests := []struct {
144+
name string
145+
input string
146+
expected string
147+
}{
148+
{
149+
name: "simple domain",
150+
input: "server.example.com",
151+
expected: "server.example.com",
152+
},
153+
{
154+
name: "with trailing dot",
155+
input: "server.example.com.",
156+
expected: "server.example.com.",
157+
},
158+
{
159+
name: "with zone domain duplication",
160+
input: "server.example.com.zone.tld",
161+
expected: "server.example",
162+
},
163+
{
164+
name: "with zone domain duplication and trailing dot",
165+
input: "server.example.com.zone.tld.",
166+
expected: "server.example.",
167+
},
168+
{
169+
name: "with complex zone domain duplication",
170+
input: "server.example.com.subdomain.zone.tld",
171+
expected: "server.example.com",
172+
},
173+
{
174+
name: "with complex zone domain duplication and trailing dot",
175+
input: "server.example.com.subdomain.zone.tld.",
176+
expected: "server.example.com.",
177+
},
178+
{
179+
name: "no domain duplication pattern",
180+
input: "server.example.com.other.tld",
181+
expected: "server.example",
182+
},
183+
{
184+
name: "no domain duplication pattern with trailing dot",
185+
input: "server.example.com.other.tld.",
186+
expected: "server.example.",
187+
},
188+
{
189+
name: "single word",
190+
input: "server",
191+
expected: "server",
192+
},
193+
{
194+
name: "single word with trailing dot",
195+
input: "server.",
196+
expected: "server.",
197+
},
198+
}
199+
200+
for _, tt := range tests {
201+
t.Run(tt.name, func(t *testing.T) {
202+
result := domain.RemoveZoneDomainSuffix(tt.input)
203+
if result != tt.expected {
204+
t.Errorf("removeZoneDomainSuffix(%q) = %q, want %q", tt.input, result, tt.expected)
205+
}
206+
})
207+
}
208+
}

0 commit comments

Comments
 (0)