diff --git a/azurerm/internal/services/privatedns/registration.go b/azurerm/internal/services/privatedns/registration.go index 37b46c37e956..2cc589a51100 100644 --- a/azurerm/internal/services/privatedns/registration.go +++ b/azurerm/internal/services/privatedns/registration.go @@ -33,6 +33,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_private_dns_mx_record": resourceArmPrivateDnsMxRecord(), "azurerm_private_dns_ptr_record": resourceArmPrivateDnsPtrRecord(), "azurerm_private_dns_srv_record": resourceArmPrivateDnsSrvRecord(), + "azurerm_private_dns_txt_record": resourceArmPrivateDnsTxtRecord(), "azurerm_private_dns_zone_virtual_network_link": resourceArmPrivateDnsZoneVirtualNetworkLink(), } } diff --git a/azurerm/internal/services/privatedns/resource_arm_private_dns_txt_record.go b/azurerm/internal/services/privatedns/resource_arm_private_dns_txt_record.go new file mode 100644 index 000000000000..1aa7a69e6216 --- /dev/null +++ b/azurerm/internal/services/privatedns/resource_arm_private_dns_txt_record.go @@ -0,0 +1,241 @@ +package privatedns + +import ( + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmPrivateDnsTxtRecord() *schema.Resource { + return &schema.Resource{ + Create: resourceArmPrivateDnsTxtRecordCreateUpdate, + Read: resourceArmPrivateDnsTxtRecordRead, + Update: resourceArmPrivateDnsTxtRecordCreateUpdate, + Delete: resourceArmPrivateDnsTxtRecordDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + // lower-cased due to the broken API https://github.com/Azure/azure-rest-api-specs/issues/6641 + ValidateFunc: validate.LowerCasedString, + }, + + // TODO: make this case sensitive once the API's fixed https://github.com/Azure/azure-rest-api-specs/issues/6641 + "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), + + "zone_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "record": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + }, + }, + }, + + "ttl": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 2147483647), + }, + + "fqdn": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmPrivateDnsTxtRecordCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).PrivateDns.RecordSetsClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + zoneName := d.Get("zone_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, zoneName, privatedns.TXT, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Private DNS TXT Record %q (Zone %q / Resource Group %q): %s", name, zoneName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_private_dns_txt_record", *existing.ID) + } + } + + parameters := privatedns.RecordSet{ + Name: &name, + RecordSetProperties: &privatedns.RecordSetProperties{ + Metadata: tags.Expand(d.Get("tags").(map[string]interface{})), + TTL: utils.Int64(int64(d.Get("ttl").(int))), + TxtRecords: expandAzureRmPrivateDnsTxtRecords(d), + }, + } + + if _, err := client.CreateOrUpdate(ctx, resGroup, zoneName, privatedns.TXT, name, parameters, "", ""); err != nil { + return fmt.Errorf("Error creating/updating Private DNS TXT Record %q (Zone %q / Resource Group %q): %s", name, zoneName, resGroup, err) + } + + resp, err := client.Get(ctx, resGroup, zoneName, privatedns.TXT, name) + if err != nil { + return fmt.Errorf("Error retrieving Private DNS TXT Record %q (Zone %q / Resource Group %q): %s", name, zoneName, resGroup, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read Private DNS TXT Record %s (resource group %s) ID", name, resGroup) + } + + d.SetId(*resp.ID) + + return resourceArmPrivateDnsTxtRecordRead(d, meta) +} + +func resourceArmPrivateDnsTxtRecordRead(d *schema.ResourceData, meta interface{}) error { + dnsClient := meta.(*clients.Client).PrivateDns.RecordSetsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resGroup := id.ResourceGroup + name := id.Path["TXT"] + zoneName := id.Path["privateDnsZones"] + + resp, err := dnsClient.Get(ctx, resGroup, zoneName, privatedns.TXT, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error reading Private DNS TXT record %s: %+v", name, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resGroup) + d.Set("zone_name", zoneName) + d.Set("ttl", resp.TTL) + d.Set("fqdn", resp.Fqdn) + + if err := d.Set("record", flattenAzureRmPrivateDnsTxtRecords(resp.TxtRecords)); err != nil { + return fmt.Errorf("setting `record`: %s", err) + } + + return tags.FlattenAndSet(d, resp.Metadata) +} + +func resourceArmPrivateDnsTxtRecordDelete(d *schema.ResourceData, meta interface{}) error { + dnsClient := meta.(*clients.Client).PrivateDns.RecordSetsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resGroup := id.ResourceGroup + name := id.Path["TXT"] + zoneName := id.Path["privateDnsZones"] + + _, err = dnsClient.Delete(ctx, resGroup, zoneName, privatedns.TXT, name, "") + if err != nil { + return fmt.Errorf("Error deleting Private DNS TXT Record %s: %+v", name, err) + } + + return nil +} + +func flattenAzureRmPrivateDnsTxtRecords(records *[]privatedns.TxtRecord) []map[string]interface{} { + results := make([]map[string]interface{}, 0) + + if records != nil { + for _, record := range *records { + txtRecord := make(map[string]interface{}) + + if v := record.Value; v != nil { + value := strings.Join(*v, "") + txtRecord["value"] = value + } + + results = append(results, txtRecord) + } + } + + return results +} + +func expandAzureRmPrivateDnsTxtRecords(d *schema.ResourceData) *[]privatedns.TxtRecord { + recordStrings := d.Get("record").(*schema.Set).List() + records := make([]privatedns.TxtRecord, len(recordStrings)) + + segmentLen := 254 + for i, v := range recordStrings { + if v == nil { + continue + } + + record := v.(map[string]interface{}) + v := record["value"].(string) + + var value []string + for len(v) > segmentLen { + value = append(value, v[:segmentLen]) + v = v[segmentLen:] + } + value = append(value, v) + + txtRecord := privatedns.TxtRecord{ + Value: &value, + } + + records[i] = txtRecord + } + + return &records +} diff --git a/azurerm/internal/services/privatedns/tests/resource_arm_private_dns_txt_record_test.go b/azurerm/internal/services/privatedns/tests/resource_arm_private_dns_txt_record_test.go new file mode 100644 index 000000000000..e62c9330f603 --- /dev/null +++ b/azurerm/internal/services/privatedns/tests/resource_arm_private_dns_txt_record_test.go @@ -0,0 +1,345 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" +) + +func TestAccAzureRMPrivateDnsTxtRecord_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_txt_record", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMPrivateDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateDnsTxtRecord_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + resource.TestCheckResourceAttrSet(data.ResourceName, "fqdn"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMPrivateDnsTxtRecord_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + data := acceptance.BuildTestData(t, "azurerm_private_dns_txt_record", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMPrivateDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateDnsTxtRecord_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMPrivateDnsTxtRecord_requiresImport), + }, + }) +} + +func TestAccAzureRMPrivateDnsTxtRecord_updateRecords(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_txt_record", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMPrivateDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateDnsTxtRecord_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "record.#", "2"), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMPrivateDnsTxtRecord_updateRecords(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "record.#", "3"), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMPrivateDnsTxtRecord_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "record.#", "2"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMPrivateDnsTxtRecord_withTags(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_private_dns_txt_record", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMPrivateDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMPrivateDnsTxtRecord_withTags(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "2"), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMPrivateDnsTxtRecord_withTagsUpdate(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPrivateDnsTxtRecordExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "1"), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMPrivateDnsTxtRecordExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acceptance.AzureProvider.Meta().(*clients.Client).PrivateDns.RecordSetsClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + txtName := rs.Primary.Attributes["name"] + zoneName := rs.Primary.Attributes["zone_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Private DNS TXT record: %s", txtName) + } + + resp, err := conn.Get(ctx, resourceGroup, zoneName, privatedns.TXT, txtName) + if err != nil { + return fmt.Errorf("Bad: Get TXT RecordSet: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Private DNS TXT record %s (resource group: %s) does not exist", txtName, resourceGroup) + } + + return nil + } +} + +func testCheckAzureRMPrivateDnsTxtRecordDestroy(s *terraform.State) error { + conn := acceptance.AzureProvider.Meta().(*clients.Client).PrivateDns.RecordSetsClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_private_dns_txt_record" { + continue + } + + txtName := rs.Primary.Attributes["name"] + zoneName := rs.Primary.Attributes["zone_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(ctx, resourceGroup, zoneName, privatedns.TXT, txtName) + + if err != nil { + if resp.StatusCode == http.StatusNotFound { + return nil + } + + return err + } + + return fmt.Errorf("Private DNS TXT record still exists:\n%#v", resp.RecordSetProperties) + } + + return nil +} + +func testAccAzureRMPrivateDnsTxtRecord_basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-prvdns-%d" + location = "%s" +} + +resource "azurerm_private_dns_zone" "test" { + name = "testzone%d.com" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_private_dns_txt_record" "test" { + name = "testacctxt%d" + resource_group_name = azurerm_resource_group.test.name + zone_name = azurerm_private_dns_zone.test.name + ttl = 300 + + record { + value = "Quick brown fox" + } + + record { + value = "A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMPrivateDnsTxtRecord_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMPrivateDnsTxtRecord_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_private_dns_txt_record" "import" { + name = azurerm_private_dns_txt_record.test.name + resource_group_name = azurerm_private_dns_txt_record.test.resource_group_name + zone_name = azurerm_private_dns_txt_record.test.zone_name + ttl = 300 + + record { + value = "Quick brown fox" + } + + record { + value = "A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......" + } +} +`, template) +} + +func testAccAzureRMPrivateDnsTxtRecord_updateRecords(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-prvdns-%d" + location = "%s" +} + +resource "azurerm_private_dns_zone" "test" { + name = "testzone%d.com" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_private_dns_txt_record" "test" { + name = "test%d" + resource_group_name = azurerm_resource_group.test.name + zone_name = azurerm_private_dns_zone.test.name + ttl = 300 + + record { + value = "Quick brown fox" + } + + record { + value = "A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......" + } + + record { + value = "I'm a record too'" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMPrivateDnsTxtRecord_withTags(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-prvdns-%d" + location = "%s" +} + +resource "azurerm_private_dns_zone" "test" { + name = "testzone%d.com" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_private_dns_txt_record" "test" { + name = "test%d" + resource_group_name = azurerm_resource_group.test.name + zone_name = azurerm_private_dns_zone.test.name + ttl = 300 + + record { + value = "Quick brown fox" + } + + record { + value = "A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......" + } + + tags = { + environment = "Production" + cost_center = "MSFT" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMPrivateDnsTxtRecord_withTagsUpdate(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-prvdns-%d" + location = "%s" +} + +resource "azurerm_private_dns_zone" "test" { + name = "testzone%d.com" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_private_dns_txt_record" "test" { + name = "test%d" + resource_group_name = azurerm_resource_group.test.name + zone_name = azurerm_private_dns_zone.test.name + ttl = 300 + + record { + value = "Quick brown fox" + } + + record { + value = "A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......A long text......" + } + + tags = { + environment = "staging" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 82495facfd3a..0145ba90d2d5 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -2138,6 +2138,9 @@
  • azurerm_private_dns_srv_record
  • +
  • + azurerm_private_dns_txt_record +
  • azurerm_private_dns_zone
  • diff --git a/website/docs/r/private_dns_txt_record.html.markdown b/website/docs/r/private_dns_txt_record.html.markdown new file mode 100644 index 000000000000..09e78337ff71 --- /dev/null +++ b/website/docs/r/private_dns_txt_record.html.markdown @@ -0,0 +1,84 @@ +--- +subcategory: "Private DNS" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_private_dns_txt_record" +description: |- + Manages a Private DNS TXT Record. +--- + +# azurerm_private_dns_txtrecord + +Enables you to manage DNS TXT Records within Azure Private DNS. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "acceptanceTestResourceGroup1" + location = "West US" +} + +resource "azurerm_private_dns_zone" "test" { + name = "contoso.com" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_private_dns_txt_record" "test" { + name = "test" + resource_group_name = azurerm_resource_group.test.name + zone_name = azurerm_private_dns_zone.test.name + ttl = 300 + + record { + value = "v=spf1 mx ~all" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the DNS TXT Record. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created. + +* `zone_name` - (Required) Specifies the Private DNS Zone where the resource exists. Changing this forces a new resource to be created. + +* `record` - (Required) One or more `record` blocks as defined below. + +* `ttl ` - (Required) The Time To Live (TTL) of the DNS record in seconds. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +--- + +A `record` block supports the following: + +* `value` - (Required) The value of the TXT record. Max length: 1024 characters + + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Private DNS TXT Record ID. + +* `fqdn` - The FQDN of the DNS TXT Record. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Private DNS TXT Record. +* `update` - (Defaults to 30 minutes) Used when updating the Private DNS TXT Record. +* `read` - (Defaults to 5 minutes) Used when retrieving the Private DNS TXT Record. +* `delete` - (Defaults to 30 minutes) Used when deleting the Private DNS TXT Record. + +## Import + +Private DNS TXT Records can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_private_dns_txt_record.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/privateDnsZones/contoso.com/TXT/test +```