Skip to content

Commit 48d7cc8

Browse files
committed
Add support for using the update provider for A data source
This adds a new option to use the DNS server configured for update requests also with the A and AAAA data source.
1 parent a1d4f0b commit 48d7cc8

8 files changed

+314
-25
lines changed

docs/data-sources/a_record_set.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ output "google_addrs" {
2929

3030
- `host` (String) Host to look up.
3131

32+
### Optional
33+
34+
- `use_update_server` (Boolean) Whether to use the configured update DNS server
35+
3236
### Read-Only
3337

3438
- `addrs` (List of String) A list of IP addresses. IP addresses are always sorted to avoid constant changing plans.

internal/provider/data_dns_a_record_set.go

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@ import (
1212
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1313
"github.com/hashicorp/terraform-plugin-framework/diag"
1414
"github.com/hashicorp/terraform-plugin-framework/types"
15+
"github.com/miekg/dns"
1516
)
1617

1718
var (
18-
_ datasource.DataSource = (*dnsARecordSetDataSource)(nil)
19+
_ datasource.DataSource = (*dnsARecordSetDataSource)(nil)
20+
_ datasource.DataSourceWithConfigure = (*dnsARecordSetDataSource)(nil)
1921
)
2022

2123
func NewDnsARecordSetDataSource() datasource.DataSource {
2224
return &dnsARecordSetDataSource{}
2325
}
2426

25-
type dnsARecordSetDataSource struct{}
27+
type dnsARecordSetDataSource struct {
28+
client *DNSClient
29+
}
2630

2731
func (d *dnsARecordSetDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
2832
resp.TypeName = req.ProviderTypeName + "_a_record_set"
@@ -36,6 +40,10 @@ func (d *dnsARecordSetDataSource) Schema(ctx context.Context, req datasource.Sch
3640
Required: true,
3741
Description: "Host to look up.",
3842
},
43+
"use_update_server": schema.BoolAttribute{
44+
Optional: true,
45+
Description: "Whether to use the configured update DNS server",
46+
},
3947
"addrs": schema.ListAttribute{
4048
ElementType: types.StringType,
4149
Computed: true,
@@ -49,6 +57,24 @@ func (d *dnsARecordSetDataSource) Schema(ctx context.Context, req datasource.Sch
4957
}
5058
}
5159

60+
func (d *dnsARecordSetDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
61+
if req.ProviderData == nil {
62+
return
63+
}
64+
65+
client, ok := req.ProviderData.(*DNSClient)
66+
if !ok {
67+
resp.Diagnostics.AddError(
68+
"Unexpected Resource Configure Type",
69+
fmt.Sprintf("Expected *DNSClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
70+
)
71+
72+
return
73+
}
74+
75+
d.client = client
76+
}
77+
5278
func (d *dnsARecordSetDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
5379
var config aRecordSetConfig
5480

@@ -57,16 +83,42 @@ func (d *dnsARecordSetDataSource) Read(ctx context.Context, req datasource.ReadR
5783
return
5884
}
5985

60-
host := config.Host.ValueString()
61-
a, _, err := lookupIP(host)
62-
if err != nil {
63-
resp.Diagnostics.AddError(fmt.Sprintf("error looking up A records for %q: ", host), err.Error())
86+
if config.UseUpdateServer.ValueBool() && d.client == nil {
87+
resp.Diagnostics.AddError("use_update_server enabled, but no update server configured", "If you set use_update_server to true, an update server needs to be configured for the provider")
6488
return
6589
}
66-
sort.Strings(a)
90+
91+
host := config.Host.ValueString()
92+
93+
answers := []string{}
94+
if !config.UseUpdateServer.ValueBool() || d.client == nil {
95+
var err error
96+
answers, _, err = lookupIP(host)
97+
if err != nil {
98+
resp.Diagnostics.AddError(fmt.Sprintf("error looking up A records for %q: ", host), err.Error())
99+
return
100+
}
101+
} else {
102+
records, diags := resourceDnsRead_framework_flags(dnsConfig{Name: host}, d.client, dns.TypeA, dns.MsgHdr{RecursionDesired: true})
103+
resp.Diagnostics.Append(diags...)
104+
if diags.HasError() {
105+
return
106+
}
107+
108+
for _, record := range records {
109+
addr, _, err := getAVal(record)
110+
if err != nil {
111+
resp.Diagnostics.AddError("Error querying DNS record:", err.Error())
112+
return
113+
}
114+
115+
answers = append(answers, addr)
116+
}
117+
}
118+
sort.Strings(answers)
67119

68120
var convertDiags diag.Diagnostics
69-
config.Addrs, convertDiags = types.ListValueFrom(ctx, config.Addrs.ElementType(ctx), a)
121+
config.Addrs, convertDiags = types.ListValueFrom(ctx, config.Addrs.ElementType(ctx), answers)
70122
resp.Diagnostics.Append(convertDiags...)
71123
if resp.Diagnostics.HasError() {
72124
return
@@ -77,7 +129,8 @@ func (d *dnsARecordSetDataSource) Read(ctx context.Context, req datasource.ReadR
77129
}
78130

79131
type aRecordSetConfig struct {
80-
ID types.String `tfsdk:"id"`
81-
Host types.String `tfsdk:"host"`
82-
Addrs types.List `tfsdk:"addrs"`
132+
ID types.String `tfsdk:"id"`
133+
Host types.String `tfsdk:"host"`
134+
UseUpdateServer types.Bool `tfsdk:"use_update_server"`
135+
Addrs types.List `tfsdk:"addrs"`
83136
}

internal/provider/data_dns_a_record_set_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,27 @@ data "dns_a_record_set" "test" {
3030
},
3131
})
3232
}
33+
34+
func TestAccDataDnsARecordSet_BasicUpdateProvider(t *testing.T) {
35+
recordName := "data.dns_a_record_set.test"
36+
37+
resource.Test(t, resource.TestCase{
38+
PreCheck: func() { testAccPreCheck(t) },
39+
ProtoV5ProviderFactories: testProtoV5ProviderFactories,
40+
Steps: []resource.TestStep{
41+
{
42+
Config: `
43+
data "dns_a_record_set" "test" {
44+
host = "terraform-provider-dns-a.hashicorptest.com"
45+
use_update_server = true
46+
}
47+
`,
48+
Check: resource.ComposeAggregateTestCheckFunc(
49+
resource.TestCheckResourceAttr(recordName, "addrs.#", "1"),
50+
resource.TestCheckTypeSetElemAttr(recordName, "addrs.*", "127.0.0.1"),
51+
resource.TestCheckResourceAttr(recordName, "id", "terraform-provider-dns-a.hashicorptest.com"),
52+
),
53+
},
54+
},
55+
})
56+
}

internal/provider/data_dns_aaaa_record_set.go

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@ import (
1212
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1313
"github.com/hashicorp/terraform-plugin-framework/diag"
1414
"github.com/hashicorp/terraform-plugin-framework/types"
15+
"github.com/miekg/dns"
1516
)
1617

1718
var (
18-
_ datasource.DataSource = (*dnsAAAARecordSetDataSource)(nil)
19+
_ datasource.DataSource = (*dnsAAAARecordSetDataSource)(nil)
20+
_ datasource.DataSourceWithConfigure = (*dnsAAAARecordSetDataSource)(nil)
1921
)
2022

2123
func NewDnsAAAARecordSetDataSource() datasource.DataSource {
2224
return &dnsAAAARecordSetDataSource{}
2325
}
2426

25-
type dnsAAAARecordSetDataSource struct{}
27+
type dnsAAAARecordSetDataSource struct {
28+
client *DNSClient
29+
}
2630

2731
func (d *dnsAAAARecordSetDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
2832
resp.TypeName = req.ProviderTypeName + "_aaaa_record_set"
@@ -36,6 +40,10 @@ func (d *dnsAAAARecordSetDataSource) Schema(ctx context.Context, req datasource.
3640
Required: true,
3741
Description: "Host to look up.",
3842
},
43+
"use_update_server": schema.BoolAttribute{
44+
Optional: true,
45+
Description: "Whether to use the configured update DNS server",
46+
},
3947
"addrs": schema.ListAttribute{
4048
ElementType: types.StringType,
4149
Computed: true,
@@ -49,6 +57,24 @@ func (d *dnsAAAARecordSetDataSource) Schema(ctx context.Context, req datasource.
4957
}
5058
}
5159

60+
func (d *dnsAAAARecordSetDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
61+
if req.ProviderData == nil {
62+
return
63+
}
64+
65+
client, ok := req.ProviderData.(*DNSClient)
66+
if !ok {
67+
resp.Diagnostics.AddError(
68+
"Unexpected Resource Configure Type",
69+
fmt.Sprintf("Expected *DNSClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
70+
)
71+
72+
return
73+
}
74+
75+
d.client = client
76+
}
77+
5278
func (d *dnsAAAARecordSetDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
5379
var config aRecordSetConfig
5480

@@ -57,16 +83,42 @@ func (d *dnsAAAARecordSetDataSource) Read(ctx context.Context, req datasource.Re
5783
return
5884
}
5985

60-
host := config.Host.ValueString()
61-
_, aaaa, err := lookupIP(host)
62-
if err != nil {
63-
resp.Diagnostics.AddError(fmt.Sprintf("error looking up AAAA records for %q: ", host), err.Error())
86+
if config.UseUpdateServer.ValueBool() && d.client == nil {
87+
resp.Diagnostics.AddError("use_update_server enabled, but no update server configured", "If you set use_update_server to true, an update server needs to be configured for the provider")
6488
return
6589
}
66-
sort.Strings(aaaa)
90+
91+
host := config.Host.ValueString()
92+
93+
answers := []string{}
94+
if !config.UseUpdateServer.ValueBool() || d.client == nil {
95+
var err error
96+
_, answers, err = lookupIP(host)
97+
if err != nil {
98+
resp.Diagnostics.AddError(fmt.Sprintf("error looking up AAAA records for %q: ", host), err.Error())
99+
return
100+
}
101+
} else {
102+
records, diags := resourceDnsRead_framework_flags(dnsConfig{Name: host}, d.client, dns.TypeAAAA, dns.MsgHdr{RecursionDesired: true})
103+
resp.Diagnostics.Append(diags...)
104+
if diags.HasError() {
105+
return
106+
}
107+
108+
for _, record := range records {
109+
addr, _, err := getAAAAVal(record)
110+
if err != nil {
111+
resp.Diagnostics.AddError("Error querying DNS record:", err.Error())
112+
return
113+
}
114+
115+
answers = append(answers, addr)
116+
}
117+
}
118+
sort.Strings(answers)
67119

68120
var convertDiags diag.Diagnostics
69-
config.Addrs, convertDiags = types.ListValueFrom(ctx, config.Addrs.ElementType(ctx), aaaa)
121+
config.Addrs, convertDiags = types.ListValueFrom(ctx, config.Addrs.ElementType(ctx), answers)
70122
resp.Diagnostics.Append(convertDiags...)
71123
if resp.Diagnostics.HasError() {
72124
return

internal/provider/data_dns_aaaa_record_set_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,27 @@ data "dns_aaaa_record_set" "test" {
3030
},
3131
})
3232
}
33+
34+
func TestAccDataDnsAAAARecordSet_BasicUpdateServer(t *testing.T) {
35+
recordName := "data.dns_aaaa_record_set.test"
36+
37+
resource.Test(t, resource.TestCase{
38+
PreCheck: func() { testAccPreCheck(t) },
39+
ProtoV5ProviderFactories: testProtoV5ProviderFactories,
40+
Steps: []resource.TestStep{
41+
{
42+
Config: `
43+
data "dns_aaaa_record_set" "test" {
44+
host = "terraform-provider-dns-aaaa.hashicorptest.com"
45+
use_update_server = true
46+
}
47+
`,
48+
Check: resource.ComposeAggregateTestCheckFunc(
49+
resource.TestCheckResourceAttr(recordName, "addrs.#", "1"),
50+
resource.TestCheckTypeSetElemAttr(recordName, "addrs.*", "::1"),
51+
resource.TestCheckResourceAttr(recordName, "id", "terraform-provider-dns-aaaa.hashicorptest.com"),
52+
),
53+
},
54+
},
55+
})
56+
}

internal/provider/provider.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,6 @@ func exchange(msg *dns.Msg, tsig bool, client *DNSClient) (*dns.Msg, error) {
489489
keyname = k
490490
}
491491

492-
msg.RecursionDesired = false
493-
494492
if tsig && keyname != "" {
495493
msg.SetTsig(keyname, keyalgo, 300, time.Now().Unix())
496494
}

internal/provider/provider_framework.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,13 @@ func (p *dnsProvider) Configure(ctx context.Context, req provider.ConfigureReque
325325
keytab: keytab,
326326
}
327327

328-
resp.ResourceData, configErr = config.Client(ctx)
328+
client, configErr := config.Client(ctx)
329329
if configErr != nil {
330330
resp.Diagnostics.AddError("Error initializing DNS Client:", configErr.Error())
331331
}
332+
333+
resp.ResourceData = client
334+
resp.DataSourceData = client
332335
}
333336

334337
func (p *dnsProvider) Resources(ctx context.Context) []func() resource.Resource {
@@ -496,11 +499,16 @@ func resourceFQDN_framework(config dnsConfig) string {
496499
}
497500

498501
func resourceDnsRead_framework(config dnsConfig, client *DNSClient, rrType uint16) ([]dns.RR, diag.Diagnostics) {
502+
return resourceDnsRead_framework_flags(config, client, rrType, dns.MsgHdr{RecursionDesired: false})
503+
}
504+
505+
func resourceDnsRead_framework_flags(config dnsConfig, client *DNSClient, rrType uint16, flags dns.MsgHdr) ([]dns.RR, diag.Diagnostics) {
499506
var diags diag.Diagnostics
500507
fqdn := resourceFQDN_framework(config)
501508

502509
msg := new(dns.Msg)
503510
msg.SetQuestion(fqdn, rrType)
511+
msg.RecursionDesired = flags.RecursionDesired
504512

505513
r, err := exchange(msg, true, client)
506514
if err != nil {

0 commit comments

Comments
 (0)