diff --git a/internal/framework/resources/zone_record_resource.go b/internal/framework/resources/zone_record_resource.go index 18de2613..1ac73130 100644 --- a/internal/framework/resources/zone_record_resource.go +++ b/internal/framework/resources/zone_record_resource.go @@ -39,16 +39,17 @@ type ZoneRecordResource struct { // ZoneRecordResourceModel describes the resource data model. type ZoneRecordResourceModel struct { - ZoneName types.String `tfsdk:"zone_name"` - ZoneId types.String `tfsdk:"zone_id"` - Name types.String `tfsdk:"name"` - QualifiedName types.String `tfsdk:"qualified_name"` - Type types.String `tfsdk:"type"` - Regions types.List `tfsdk:"regions"` - Value types.String `tfsdk:"value"` - TTL types.Int64 `tfsdk:"ttl"` - Priority types.Int64 `tfsdk:"priority"` - Id types.Int64 `tfsdk:"id"` + ZoneName types.String `tfsdk:"zone_name"` + ZoneId types.String `tfsdk:"zone_id"` + Name types.String `tfsdk:"name"` + QualifiedName types.String `tfsdk:"qualified_name"` + Type types.String `tfsdk:"type"` + Regions types.List `tfsdk:"regions"` + Value types.String `tfsdk:"value"` + ValueNormalized types.String `tfsdk:"value_normalized"` + TTL types.Int64 `tfsdk:"ttl"` + Priority types.Int64 `tfsdk:"priority"` + Id types.Int64 `tfsdk:"id"` } func (r *ZoneRecordResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { @@ -89,6 +90,9 @@ func (r *ZoneRecordResource) Schema(_ context.Context, _ resource.SchemaRequest, "value": schema.StringAttribute{ Required: true, }, + "value_normalized": schema.StringAttribute{ + Computed: true, + }, "ttl": schema.Int64Attribute{ Optional: true, Computed: true, @@ -245,6 +249,12 @@ func (r *ZoneRecordResource) Read(ctx context.Context, req resource.ReadRequest, record = *response.Data } + if record.Content != data.ValueNormalized.ValueString() { + // If the record content has changed, we need to update the record in the remote + tflog.Debug(ctx, "DNSimple Zone Record content changed") + data.Value = types.StringValue(record.Content) + } + r.updateModelFromAPIResponse(&record, data) // Save updated data into Terraform state @@ -353,7 +363,7 @@ func (r *ZoneRecordResource) updateModelFromAPIResponse(record *dnsimple.ZoneRec data.ZoneId = types.StringValue(record.ZoneID) data.Name = types.StringValue(record.Name) data.Type = types.StringValue(record.Type) - data.Value = types.StringValue(record.Content) + data.ValueNormalized = types.StringValue(record.Content) data.TTL = types.Int64Value(int64(record.TTL)) data.Priority = types.Int64Value(int64(record.Priority)) diff --git a/internal/framework/resources/zone_record_resource_test.go b/internal/framework/resources/zone_record_resource_test.go index 177ce38c..23a7d78f 100644 --- a/internal/framework/resources/zone_record_resource_test.go +++ b/internal/framework/resources/zone_record_resource_test.go @@ -93,6 +93,54 @@ func TestAccZoneRecordResourceWithPriority(t *testing.T) { }) } +func TestAccZoneRecordResourceWithTXT(t *testing.T) { + domainName := os.Getenv("DNSIMPLE_DOMAIN") + resourceName := "dnsimple_zone_record.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { test_utils.TestAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + CheckDestroy: testAccCheckZoneRecordResourceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccZoneRecordResourceTXTConfig(domainName, "test value for TXT record"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "zone_name", domainName), + resource.TestCheckResourceAttr(resourceName, "qualified_name", "terraform."+domainName), + resource.TestCheckResourceAttr(resourceName, "value", "test value for TXT record"), + resource.TestCheckResourceAttr(resourceName, "ttl", "3600"), + resource.TestCheckResourceAttrSet(resourceName, "id"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + +func TestAccZoneRecordResourceWithNormalizedTXT(t *testing.T) { + domainName := os.Getenv("DNSIMPLE_DOMAIN") + resourceName := "dnsimple_zone_record.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { test_utils.TestAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + CheckDestroy: testAccCheckZoneRecordResourceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccZoneRecordResourceTXTConfig(domainName, "\"test value for TXT record\""), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "zone_name", domainName), + resource.TestCheckResourceAttr(resourceName, "qualified_name", "terraform."+domainName), + resource.TestCheckResourceAttr(resourceName, "value", "\"test value for TXT record\""), + resource.TestCheckResourceAttr(resourceName, "ttl", "3600"), + resource.TestCheckResourceAttrSet(resourceName, "id"), + ), + }, + // Delete testing automatically occurs in TestCase + }, + }) +} + func TestAccZoneRecordResourceWithPrefetch(t *testing.T) { domainName := os.Getenv("DNSIMPLE_DOMAIN") resourceName := "dnsimple_zone_record.test" @@ -241,6 +289,17 @@ func testAccCheckZoneRecordExists(n string, record *dnsimple.ZoneRecord) resourc } } +func testAccZoneRecordResourceTXTConfig(domainName string, value string) string { + return fmt.Sprintf(` +resource "dnsimple_zone_record" "test" { + zone_name = %[1]q + + name = "terraform" + value = %[2]q + type = "TXT" +}`, domainName, value) +} + func testAccZoneRecordResourcePriorityConfig(domainName string) string { return fmt.Sprintf(` resource "dnsimple_zone_record" "test" {