diff --git a/tencentcloud/basic_test.go b/tencentcloud/basic_test.go index 75f81a7f5e..5997515f7d 100644 --- a/tencentcloud/basic_test.go +++ b/tencentcloud/basic_test.go @@ -175,6 +175,7 @@ const ( defaultTkeClusterName = "keep-tke-cluster" defaultTkeClusterType = "tke" defaultPrometheusId = "prom-1lspn8sw" + defaultTemplateId = "temp-gqunlvo1" ) /* diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 400e208fa3..cd520af951 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -433,6 +433,7 @@ Monitor tencentcloud_monitor_tmp_alert_rule tencentcloud_monitor_tmp_recording_rule tencentcloud_monitor_tmp_tke_template + tencentcloud_monitor_tmp_tke_template_attachment tencentcloud_monitor_tmp_tke_alert_policy tencentcloud_monitor_tmp_tke_config tencentcloud_monitor_alarm_notice @@ -1100,6 +1101,7 @@ func Provider() terraform.ResourceProvider { "tencentcloud_monitor_tmp_alert_rule": resourceTencentCloudMonitorTmpAlertRule(), "tencentcloud_monitor_tmp_recording_rule": resourceTencentCloudMonitorTmpRecordingRule(), "tencentcloud_monitor_tmp_tke_template": resourceTencentCloudMonitorTmpTkeTemplate(), + "tencentcloud_monitor_tmp_tke_template_attachment": resourceTencentCloudMonitorTmpTkeTemplateAttachment(), "tencentcloud_monitor_tmp_tke_alert_policy": resourceTencentCloudMonitorTmpTkeAlertPolicy(), "tencentcloud_monitor_tmp_tke_config": resourceTencentCloudMonitorTmpTkeConfig(), "tencentcloud_monitor_tmp_tke_record_rule_yaml": resourceTencentCloudMonitorTmpTkeRecordRuleYaml(), diff --git a/tencentcloud/resource_tc_monitor_tmp_tke_template_attachment.go b/tencentcloud/resource_tc_monitor_tmp_tke_template_attachment.go new file mode 100644 index 0000000000..c37608a1f0 --- /dev/null +++ b/tencentcloud/resource_tc_monitor_tmp_tke_template_attachment.go @@ -0,0 +1,265 @@ +/* +Provides a resource to create a tmp tke template attachment + +Example Usage + +```hcl + +resource "tencentcloud_monitor_tmp_tke_template_attachment" "temp_attachment" { + template_id = "temp-xxx" + + targets { + region = "ap-xxx" + instance_id = "prom-xxx" + } +} + +*/ +package tencentcloud + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func resourceTencentCloudMonitorTmpTkeTemplateAttachment() *schema.Resource { + return &schema.Resource{ + Read: resourceTencentCloudMonitorTmpTkeTemplateAttachmentRead, + Create: resourceTencentCloudMonitorTmpTkeTemplateAttachmentCreate, + Delete: resourceTencentCloudMonitorTmpTkeTemplateAttachmentDelete, + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The ID of the template, which is used for the outgoing reference.", + }, + + "targets": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + ForceNew: true, + Description: "Sync target details.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "region": { + Type: schema.TypeString, + Required: true, + Description: "target area.", + }, + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "instance id.", + }, + "cluster_id": { + Type: schema.TypeString, + Optional: true, + Description: "ID of the cluster.", + }, + "sync_time": { + Type: schema.TypeString, + Optional: true, + Description: "Last sync template time.", + }, + "version": { + Type: schema.TypeString, + Optional: true, + Description: "Template version currently in use.", + }, + "cluster_type": { + Type: schema.TypeString, + Optional: true, + Description: "Cluster type.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the prometheus instance.", + }, + "cluster_name": { + Type: schema.TypeString, + Optional: true, + Description: "Name the cluster.", + }, + }, + }, + }, + }, + } +} + +func resourceTencentCloudMonitorTmpTkeTemplateAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_monitor_tmp_tke_template_attachment.create")() + defer inconsistentCheck(d, meta)() + + logId := getLogId(contextNil) + + request := tke.NewSyncPrometheusTempRequest() + + if v, ok := d.GetOk("template_id"); ok { + request.TemplateId = helper.String(v.(string)) + } + + if dMap, ok := helper.InterfacesHeadMap(d, "targets"); ok { + var prometheusTarget tke.PrometheusTemplateSyncTarget + if v, ok := dMap["region"]; ok { + prometheusTarget.Region = helper.String(v.(string)) + } + + if v, ok := dMap["instance_id"]; ok { + prometheusTarget.InstanceId = helper.String(v.(string)) + } + + if v, ok := dMap["cluster_id"]; ok { + prometheusTarget.ClusterId = helper.String(v.(string)) + } + + if v, ok := dMap["sync_time"]; ok { + prometheusTarget.SyncTime = helper.String(v.(string)) + } + + if v, ok := dMap["version"]; ok { + prometheusTarget.Version = helper.String(v.(string)) + } + + if v, ok := dMap["cluster_type"]; ok { + prometheusTarget.ClusterType = helper.String(v.(string)) + } + + if v, ok := dMap["instance_name"]; ok { + prometheusTarget.InstanceName = helper.String(v.(string)) + } + + if v, ok := dMap["cluster_name"]; ok { + prometheusTarget.ClusterName = helper.String(v.(string)) + } + + prometheusTargets := make([]*tke.PrometheusTemplateSyncTarget, 0) + prometheusTargets = append(prometheusTargets, &prometheusTarget) + request.Targets = prometheusTargets + + } + + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { + result, e := meta.(*TencentCloudClient).apiV3Conn.UseTkeClient().SyncPrometheusTemp(request) + if e != nil { + return retryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s sync tke template failed, reason:%+v", logId, err) + return err + } + + templateId := *request.TemplateId + instanceId := *request.Targets[0].InstanceId + region := *request.Targets[0].Region + d.SetId(strings.Join([]string{templateId, instanceId, region}, FILED_SP)) + + return resourceTencentCloudMonitorTmpTkeTemplateAttachmentRead(d, meta) +} + +func resourceTencentCloudMonitorTmpTkeTemplateAttachmentRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_monitor_tmp_tke_template_attachment.read")() + defer inconsistentCheck(d, meta)() + + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + + service := TkeService{client: meta.(*TencentCloudClient).apiV3Conn} + + ids := strings.Split(d.Id(), FILED_SP) + if len(ids) != 3 { + return fmt.Errorf("id is broken, id is %s", d.Id()) + } + + templateId := ids[0] + instanceId := ids[1] + region := ids[2] + + targets, err := service.DescribePrometheusTempSync(ctx, templateId) + + if err != nil { + return err + } + + if targets == nil || len(targets) < 1 { + d.SetId("") + return fmt.Errorf("resource `targets` %s does not exist", templateId) + } + + tempTargets := make([]map[string]interface{}, 0) + for _, v := range targets { + if *v.InstanceId == instanceId && *v.Region == region { + tempTargets = append(tempTargets, map[string]interface{}{ + "region": v.Region, + "instance_id": v.InstanceId, + //"cluster_id": v.ClusterId, + //"sync_time": v.SyncTime, + //"version": v.Version, + //"cluster_type": v.ClusterType, + //"instance_name": v.InstanceName, + //"cluster_name": v.ClusterName, + }) + } + } + _ = d.Set("targets", tempTargets) + + return nil +} + +func resourceTencentCloudMonitorTmpTkeTemplateAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_monitor_tmp_tke_template_attachment.delete")() + defer inconsistentCheck(d, meta)() + + logId := getLogId(contextNil) + request := tke.NewDeletePrometheusTempSyncRequest() + + ids := strings.Split(d.Id(), FILED_SP) + if len(ids) != 3 { + return fmt.Errorf("id is broken, id is %s", d.Id()) + } + + templateId := ids[0] + instanceId := ids[1] + region := ids[2] + + request.TemplateId = &templateId + var targets []*tke.PrometheusTemplateSyncTarget + target := tke.PrometheusTemplateSyncTarget{ + Region: ®ion, + InstanceId: &instanceId, + } + targets = append(targets, &target) + request.Targets = targets + + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { + result, e := meta.(*TencentCloudClient).apiV3Conn.UseTkeClient().DeletePrometheusTempSync(request) + if e != nil { + return retryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + return nil + }) + if err != nil { + return err + } + + return nil +} diff --git a/tencentcloud/resource_tc_monitor_tmp_tke_template_attachment_test.go b/tencentcloud/resource_tc_monitor_tmp_tke_template_attachment_test.go new file mode 100644 index 0000000000..ab827482e1 --- /dev/null +++ b/tencentcloud/resource_tc_monitor_tmp_tke_template_attachment_test.go @@ -0,0 +1,127 @@ +package tencentcloud + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccTencentCloudMonitorTempAttachment_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckCommon(t, ACCOUNT_TYPE_COMMON) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckTempAttachmentDestroy, + Steps: []resource.TestStep{ + { + Config: testTempAttachment_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckTempAttachmentExists("tencentcloud_monitor_tmp_tke_template_attachment.basic"), + resource.TestCheckResourceAttr("tencentcloud_monitor_tmp_tke_template_attachment.basic", "template_id", "temp-gqunlvo1"), + resource.TestCheckResourceAttr("tencentcloud_monitor_tmp_tke_template_attachment.basic", "targets.0.instance_id", "prom-1lspn8sw"), + resource.TestCheckResourceAttr("tencentcloud_monitor_tmp_tke_template_attachment.basic", "targets.0.region", "ap-guangzhou"), + ), + }, + }, + }) +} + +func testAccCheckTempAttachmentDestroy(s *terraform.State) error { + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + recordService := TkeService{client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn} + for _, rs := range s.RootModule().Resources { + if rs.Type != "tencentcloud_monitor_tmp_tke_template_attachment" { + continue + } + items := strings.Split(rs.Primary.ID, FILED_SP) + if len(items) != 3 { + return fmt.Errorf("invalid ID %s", rs.Primary.ID) + } + + templateId := items[0] + instanceId := items[1] + region := items[2] + targets, err := recordService.DescribePrometheusTempSync(ctx, templateId) + if err != nil { + return err + } + + if len(targets) > 0 { + for _, v := range targets { + if *v.InstanceId == instanceId && *v.Region == region { + return fmt.Errorf("associated instance information %s still exists", rs.Primary.ID) + } + } + } + } + + return nil +} + +func testAccCheckTempAttachmentExists(r string) resource.TestCheckFunc { + return func(s *terraform.State) error { + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + + rs, ok := s.RootModule().Resources[r] + if !ok { + return fmt.Errorf("resource %s is not found", r) + } + if rs.Primary.ID == "" { + return fmt.Errorf("resource id is not set") + } + items := strings.Split(rs.Primary.ID, FILED_SP) + if len(items) != 3 { + return fmt.Errorf("invalid ID %s", rs.Primary.ID) + } + + templateId := items[0] + instanceId := items[1] + region := items[2] + service := TkeService{client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn} + targets, err := service.DescribePrometheusTempSync(ctx, templateId) + if err != nil { + return err + } + + if len(targets) < 1 { + return fmt.Errorf("associated instance information %s is not found", rs.Primary.ID) + } + for i, v := range targets { + if *v.InstanceId == instanceId && *v.Region == region { + return nil + } + if i == len(targets)-1 { + return fmt.Errorf("associated instance information %s is not found", rs.Primary.ID) + } + } + + return nil + } +} + +const testTempAttachmentVar = ` +variable "prometheus_id" { + default = "` + defaultPrometheusId + `" +} +variable "template_id" { + default = "` + defaultTemplateId + `" +} +variable "region" { + default = "ap-guangzhou" +}` + +const testTempAttachment_basic = testTempAttachmentVar + ` +resource "tencentcloud_monitor_tmp_tke_template_attachment" "basic" { + template_id = var.template_id + + targets { + region = var.region + instance_id = var.prometheus_id + } +}` diff --git a/tencentcloud/service_tencentcloud_tke.go b/tencentcloud/service_tencentcloud_tke.go index 543943d0b4..54c6930424 100644 --- a/tencentcloud/service_tencentcloud_tke.go +++ b/tencentcloud/service_tencentcloud_tke.go @@ -2087,3 +2087,43 @@ func (me *TkeService) ModifyTkeTmpGlobalNotification(ctx context.Context, instan return } + +func (me *TkeService) DescribePrometheusTempSync(ctx context.Context, templateId string) (targets []*tke.PrometheusTemplateSyncTarget, errRet error) { + var ( + logId = getLogId(ctx) + request = tke.NewDescribePrometheusTempSyncRequest() + ) + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", + logId, "query object", request.ToJsonString(), errRet.Error()) + } + }() + + request.TemplateId = &templateId + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseTkeClient().DescribePrometheusTempSync(request) + if err != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", + logId, request.GetAction(), request.ToJsonString(), err.Error()) + errRet = err + return + } + + log.Printf("[DEBUG]%s api[%s] success,ids [%s], request body [%s], response body [%s]\n", + logId, request.GetAction(), templateId, request.ToJsonString(), response.ToJsonString()) + + if response == nil || response.Response.RequestId == nil { + return nil, fmt.Errorf("response is invalid, %s", response.ToJsonString()) + } + + if len(response.Response.Targets) < 1 { + return + } + + targets = response.Response.Targets + + return +} diff --git a/website/docs/r/monitor_tmp_tke_template_attachment.html.markdown b/website/docs/r/monitor_tmp_tke_template_attachment.html.markdown new file mode 100644 index 0000000000..36e9a42e03 --- /dev/null +++ b/website/docs/r/monitor_tmp_tke_template_attachment.html.markdown @@ -0,0 +1,43 @@ +--- +subcategory: "Monitor" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_monitor_tmp_tke_template_attachment" +sidebar_current: "docs-tencentcloud-resource-monitor_tmp_tke_template_attachment" +description: |- + Provides a resource to create a tmp tke template attachment +--- + +# tencentcloud_monitor_tmp_tke_template_attachment + +Provides a resource to create a tmp tke template attachment + +## Example Usage + + + +## Argument Reference + +The following arguments are supported: + +* `targets` - (Required, List, ForceNew) Sync target details. +* `template_id` - (Required, String, ForceNew) The ID of the template, which is used for the outgoing reference. + +The `targets` object supports the following: + +* `instance_id` - (Required, String) instance id. +* `region` - (Required, String) target area. +* `cluster_id` - (Optional, String) ID of the cluster. +* `cluster_name` - (Optional, String) Name the cluster. +* `cluster_type` - (Optional, String) Cluster type. +* `instance_name` - (Optional, String) Name of the prometheus instance. +* `sync_time` - (Optional, String) Last sync template time. +* `version` - (Optional, String) Template version currently in use. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the resource. + + + diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index f9e89dabaa..9ee078b622 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -1158,14 +1158,17 @@ tencentcloud_monitor_tmp_tke_config