diff --git a/internal/provider/acctest/datasource_dns_record_test.go b/internal/provider/acctest/datasource_dns_record_test.go index 4344b24..4831e06 100644 --- a/internal/provider/acctest/datasource_dns_record_test.go +++ b/internal/provider/acctest/datasource_dns_record_test.go @@ -63,7 +63,7 @@ func TestDNSRecordDataSource_basic(t *testing.T) { } var ( - dnsDataSourceFilterErrorRegex = regexp.MustCompile(`[filter.name,filter.record]`) + dnsDataSourceFilterErrorRegex = regexp.MustCompile(`[name,record]`) ) func TestDNSRecordDataSource_errorWithoutFilter(t *testing.T) { @@ -89,9 +89,7 @@ func testAccDnsRecordDataSourceConfig(tc dnsRecordTestCase, filterByName bool) s return fmt.Sprintf(` data "unifi_dns_record" "test" { - filter { - %s - } + %s depends_on = [unifi_dns_record.test] }`, filter) } @@ -99,8 +97,5 @@ data "unifi_dns_record" "test" { func testAccDnsRecordDataSourceWithoutFilter() string { return ` data "unifi_dns_record" "test" { - filter { - - } }` } diff --git a/internal/provider/dns/datasource_dns_record.go b/internal/provider/dns/datasource_dns_record.go index 3590caa..e134eac 100644 --- a/internal/provider/dns/datasource_dns_record.go +++ b/internal/provider/dns/datasource_dns_record.go @@ -8,11 +8,9 @@ import ( "github.com/filipowm/terraform-provider-unifi/internal/provider/base" "github.com/filipowm/terraform-provider-unifi/internal/utils" "github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator" - "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) var ( @@ -39,8 +37,8 @@ func NewDnsRecordDatasource() datasource.DataSource { func (d *dnsRecordDatasource) ConfigValidators(_ context.Context) []datasource.ConfigValidator { return []datasource.ConfigValidator{ datasourcevalidator.ExactlyOneOf( - path.MatchRoot("filter").AtName("name"), - path.MatchRoot("filter").AtName("record"), + path.MatchRoot("name"), + path.MatchRoot("record"), ), } } @@ -67,26 +65,6 @@ func (d *dnsRecordDatasource) Schema(_ context.Context, _ datasource.SchemaReque "This data source allows you to look up DNS records by either their name or record content. " + "It's particularly useful for validating existing DNS configurations or referencing DNS records in other resources.", Attributes: dnsRecordDatasourceAttributes, - Blocks: map[string]schema.Block{ - "filter": schema.SingleNestedBlock{ - Description: "Filter criteria to identify the specific DNS record. You must specify either the record name or content.", - Validators: []validator.Object{ - objectvalidator.IsRequired(), - }, - Attributes: map[string]schema.Attribute{ - "name": schema.StringAttribute{ - Description: "The DNS record name to look up (e.g., 'example.com', 'subdomain.example.com'). " + - "Cannot be specified together with `record`.", - Optional: true, - }, - "record": schema.StringAttribute{ - Description: "The DNS record content to look up (e.g., IP address for A records, target hostname for CNAME records). " + - "Cannot be specified together with `name`.", - Optional: true, - }, - }, - }, - }, } } @@ -94,19 +72,15 @@ func (d *dnsRecordDatasource) Read(ctx context.Context, req datasource.ReadReque if !d.client.SupportsDnsRecords() { resp.Diagnostics.AddError("DNS Records are not supported", fmt.Sprintf("The Unifi controller in version %q does not support DNS records. Required controller version: %q", d.client.Version, base.ControllerVersionDnsRecords)) } - var state dnsRecordDatasourceModel + var state dnsRecordModel resp.Diagnostics.Append(req.Config.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { return } - if state.Filter == nil { - // TODO remove after testing validation - resp.Diagnostics.AddError("Filter is required", "Filter is required. Validation should prevent this from happening.") - return - } site := d.client.ResolveSite(&state) + list, err := d.client.ListDNSRecord(ctx, site) + if err != nil { resp.Diagnostics.AddError("Failed to list DNS records", err.Error()) return @@ -115,35 +89,40 @@ func (d *dnsRecordDatasource) Read(ctx context.Context, req datasource.ReadReque resp.Diagnostics.AddError("DNS record not found", "No DNS record found") return } + var nameFilter, recordFilter string - if utils.IsStringValueNotEmpty(state.Filter.Name) { - nameFilter = state.Filter.Name.ValueString() + if utils.IsStringValueNotEmpty(state.Name) { + nameFilter = state.Name.ValueString() } - if utils.IsStringValueNotEmpty(state.Filter.Record) { - recordFilter = state.Filter.Record.ValueString() + if utils.IsStringValueNotEmpty(state.Record) { + recordFilter = state.Record.ValueString() } if nameFilter != "" && recordFilter != "" { // TODO remove after testing validation resp.Diagnostics.AddError("Filter is invalid", "Only one of 'name' or 'record' can be specified. Validation should prevent this from happening.") return } - var found *unifi.DNSRecord + var found []*unifi.DNSRecord for _, record := range list { if nameFilter != "" && record.Key == nameFilter { - found = &record + found = append(found, &record) break } if recordFilter != "" && record.Value == recordFilter { - found = &record + found = append(found, &record) break } } - if found == nil { + + if len(found) == 0 { resp.Diagnostics.AddError("DNS record not found", "No DNS record found") return + } else if len(found) > 1 { + resp.Diagnostics.AddError("Multiple DNS records found", "More than one DNS record found") + return } - (&state.dnsRecordModel).Merge(ctx, found) - state.SetID(found.ID) + (&state).Merge(ctx, found[0]) + state.SetID(found[0].ID) state.SetSite(site) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } diff --git a/internal/provider/dns/dns_record_model.go b/internal/provider/dns/dns_record_model.go index fd1c6a1..6d6c808 100644 --- a/internal/provider/dns/dns_record_model.go +++ b/internal/provider/dns/dns_record_model.go @@ -4,8 +4,11 @@ import ( "context" "github.com/filipowm/go-unifi/unifi" "github.com/filipowm/terraform-provider-unifi/internal/provider/base" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -25,11 +28,6 @@ type dnsRecordModel struct { Weight types.Int32 `tfsdk:"weight"` } -type dnsRecordDatasourceModel struct { - dnsRecordModel - Filter *dnsRecordFilterModel `tfsdk:"filter"` -} - type dnsRecordsDatasourceModel struct { Site types.String `tfsdk:"site"` Records []*dnsRecordModel `tfsdk:"result"` @@ -52,11 +50,19 @@ var dnsRecordDatasourceAttributes = map[string]schema.Attribute{ "site": base.SiteAttribute(), "name": schema.StringAttribute{ Description: "DNS record name.", + Optional: true, Computed: true, + Validators: []validator.String{ + stringvalidator.ConflictsWith(path.MatchRoot("record")), + }, }, "record": schema.StringAttribute{ Description: "DNS record content.", + Optional: true, Computed: true, + Validators: []validator.String{ + stringvalidator.ConflictsWith(path.MatchRoot("name")), + }, }, "enabled": schema.BoolAttribute{ Description: "Whether the DNS record is enabled.", @@ -84,12 +90,7 @@ var dnsRecordDatasourceAttributes = map[string]schema.Attribute{ }, } -type dnsRecordFilterModel struct { - Name types.String `tfsdk:"name"` - Record types.String `tfsdk:"record"` -} - -func (d *dnsRecordModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnostics) { +func (d *dnsRecordModel) AsUnifiModel(_ context.Context) (interface{}, diag.Diagnostics) { return &unifi.DNSRecord{ ID: d.ID.ValueString(), Key: d.Name.ValueString(), @@ -103,7 +104,7 @@ func (d *dnsRecordModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Di }, diag.Diagnostics{} } -func (d *dnsRecordModel) Merge(ctx context.Context, i interface{}) diag.Diagnostics { +func (d *dnsRecordModel) Merge(_ context.Context, i interface{}) diag.Diagnostics { diags := diag.Diagnostics{} other, ok := i.(*unifi.DNSRecord) if !ok {