fix: invalid handling of site of DNS resource and datasources (#52)
This commit is contained in:
committed by
GitHub
parent
5d1643ed80
commit
34c495021f
@@ -85,7 +85,7 @@ func TestDNSRecord_basic(t *testing.T) {
|
||||
Config: testAccDnsRecordConfig(tc),
|
||||
Check: testAccDnsRecordCheckAttrs(tc),
|
||||
},
|
||||
pt.ImportStep(testDnsRecordResourceName),
|
||||
pt.ImportStepWithSite(testDnsRecordResourceName),
|
||||
}
|
||||
|
||||
AcceptanceTest(t, AcceptanceTestCase{
|
||||
|
||||
@@ -100,7 +100,8 @@ func (d *dnsRecordDatasource) Read(ctx context.Context, req datasource.ReadReque
|
||||
resp.Diagnostics.AddError("Filter is required", "Filter is required. Validation should prevent this from happening.")
|
||||
return
|
||||
}
|
||||
list, err := d.client.ListDNSRecord(ctx, d.client.Site)
|
||||
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
|
||||
@@ -136,6 +137,8 @@ func (d *dnsRecordDatasource) Read(ctx context.Context, req datasource.ReadReque
|
||||
resp.Diagnostics.AddError("DNS record not found", "No DNS record found")
|
||||
return
|
||||
}
|
||||
(&state.dnsRecordModel).merge(found)
|
||||
(&state.dnsRecordModel).Merge(ctx, found)
|
||||
state.SetID(found.ID)
|
||||
state.SetSite(site)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ func (d *dnsRecordsDatasource) Schema(_ context.Context, _ datasource.SchemaRequ
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Retrieves information about a all DNS records.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"site": base.SiteAttribute(),
|
||||
"result": schema.ListNestedAttribute{
|
||||
Description: "The list of DNS records.",
|
||||
Computed: true,
|
||||
@@ -63,15 +64,18 @@ func (d *dnsRecordsDatasource) Read(ctx context.Context, req datasource.ReadRequ
|
||||
return
|
||||
}
|
||||
|
||||
records, err := d.client.ListDNSRecord(ctx, d.client.Site)
|
||||
site := d.client.ResolveSite(&state)
|
||||
records, err := d.client.ListDNSRecord(ctx, site)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Failed to list DNS records", err.Error())
|
||||
return
|
||||
}
|
||||
for _, record := range records {
|
||||
state.Records = append(state.Records, &dnsRecordModel{
|
||||
Model: base.Model{
|
||||
ID: types.StringValue(record.ID),
|
||||
SiteID: types.StringValue(record.SiteID),
|
||||
Site: types.StringValue(site),
|
||||
},
|
||||
Name: types.StringValue(record.Key),
|
||||
Record: types.StringValue(record.Value),
|
||||
Enabled: types.BoolValue(record.Enabled),
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
const resourceName = "dns_record"
|
||||
|
||||
var _ base.ResourceModel = &dnsRecordModel{}
|
||||
|
||||
type dnsRecordModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
SiteID types.String `tfsdk:"site_id"`
|
||||
base.Model
|
||||
Name types.String `tfsdk:"name"`
|
||||
Record types.String `tfsdk:"record"`
|
||||
Enabled types.Bool `tfsdk:"enabled"`
|
||||
@@ -28,12 +31,25 @@ type dnsRecordDatasourceModel struct {
|
||||
}
|
||||
|
||||
type dnsRecordsDatasourceModel struct {
|
||||
Site types.String `tfsdk:"site"`
|
||||
Records []*dnsRecordModel `tfsdk:"result"`
|
||||
}
|
||||
|
||||
func (b *dnsRecordsDatasourceModel) GetSite() string {
|
||||
return b.Site.ValueString()
|
||||
}
|
||||
|
||||
func (b *dnsRecordsDatasourceModel) GetRawSite() types.String {
|
||||
return b.Site
|
||||
}
|
||||
|
||||
func (b *dnsRecordsDatasourceModel) SetSite(site string) {
|
||||
b.Site = types.StringValue(site)
|
||||
}
|
||||
|
||||
var dnsRecordDatasourceAttributes = map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site_id": base.ID("The site ID where the DNS record is located."),
|
||||
"site": base.SiteAttribute(),
|
||||
"name": schema.StringAttribute{
|
||||
Description: "DNS record name.",
|
||||
Computed: true,
|
||||
@@ -73,10 +89,9 @@ type dnsRecordFilterModel struct {
|
||||
Record types.String `tfsdk:"record"`
|
||||
}
|
||||
|
||||
func (d *dnsRecordModel) asUnifiModel() *unifi.DNSRecord {
|
||||
func (d *dnsRecordModel) AsUnifiModel(ctx context.Context) (interface{}, diag.Diagnostics) {
|
||||
return &unifi.DNSRecord{
|
||||
ID: d.ID.ValueString(),
|
||||
SiteID: d.SiteID.ValueString(),
|
||||
Key: d.Name.ValueString(),
|
||||
Value: d.Record.ValueString(),
|
||||
Enabled: d.Enabled.ValueBool(),
|
||||
@@ -85,12 +100,17 @@ func (d *dnsRecordModel) asUnifiModel() *unifi.DNSRecord {
|
||||
RecordType: d.Type.ValueString(),
|
||||
Ttl: int(d.TTL.ValueInt32()),
|
||||
Weight: int(d.Weight.ValueInt32()),
|
||||
}
|
||||
}, diag.Diagnostics{}
|
||||
}
|
||||
|
||||
func (d *dnsRecordModel) merge(other *unifi.DNSRecord) {
|
||||
func (d *dnsRecordModel) Merge(ctx context.Context, i interface{}) diag.Diagnostics {
|
||||
diags := diag.Diagnostics{}
|
||||
other, ok := i.(*unifi.DNSRecord)
|
||||
if !ok {
|
||||
diags.AddError("Invalid model type", "Expected *unifi.DNSRecord")
|
||||
return diags
|
||||
}
|
||||
d.ID = types.StringValue(other.ID)
|
||||
d.SiteID = types.StringValue(other.SiteID)
|
||||
d.Name = types.StringValue(other.Key)
|
||||
d.Record = types.StringValue(other.Value)
|
||||
d.Enabled = types.BoolValue(other.Enabled)
|
||||
@@ -99,4 +119,5 @@ func (d *dnsRecordModel) merge(other *unifi.DNSRecord) {
|
||||
d.Type = types.StringValue(other.RecordType)
|
||||
d.TTL = types.Int32Value(int32(other.Ttl))
|
||||
d.Weight = types.Int32Value(int32(other.Weight))
|
||||
return diags
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filipowm/go-unifi/unifi"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/base"
|
||||
"github.com/filipowm/terraform-provider-unifi/internal/provider/validators"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/int32validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
@@ -19,32 +19,53 @@ var (
|
||||
_ resource.Resource = &dnsRecordResource{}
|
||||
_ resource.ResourceWithConfigure = &dnsRecordResource{}
|
||||
_ resource.ResourceWithImportState = &dnsRecordResource{}
|
||||
_ resource.ResourceWithModifyPlan = &dnsRecordResource{}
|
||||
_ resource.ResourceWithConfigValidators = &dnsRecordResource{}
|
||||
_ base.Resource = &dnsRecordResource{}
|
||||
)
|
||||
|
||||
type dnsRecordResource struct {
|
||||
base.ControllerVersionValidator
|
||||
client *base.Client
|
||||
*base.GenericResource[*dnsRecordModel]
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) SetClient(client *base.Client) {
|
||||
d.client = client
|
||||
func (d *dnsRecordResource) ConfigValidators(ctx context.Context) []resource.ConfigValidator {
|
||||
return []resource.ConfigValidator{
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("A"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("AAAA"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("CNAME"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("MX"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("NS"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("PTR"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("SOA"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
validators.RequiredNoneIf(path.MatchRoot("type"), types.StringValue("TXT"), path.MatchRoot("priority"), path.MatchRoot("weight"), path.MatchRoot("port")),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) SetVersionValidator(validator base.ControllerVersionValidator) {
|
||||
d.ControllerVersionValidator = validator
|
||||
func (d *dnsRecordResource) ModifyPlan(_ context.Context, _ resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
|
||||
resp.Diagnostics.Append(d.RequireMinVersion("8.2")...)
|
||||
}
|
||||
|
||||
func NewDnsRecordResource() resource.Resource {
|
||||
return &dnsRecordResource{}
|
||||
return &dnsRecordResource{
|
||||
GenericResource: base.NewGenericResource(
|
||||
"unifi_dns_record",
|
||||
func() *dnsRecordModel { return &dnsRecordModel{} },
|
||||
base.ResourceFunctions{
|
||||
Read: func(ctx context.Context, client *base.Client, site, id string) (interface{}, error) {
|
||||
return client.GetDNSRecord(ctx, site, id)
|
||||
},
|
||||
Create: func(ctx context.Context, client *base.Client, site string, model interface{}) (interface{}, error) {
|
||||
return client.CreateDNSRecord(ctx, site, model.(*unifi.DNSRecord))
|
||||
},
|
||||
Update: func(ctx context.Context, client *base.Client, site string, model interface{}) (interface{}, error) {
|
||||
return client.UpdateDNSRecord(ctx, site, model.(*unifi.DNSRecord))
|
||||
},
|
||||
Delete: func(ctx context.Context, client *base.Client, site, id string) error {
|
||||
return client.DeleteDNSRecord(ctx, site, id)
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
base.ConfigureResource(d, req, resp)
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = fmt.Sprintf("%s_%s", req.ProviderTypeName, resourceName)
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
@@ -58,7 +79,7 @@ func (d *dnsRecordResource) Schema(_ context.Context, _ resource.SchemaRequest,
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": base.ID(),
|
||||
"site_id": base.ID("The site ID where the DNS record is located."),
|
||||
"site": base.SiteAttribute(),
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "DNS record name.",
|
||||
Required: true,
|
||||
@@ -123,134 +144,4 @@ func (d *dnsRecordResource) Schema(_ context.Context, _ resource.SchemaRequest,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) checkSupportsDnsRecords(diag *diag.Diagnostics) {
|
||||
if !d.client.SupportsDnsRecords() {
|
||||
diag.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))
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
d.checkSupportsDnsRecords(&resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
var plan dnsRecordModel
|
||||
diags := req.Plan.Get(ctx, &plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
body := plan.asUnifiModel()
|
||||
|
||||
res, err := d.client.CreateDNSRecord(ctx, d.client.Site, body)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error creating DNS record", err.Error())
|
||||
return
|
||||
}
|
||||
plan.merge(res)
|
||||
|
||||
resp.State.Set(ctx, plan)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) read(ctx context.Context, state *dnsRecordModel, diag *diag.Diagnostics) {
|
||||
res, err := d.client.GetDNSRecord(ctx, d.client.Site, state.ID.ValueString())
|
||||
if err != nil {
|
||||
diag.AddError("Error reading DNS record", err.Error())
|
||||
return
|
||||
}
|
||||
state.merge(res)
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
d.checkSupportsDnsRecords(&resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
var state dnsRecordModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
d.read(ctx, &state, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
diags = resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
d.checkSupportsDnsRecords(&resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
var plan, state dnsRecordModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
body := plan.asUnifiModel()
|
||||
|
||||
res, err := d.client.UpdateDNSRecord(ctx, d.client.Site, body)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error updating DNS record", err.Error())
|
||||
return
|
||||
}
|
||||
state.merge(res)
|
||||
diags := resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
d.checkSupportsDnsRecords(&resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
var state dnsRecordModel
|
||||
diags := req.State.Get(ctx, &state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
err := d.client.DeleteDNSRecord(ctx, d.client.Site, state.ID.ValueString())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error deleting DNS record", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dnsRecordResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||
d.checkSupportsDnsRecords(&resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
id := req.ID
|
||||
if id == "" {
|
||||
resp.Diagnostics.AddError("Invalid import ID", "The ID must be set")
|
||||
return
|
||||
}
|
||||
|
||||
state := dnsRecordModel{
|
||||
ID: types.StringValue(id),
|
||||
}
|
||||
d.read(ctx, &state, &resp.Diagnostics)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
diags := resp.State.Set(ctx, state)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user