diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 85733b778f..94742b41d9 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -565,9 +565,10 @@ DNSPOD Resource tencentcloud_dnspod_domain_instance -PRIVATE DNS +PrivateDNS Resource tencentcloud_private_dns_zone + tencentcloud_private_dns_record */ package tencentcloud @@ -1024,6 +1025,7 @@ func Provider() terraform.ResourceProvider { "tencentcloud_cdh_instance": resourceTencentCloudCdhInstance(), "tencentcloud_dnspod_domain_instance": resourceTencentCloudDnspodDomainInstance(), "tencentcloud_private_dns_zone": resourceTencentCloudPrivateDnsZone(), + "tencentcloud_private_dns_record": resourceTencentCloudPrivateDnsRecord(), }, ConfigureFunc: providerConfigure, diff --git a/tencentcloud/resource_tc_private_dns_record.go b/tencentcloud/resource_tc_private_dns_record.go new file mode 100644 index 0000000000..b62f016ef9 --- /dev/null +++ b/tencentcloud/resource_tc_private_dns_record.go @@ -0,0 +1,287 @@ +/* +Provide a resource to create a Private Dns Record. + +Example Usage + +```hcl +resource "tencentcloud_private_dns_record" "foo" { + zone_id = "zone-rqndjnki" + record_type = "A" + record_value = "192.168.1.2" + sub_domain = "www" + ttl = 300 + weight = 1 + mx = 0 +} +``` + +Import + +Private Dns Record can be imported, e.g. + +``` +$ terraform import tencentcloud_private_dns_zone.foo zone_id#record_id +``` +*/ +package tencentcloud + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + privatedns "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns/v20201028" +) + +func resourceTencentCloudPrivateDnsRecord() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudDPrivateDnsRecordCreate, + Read: resourceTencentCloudDPrivateDnsRecordRead, + Update: resourceTencentCloudDPrivateDnsRecordUpdate, + Delete: resourceTencentCloudDPrivateDnsRecordDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "zone_id": { + Type: schema.TypeString, + Required: true, + Description: "Private domain ID.", + }, + "record_type": { + Type: schema.TypeString, + Required: true, + Description: "Record type. Valid values: \"A\", \"AAAA\", \"CNAME\", \"MX\", \"TXT\", \"PTR\".", + }, + "sub_domain": { + Type: schema.TypeString, + Required: true, + Description: "Subdomain, such as \"www\", \"m\", and \"@\".", + }, + "record_value": { + Type: schema.TypeString, + Required: true, + Description: "Record value, such as IP: 192.168.10.2," + + " CNAME: cname.qcloud.com, and MX: mail.qcloud.com..", + }, + "weight": { + Type: schema.TypeInt, + Optional: true, + Description: "Record weight. Value range: 1~100.", + }, + "mx": { + Type: schema.TypeInt, + Optional: true, + Description: "MX priority, which is required when the record type is MX." + + " Valid values: 5, 10, 15, 20, 30, 40, 50.", + }, + "ttl": { + Type: schema.TypeInt, + Optional: true, + Description: "Record cache time. The smaller the value, the faster the record will take effect." + + " Value range: 1~86400s.", + }, + }, + } +} + +func resourceTencentCloudDPrivateDnsRecordCreate(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_private_dns_record.create")() + + logId := getLogId(contextNil) + + request := privatedns.NewCreatePrivateZoneRecordRequest() + + zoneId := d.Get("zone_id").(string) + request.ZoneId = &zoneId + + recordType := d.Get("record_type").(string) + request.RecordType = &recordType + + subDomain := d.Get("sub_domain").(string) + request.SubDomain = &subDomain + + recordValue := d.Get("record_value").(string) + request.RecordValue = &recordValue + + if v, ok := d.GetOk("weight"); ok { + request.Weight = helper.Int64(int64(v.(int))) + } + + if v, ok := d.GetOk("mx"); ok { + request.MX = helper.Int64(int64(v.(int))) + } + if v, ok := d.GetOk("ttl"); ok { + request.TTL = helper.Int64(int64(v.(int))) + } + + result, err := meta.(*TencentCloudClient).apiV3Conn.UsePrivateDnsClient().CreatePrivateZoneRecord(request) + + if err != nil { + log.Printf("[CRITAL]%s create PrivateDns record failed, reason:%s\n", logId, err.Error()) + return err + } + + var response *privatedns.CreatePrivateZoneRecordResponse + response = result + + recordId := *response.Response.RecordId + d.SetId(strings.Join([]string{zoneId, recordId}, FILED_SP)) + + return resourceTencentCloudDPrivateDnsRecordRead(d, meta) +} + +func resourceTencentCloudDPrivateDnsRecordRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_private_dns_zone.read")() + defer inconsistentCheck(d, meta)() + + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + + service := PrivateDnsService{ + client: meta.(*TencentCloudClient).apiV3Conn, + } + + idSplit := strings.Split(d.Id(), FILED_SP) + if len(idSplit) != 2 { + return fmt.Errorf("record id strategy is can't read, id is borken, id is %s", d.Id()) + } + zoneId := idSplit[0] + recordId := idSplit[1] + + records, err := service.DescribePrivateDnsRecordByFilter(ctx, zoneId, "") + if err != nil { + return err + } + + if len(records) < 1 { + return fmt.Errorf("private dns record not exists.") + } + + var record *privatedns.PrivateZoneRecord + for _, item := range records { + if *item.RecordId == recordId { + record = item + } + } + _ = d.Set("zone_id", record.ZoneId) + _ = d.Set("record_type", record.RecordType) + _ = d.Set("sub_domain", record.SubDomain) + _ = d.Set("record_value", record.RecordValue) + _ = d.Set("weight", record.Weight) + _ = d.Set("mx", record.MX) + _ = d.Set("ttl", record.TTL) + + return nil +} + +func resourceTencentCloudDPrivateDnsRecordUpdate(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_private_dns_record.update")() + + idSplit := strings.Split(d.Id(), FILED_SP) + if len(idSplit) != 2 { + return fmt.Errorf("record id strategy is can't read, id is borken, id is %s", d.Id()) + } + logId := getLogId(contextNil) + zoneId := idSplit[0] + recordId := idSplit[1] + + request := privatedns.NewModifyPrivateZoneRecordRequest() + request.ZoneId = helper.String(zoneId) + request.RecordId = helper.String(recordId) + + needModify := false + if d.HasChange("record_type") { + needModify = true + } + + if d.HasChange("sub_domain") { + needModify = true + } + + if d.HasChange("record_value") { + needModify = true + } + + if d.HasChange("weight") { + needModify = true + if v, ok := d.GetOk("weight"); ok { + request.Weight = helper.Int64(int64(v.(int))) + } + } + + if d.HasChange("mx") { + needModify = true + if v, ok := d.GetOk("mx"); ok { + request.MX = helper.Int64(int64(v.(int))) + } + } + + if d.HasChange("ttl") { + needModify = true + if v, ok := d.GetOk("ttl"); ok { + request.TTL = helper.Int64(int64(v.(int))) + } + } + + if needModify { + if v, ok := d.GetOk("record_type"); ok { + request.RecordType = helper.String(v.(string)) + } + if v, ok := d.GetOk("sub_domain"); ok { + request.SubDomain = helper.String(v.(string)) + } + if v, ok := d.GetOk("record_value"); ok { + request.RecordValue = helper.String(v.(string)) + } + err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + _, e := meta.(*TencentCloudClient).apiV3Conn.UsePrivateDnsClient().ModifyPrivateZoneRecord(request) + if e != nil { + return retryError(e) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s modify privateDns record info failed, reason:%s\n", logId, err.Error()) + return err + } + } + + return resourceTencentCloudDPrivateDnsRecordRead(d, meta) +} + +func resourceTencentCloudDPrivateDnsRecordDelete(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_private_dns_record.delete")() + + logId := getLogId(contextNil) + + idSplit := strings.Split(d.Id(), FILED_SP) + if len(idSplit) != 2 { + return fmt.Errorf("record id strategy is can't read, id is borken, id is %s", d.Id()) + } + zoneId := idSplit[0] + recordId := idSplit[1] + + request := privatedns.NewDeletePrivateZoneRecordRequest() + request.ZoneId = helper.String(zoneId) + request.RecordId = helper.String(recordId) + + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { + _, e := meta.(*TencentCloudClient).apiV3Conn.UsePrivateDnsClient().DeletePrivateZoneRecord(request) + if e != nil { + return retryError(e) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s delete privateDns record failed, reason:%s\n", logId, err.Error()) + return err + } + return nil +} diff --git a/tencentcloud/service_tencentcloud_private_dns.go b/tencentcloud/service_tencentcloud_private_dns.go new file mode 100644 index 0000000000..40602188a8 --- /dev/null +++ b/tencentcloud/service_tencentcloud_private_dns.go @@ -0,0 +1,87 @@ +package tencentcloud + +import ( + "context" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + "log" + + privatedns "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns/v20201028" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/connectivity" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit" +) + +// basic information + +type PrivateDnsService struct { + client *connectivity.TencentCloudClient +} + +// ////////api +func (me *PrivateDnsService) DescribePrivateDnsRecordByFilter(ctx context.Context, zoneId string, + recordId string) (recordInfos []*privatedns.PrivateZoneRecord, errRet error) { + logId := getLogId(ctx) + request := privatedns.NewDescribePrivateZoneRecordListRequest() + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", + logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + var ( + limit int64 = 20 + offset int64 = 0 + total int64 = -1 + ) + request.ZoneId = &zoneId + request.Filters = make([]*privatedns.Filter, 0) + + if recordId != "" { + filter := privatedns.Filter{ + Name: helper.String("RecordId"), + Values: []*string{&recordId}, + } + request.Filters = append(request.Filters, &filter) + } + +getMoreData: + + if total >= 0 { + if offset >= total { + return + } + } + var response *privatedns.DescribePrivateZoneRecordListResponse + + ratelimit.Check(request.GetAction()) + request.Limit = &limit + request.Offset = &offset + + if err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + ratelimit.Check(request.GetAction()) + result, err := me.client.UsePrivateDnsClient().DescribePrivateZoneRecordList(request) + if err != nil { + return retryError(err, InternalError) + } + response = result + return nil + }); err != nil { + log.Printf("[CRITAL]%s read private dns failed, reason: %v", logId, err) + return nil, err + } + if total < 0 { + total = *response.Response.TotalCount + } + + if len(response.Response.RecordSet) > 0 { + offset = offset + limit + } else { + return + } + + for _, item := range response.Response.RecordSet { + recordInfos = append(recordInfos, item) + + } + goto getMoreData +} diff --git a/website/docs/r/private_dns_record.html.markdown b/website/docs/r/private_dns_record.html.markdown new file mode 100644 index 0000000000..5e7ebd04d0 --- /dev/null +++ b/website/docs/r/private_dns_record.html.markdown @@ -0,0 +1,55 @@ +--- +subcategory: "PrivateDNS" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_private_dns_record" +sidebar_current: "docs-tencentcloud-resource-private_dns_record" +description: |- + Provide a resource to create a Private Dns Record. +--- + +# tencentcloud_private_dns_record + +Provide a resource to create a Private Dns Record. + +## Example Usage + +```hcl +resource "tencentcloud_private_dns_record" "foo" { + zone_id = "zone-rqndjnki" + record_type = "A" + record_value = "192.168.1.2" + sub_domain = "www" + ttl = 300 + weight = 1 + mx = 0 +} +``` + +## Argument Reference + +The following arguments are supported: + +* `record_type` - (Required) Record type. Valid values: "A", "AAAA", "CNAME", "MX", "TXT", "PTR". +* `record_value` - (Required) Record value, such as IP: 192.168.10.2, CNAME: cname.qcloud.com, and MX: mail.qcloud.com.. +* `sub_domain` - (Required) Subdomain, such as "www", "m", and "@". +* `zone_id` - (Required) Private domain ID. +* `mx` - (Optional) MX priority, which is required when the record type is MX. Valid values: 5, 10, 15, 20, 30, 40, 50. +* `ttl` - (Optional) Record cache time. The smaller the value, the faster the record will take effect. Value range: 1~86400s. +* `weight` - (Optional) Record weight. Value range: 1~100. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the resource. + + + +## Import + +Private Dns Record can be imported, e.g. + +``` +$ terraform import tencentcloud_private_dns_zone.foo zone_id#record_id +``` + diff --git a/website/docs/r/private_dns_zone.html.markdown b/website/docs/r/private_dns_zone.html.markdown index a0cb23c264..57882228c8 100644 --- a/website/docs/r/private_dns_zone.html.markdown +++ b/website/docs/r/private_dns_zone.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "PRIVATE DNS" +subcategory: "PrivateDNS" layout: "tencentcloud" page_title: "TencentCloud: tencentcloud_private_dns_zone" sidebar_current: "docs-tencentcloud-resource-private_dns_zone" diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index 33c7afa288..687a5058f4 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -1025,20 +1025,6 @@ -
  • - PRIVATE DNS - -
  • PostgreSQL
  • +
  • + PrivateDNS + +
  • Redis