From 4f8f63e5d626d495da3c7dc4f860dd9cfa19ad39 Mon Sep 17 00:00:00 2001 From: hellertang Date: Tue, 12 Apr 2022 17:54:49 +0800 Subject: [PATCH] support cls shipper --- tencentcloud/provider.go | 2 + tencentcloud/resource_tc_cls_cos_shipper.go | 600 ++++++++++++++++++ .../resource_tc_cls_cos_shipper_test.go | 111 ++++ tencentcloud/resource_tc_cls_machine_group.go | 2 +- tencentcloud/service_tencentcloud_cls.go | 131 ++++ website/docs/r/cls_cos_shipper.html.markdown | 105 +++ website/tencentcloud.erb | 3 + 7 files changed, 953 insertions(+), 1 deletion(-) create mode 100644 tencentcloud/resource_tc_cls_cos_shipper.go create mode 100644 tencentcloud/resource_tc_cls_cos_shipper_test.go create mode 100644 website/docs/r/cls_cos_shipper.html.markdown diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 094a7a3ab2..022c1d2051 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -605,6 +605,7 @@ CLS tencentcloud_cls_logset tencentcloud_cls_topic tencentcloud_cls_machine_group + tencentcloud_cls_cos_shipper */ package tencentcloud @@ -1093,6 +1094,7 @@ func Provider() terraform.ResourceProvider { "tencentcloud_cls_logset": resourceTencentCloudClsLogset(), "tencentcloud_cls_topic": resourceTencentCloudClsTopic(), "tencentcloud_cls_machine_group": resourceTencentCloudClsMachineGroup(), + "tencentcloud_cls_cos_shipper": resourceTencentCloudClsCosShipper(), }, ConfigureFunc: providerConfigure, diff --git a/tencentcloud/resource_tc_cls_cos_shipper.go b/tencentcloud/resource_tc_cls_cos_shipper.go new file mode 100644 index 0000000000..41446b7aa5 --- /dev/null +++ b/tencentcloud/resource_tc_cls_cos_shipper.go @@ -0,0 +1,600 @@ +/* +Provides a resource to create a cls cos shipper. + +Example Usage + +```hcl +resource "tencentcloud_cls_cos_shipper" "shipper" { + bucket = "preset-scf-bucket-1308919341" + interval = 300 + max_size = 200 + partition = "/%Y/%m/%d/%H/" + prefix = "ap-guangzhou-fffsasad-1649734752" + shipper_name = "ap-guangzhou-fffsasad-1649734752" + topic_id = "4d07fba0-b93e-4e0b-9a7f-d58542560bbb" + + compress { + format = "lzop" + } + + content { + format = "json" + + json { + enable_tag = true + meta_fields = [ + "__FILENAME__", + "__SOURCE__", + "__TIMESTAMP__", + ] + } + } +} +``` + +Import + +cls cos shipper can be imported using the id, e.g. + +``` +$ terraform import tencentcloud_cls_cos_shipper.shipper 5d1b7b2a-c163-4c48-bb01-9ee00584d761 +``` +*/ +package tencentcloud + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + cls "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cls/v20201016" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func resourceTencentCloudClsCosShipper() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudClsCosShipperCreate, + Read: resourceTencentCloudClsCosShipperRead, + Delete: resourceTencentCloudClsCosShipperDelete, + Update: resourceTencentCloudClsCosShipperUpdate, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "topic_id": { + Type: schema.TypeString, + Required: true, + Description: "ID of the log topic to which the shipping rule to be created belongs.", + }, + "bucket": { + Type: schema.TypeString, + Required: true, + Description: "Destination bucket in the shipping rule to be created.", + }, + "prefix": { + Type: schema.TypeString, + Required: true, + Description: "Prefix of the shipping directory in the shipping rule to be created.", + }, + "shipper_name": { + Type: schema.TypeString, + Required: true, + Description: "Shipping rule name.", + }, + "interval": { + Type: schema.TypeInt, + Optional: true, + Description: "Shipping time interval in seconds. Default value: 300. Value range: 300~900.", + }, + "max_size": { + Type: schema.TypeInt, + Optional: true, + Description: "Maximum size of a file to be shipped, in MB. Default value: 256. Value range: 100~256.", + }, + "filter_rules": { + Type: schema.TypeList, + Optional: true, + Description: "Filter rules for shipped logs. Only logs matching the rules can be shipped. All rules are in the AND relationship, and up to five rules can be added. " + + "If the array is empty, no filtering will be performed, and all logs will be shipped.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + Description: "Filter rule key.", + }, + "regex": { + Type: schema.TypeString, + Required: true, + Description: "Filter rule.", + }, + "value": { + Type: schema.TypeString, + Required: true, + Description: "Filter rule value.", + }, + }, + }, + }, + "partition": { + Type: schema.TypeString, + Optional: true, + Description: "Partition rule of shipped log, which can be represented in strftime time format.", + }, + "compress": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "format": { + Type: schema.TypeString, + Required: true, + Description: "Compression format. Valid values: gzip, lzop, none (no compression).", + }, + }, + }, + Description: "Compression configuration of shipped log.", + }, + "content": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: "Format configuration of shipped log content.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "format": { + Type: schema.TypeString, + Required: true, + Description: "Content format. Valid values: json, csv.", + }, + "csv": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "print_key": { + Type: schema.TypeBool, + Required: true, + Description: "Whether to print key on the first row of the CSV file.", + }, + "keys": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Names of keys.Note: this field may return null, indicating that no valid values can be obtained.", + }, + "delimiter": { + Type: schema.TypeString, + Required: true, + Description: "Field delimiter.", + }, + "escape_char": { + Type: schema.TypeString, + Required: true, + Description: "Field delimiter.", + }, + "non_existing_field": { + Type: schema.TypeString, + Required: true, + Description: "Content used to populate non-existing fields.", + }, + }, + }, + Description: "CSV format content description.Note: this field may return null, indicating that no valid values can be obtained.", + }, + "json": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_tag": { + Type: schema.TypeBool, + Required: true, + Description: "Enablement flag.", + }, + "meta_fields": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Metadata information list\nNote: this field may return null, indicating that no valid values can be obtained..", + }, + }, + }, + Description: "JSON format content description.Note: this field may return null, indicating that no valid values can be obtained.", + }, + }, + }, + }, + }, + } +} + +func resourceTencentCloudClsCosShipperCreate(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_cls_cos_shipper.create")() + + logId := getLogId(contextNil) + + var ( + request = cls.NewCreateShipperRequest() + response *cls.CreateShipperResponse + ) + + if v, ok := d.GetOk("topic_id"); ok { + request.TopicId = helper.String(v.(string)) + } + + if v, ok := d.GetOk("bucket"); ok { + request.Bucket = helper.String(v.(string)) + } + + if v, ok := d.GetOk("prefix"); ok { + request.Prefix = helper.String(v.(string)) + } + + if v, ok := d.GetOk("shipper_name"); ok { + request.ShipperName = helper.String(v.(string)) + } + + if v, ok := d.GetOk("interval"); ok { + request.Interval = helper.IntUint64(v.(int)) + } + + if v, ok := d.GetOk("max_size"); ok { + request.MaxSize = helper.IntUint64(v.(int)) + } + + if v, ok := d.GetOk("filter_rules"); ok { + filterRules := make([]*cls.FilterRuleInfo, 0, 10) + for _, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + filterRule := cls.FilterRuleInfo{} + if v, ok := dMap["key"]; ok { + filterRule.Key = helper.String(v.(string)) + } + if v, ok := dMap["regex"]; ok { + filterRule.Regex = helper.String(v.(string)) + } + if v, ok := dMap["value"]; ok { + filterRule.Value = helper.String(v.(string)) + } + filterRules = append(filterRules, &filterRule) + } + request.FilterRules = filterRules + } + + if v, ok := d.GetOk("partition"); ok { + request.Partition = helper.String(v.(string)) + } + + if v, ok := d.GetOk("compress"); ok { + compresses := make([]*cls.CompressInfo, 0, 10) + if len(v.([]interface{})) != 1 { + return fmt.Errorf("need only one compress.") + } + for _, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + compress := cls.CompressInfo{} + if v, ok := dMap["format"]; ok { + compress.Format = helper.String(v.(string)) + } + compresses = append(compresses, &compress) + } + request.Compress = compresses[0] + } + + if v, ok := d.GetOk("content"); ok { + contents := make([]*cls.ContentInfo, 0, 10) + if len(v.([]interface{})) != 1 { + return fmt.Errorf("need only one content.") + } + for _, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + content := cls.ContentInfo{} + if v, ok := dMap["format"]; ok { + content.Format = helper.String(v.(string)) + } + if v, ok := dMap["csv"]; ok { + if len(v.([]interface{})) == 1 { + csv := v.([]interface{})[0].(map[string]interface{}) + csvInfo := cls.CsvInfo{} + csvInfo.PrintKey = helper.Bool(csv["print_key"].(bool)) + keys := csv["keys"].(*schema.Set).List() + for _, key := range keys { + csvInfo.Keys = append(csvInfo.Keys, helper.String(key.(string))) + } + csvInfo.Delimiter = helper.String(csv["delimiter"].(string)) + csvInfo.EscapeChar = helper.String(csv["escape_char"].(string)) + csvInfo.NonExistingField = helper.String(csv["non_existing_field"].(string)) + content.Csv = &csvInfo + } + } + if v, ok := dMap["json"]; ok { + if len(v.([]interface{})) == 1 { + + json := v.([]interface{})[0].(map[string]interface{}) + jsonInfo := cls.JsonInfo{} + jsonInfo.EnableTag = helper.Bool(json["enable_tag"].(bool)) + metaFields := json["meta_fields"].(*schema.Set).List() + for _, metaField := range metaFields { + jsonInfo.MetaFields = append(jsonInfo.MetaFields, helper.String(metaField.(string))) + } + content.Json = &jsonInfo + } + } + contents = append(contents, &content) + } + request.Content = contents[0] + } + + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { + result, e := meta.(*TencentCloudClient).apiV3Conn.UseClsClient().CreateShipper(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()) + } + response = result + return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s create cls cos shipper failed, reason:%+v", logId, err) + return err + } + + id := *response.Response.ShipperId + log.Printf("=====1=========") + log.Printf(id) + log.Printf("=====1=========") + d.SetId(id) + return resourceTencentCloudClsCosShipperRead(d, meta) +} + +func resourceTencentCloudClsCosShipperRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_cls_cos_shipper.read")() + defer inconsistentCheck(d, meta)() + + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + service := ClsService{client: meta.(*TencentCloudClient).apiV3Conn} + + id := d.Id() + + shipper, err := service.DescribeClsCosShipperById(ctx, id) + + if err != nil { + return err + } + + if shipper == nil { + d.SetId("") + return fmt.Errorf("resource `Shipper` %s does not exist", id) + } + + _ = d.Set("topic_id", shipper.TopicId) + _ = d.Set("bucket", shipper.Bucket) + _ = d.Set("prefix", shipper.Prefix) + _ = d.Set("shipper_name", shipper.ShipperName) + if shipper.Interval != nil { + _ = d.Set("interval", shipper.Interval) + } + if shipper.MaxSize != nil { + _ = d.Set("max_size", shipper.MaxSize) + } + + if shipper.FilterRules != nil { + filterRules := make([]interface{}, 0, 100) + for _, v := range shipper.FilterRules { + filterRule := map[string]interface{}{ + "key": v.Key, + "regex": v.Regex, + "value": v.Value, + } + filterRules = append(filterRules, filterRule) + } + _ = d.Set("filter_rules", filterRules) + } + + if shipper.Partition != nil { + _ = d.Set("partition", shipper.Partition) + } + + if shipper.Compress != nil { + compress := map[string]interface{}{ + "format": shipper.Compress.Format, + } + _ = d.Set("compress", []interface{}{compress}) + } + + if shipper.Content != nil { + content := map[string]interface{}{ + "format": shipper.Content.Format, + } + if shipper.Content.Csv != nil { + csv := map[string]interface{}{ + "print_key": shipper.Content.Csv.PrintKey, + "keys": shipper.Content.Csv.Keys, + "delimiter": shipper.Content.Csv.Delimiter, + "escape_char": shipper.Content.Csv.EscapeChar, + "non_existing_field": shipper.Content.Csv.NonExistingField, + } + content["csv"] = []interface{}{csv} + } + if shipper.Content.Json != nil { + json := map[string]interface{}{ + "enable_tag": shipper.Content.Json.EnableTag, + "meta_fields": shipper.Content.Json.MetaFields, + } + content["json"] = []interface{}{json} + } + _ = d.Set("content", []interface{}{content}) + } + return nil +} + +func resourceTencentCloudClsCosShipperUpdate(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_cls_cos_shipper.update")() + logId := getLogId(contextNil) + request := cls.NewModifyShipperRequest() + + request.ShipperId = helper.String(d.Id()) + + if d.HasChange("bucket") { + if v, ok := d.GetOk("bucket"); ok { + request.Bucket = helper.String(v.(string)) + } + } + + if d.HasChange("prefix") { + if v, ok := d.GetOk("prefix"); ok { + request.Prefix = helper.String(v.(string)) + } + } + + if d.HasChange("shipper_name") { + if v, ok := d.GetOk("shipper_name"); ok { + request.ShipperName = helper.String(v.(string)) + } + } + + if d.HasChange("interval") { + if v, ok := d.GetOk("interval"); ok { + request.Interval = helper.IntUint64(v.(int)) + } + } + + if d.HasChange("max_size") { + if v, ok := d.GetOk("max_size"); ok { + request.MaxSize = helper.IntUint64(v.(int)) + } + } + + if d.HasChange("filter_rules") { + if v, ok := d.GetOk("filter_rules"); ok { + filterRules := make([]*cls.FilterRuleInfo, 0, 10) + for _, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + filterRule := cls.FilterRuleInfo{} + if v, ok := dMap["key"]; ok { + filterRule.Key = helper.String(v.(string)) + } + if v, ok := dMap["regex"]; ok { + filterRule.Regex = helper.String(v.(string)) + } + if v, ok := dMap["value"]; ok { + filterRule.Value = helper.String(v.(string)) + } + filterRules = append(filterRules, &filterRule) + } + request.FilterRules = filterRules + } + } + + if d.HasChange("partition") { + if v, ok := d.GetOk("partition"); ok { + request.Partition = helper.String(v.(string)) + } + } + + if d.HasChange("compress") { + if v, ok := d.GetOk("compress"); ok { + compresses := make([]*cls.CompressInfo, 0, 10) + if len(v.([]interface{})) != 1 { + return fmt.Errorf("need only one compress.") + } + for _, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + compress := cls.CompressInfo{} + if v, ok := dMap["format"]; ok { + compress.Format = helper.String(v.(string)) + } + compresses = append(compresses, &compress) + } + request.Compress = compresses[0] + } + } + + if d.HasChange("content") { + if v, ok := d.GetOk("content"); ok { + contents := make([]*cls.ContentInfo, 0, 10) + if len(v.([]interface{})) != 1 { + return fmt.Errorf("need only one content.") + } + for _, item := range v.([]interface{}) { + dMap := item.(map[string]interface{}) + content := cls.ContentInfo{} + if v, ok := dMap["format"]; ok { + content.Format = helper.String(v.(string)) + } + if v, ok := dMap["csv"]; ok { + if len(v.([]interface{})) == 1 { + csv := v.([]interface{})[0].(map[string]interface{}) + csvInfo := cls.CsvInfo{} + csvInfo.PrintKey = helper.Bool(csv["print_key"].(bool)) + keys := csv["keys"].(*schema.Set).List() + for _, key := range keys { + csvInfo.Keys = append(csvInfo.Keys, helper.String(key.(string))) + } + csvInfo.Delimiter = helper.String(csv["delimiter"].(string)) + csvInfo.EscapeChar = helper.String(csv["escape_char"].(string)) + csvInfo.NonExistingField = helper.String(csv["non_existing_field"].(string)) + content.Csv = &csvInfo + } + } + if v, ok := dMap["json"]; ok { + if len(v.([]interface{})) == 1 { + + json := v.([]interface{})[0].(map[string]interface{}) + jsonInfo := cls.JsonInfo{} + jsonInfo.EnableTag = helper.Bool(json["enable_tag"].(bool)) + metaFields := json["meta_fields"].(*schema.Set).List() + for _, metaField := range metaFields { + jsonInfo.MetaFields = append(jsonInfo.MetaFields, helper.String(metaField.(string))) + } + content.Json = &jsonInfo + } + } + contents = append(contents, &content) + } + request.Content = contents[0] + } + } + + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { + result, e := meta.(*TencentCloudClient).apiV3Conn.UseClsClient().ModifyShipper(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 resourceTencentCloudClsCosShipperRead(d, meta) +} + +func resourceTencentCloudClsCosShipperDelete(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_cls_cos_shipper.delete")() + + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + service := ClsService{client: meta.(*TencentCloudClient).apiV3Conn} + id := d.Id() + + if err := service.DeleteClsCosShipper(ctx, id); err != nil { + return err + } + + return nil +} diff --git a/tencentcloud/resource_tc_cls_cos_shipper_test.go b/tencentcloud/resource_tc_cls_cos_shipper_test.go new file mode 100644 index 0000000000..7277682f28 --- /dev/null +++ b/tencentcloud/resource_tc_cls_cos_shipper_test.go @@ -0,0 +1,111 @@ +package tencentcloud + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccTencentCloudClsCosShipper_basic(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccClsTopic, + Check: resource.ComposeTestCheckFunc( + testAccCheckClsCosShipperExists("tencentcloud_cls_cos_shipper.shipper"), + resource.TestCheckResourceAttr("tencentcloud_cls_cos_shipper.shipper", "shipper_name", "tf-shipper-test"), + ), + }, + { + ResourceName: "tencentcloud_cls_cos_shipper.shipper", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckClsCosShipperExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("[CHECK][CLS Cos Shipper][Exists] check: CLS Cos Shipper %s is not found", n) + } + if rs.Primary.ID == "" { + return fmt.Errorf("[CHECK][CLS Cos Shipper][Exists] check: CLS Cos Shipper id is not set") + } + clsService := ClsService{ + client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn, + } + instance, err := clsService.DescribeClsCosShipperById(ctx, rs.Primary.ID) + if err != nil { + return err + } + + if instance == nil { + return fmt.Errorf("[CHECK][CLS Cos Shipper][Exists] id %s is not exist", rs.Primary.ID) + } + return nil + } +} + +const testAccClsCosShipper = ` +resource "tencentcloud_cls_logset" "logset" { + logset_name = "tf-topic-test" + tags = { + "test" = "test" + } +} + +resource "tencentcloud_cls_topic" "topic" { + auto_split = true + logset_id = tencentcloud_cls_logset.logset.id + max_split_partitions = 20 + partition_count = 1 + period = 10 + storage_type = "hot" + tags = { + "test" = "test" + } + topic_name = "tf-topic-test" +} + +resource "tencentcloud_cls_cos_shipper" "shipper" { + bucket = "preset-scf-bucket-1308919341" + interval = 300 + max_size = 200 + partition = "/%Y/%m/%d/%H/" + prefix = "ap-guangzhou-fffsasad-1649734752" + shipper_name = "tf-shipper-test" + topic_id = tencentcloud_cls_topic.topic.id + + compress { + format = "lzop" + } + + content { + format = "json" + + json { + enable_tag = true + meta_fields = [ + "__FILENAME__", + "__SOURCE__", + "__TIMESTAMP__", + ] + } + } +} + + +` diff --git a/tencentcloud/resource_tc_cls_machine_group.go b/tencentcloud/resource_tc_cls_machine_group.go index a78c140bed..159f94a938 100644 --- a/tencentcloud/resource_tc_cls_machine_group.go +++ b/tencentcloud/resource_tc_cls_machine_group.go @@ -142,8 +142,8 @@ func resourceTencentCloudClsMachineGroupCreate(d *schema.ResourceData, meta inte for _, u := range v.([]interface{}) { machineGroupType.Values = append(machineGroupType.Values, helper.String(u.(string))) } - machineGroupTypes = append(machineGroupTypes, &machineGroupType) } + machineGroupTypes = append(machineGroupTypes, &machineGroupType) } request.MachineGroupType = machineGroupTypes[0] } diff --git a/tencentcloud/service_tencentcloud_cls.go b/tencentcloud/service_tencentcloud_cls.go index d149bb4bef..e7479ee49d 100644 --- a/tencentcloud/service_tencentcloud_cls.go +++ b/tencentcloud/service_tencentcloud_cls.go @@ -416,3 +416,134 @@ func (me *ClsService) DeleteClsMachineGroup(ctx context.Context, id string) (err return } + +// cls cos shipper +func (me *ClsService) DescribeClsCosShippersByFilter(ctx context.Context, filters map[string]string) (instances []*cls.ShipperInfo, errRet error) { + var ( + logId = getLogId(ctx) + request = cls.NewDescribeShippersRequest() + ) + 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.Filters = make([]*cls.Filter, 0, len(filters)) + for k, v := range filters { + filter := cls.Filter{ + Key: helper.String(k), + Values: []*string{helper.String(v)}, + } + request.Filters = append(request.Filters, &filter) + } + + var offset uint64 = 0 + var pageSize uint64 = 100 + instances = make([]*cls.ShipperInfo, 0) + + for { + request.Offset = &offset + request.Limit = &pageSize + ratelimit.Check(request.GetAction()) + response, err := me.client.UseClsClient().DescribeShippers(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, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if response == nil || len(response.Response.Shippers) < 1 { + break + } + instances = append(instances, response.Response.Shippers...) + if len(response.Response.Shippers) < int(pageSize) { + break + } + offset += pageSize + } + return +} + +func (me *ClsService) DescribeClsCosShipperById(ctx context.Context, shipperId string) (instance *cls.ShipperInfo, errRet error) { + var ( + logId = getLogId(ctx) + request = cls.NewDescribeShippersRequest() + ) + 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.Filters = []*cls.Filter{ + { + Key: common.StringPtr("shipperId"), + Values: []*string{&shipperId}, + }, + } + + var offset uint64 = 0 + var pageSize uint64 = 100 + instances := make([]*cls.ShipperInfo, 0) + + for { + request.Offset = &offset + request.Limit = &pageSize + ratelimit.Check(request.GetAction()) + response, err := me.client.UseClsClient().DescribeShippers(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, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if response == nil || len(response.Response.Shippers) < 1 { + break + } + instances = append(instances, response.Response.Shippers...) + if len(response.Response.Shippers) < int(pageSize) { + break + } + offset += pageSize + } + + if len(instances) < 0 { + return + } + instance = instances[0] + return +} + +func (me *ClsService) DeleteClsCosShipper(ctx context.Context, id string) (errRet error) { + logId := getLogId(ctx) + + request := cls.NewDeleteShipperRequest() + request.ShipperId = &id + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", + logId, "delete object", request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + response, err := me.client.UseClsClient().DeleteShipper(request) + if err != nil { + errRet = err + return err + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + return +} diff --git a/website/docs/r/cls_cos_shipper.html.markdown b/website/docs/r/cls_cos_shipper.html.markdown new file mode 100644 index 0000000000..5b1606204a --- /dev/null +++ b/website/docs/r/cls_cos_shipper.html.markdown @@ -0,0 +1,105 @@ +--- +subcategory: "CLS" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_cls_cos_shipper" +sidebar_current: "docs-tencentcloud-resource-cls_cos_shipper" +description: |- + Provides a resource to create a cls cos shipper. +--- + +# tencentcloud_cls_cos_shipper + +Provides a resource to create a cls cos shipper. + +## Example Usage + +```hcl +resource "tencentcloud_cls_cos_shipper" "shipper" { + bucket = "preset-scf-bucket-1308919341" + interval = 300 + max_size = 200 + partition = "/%Y/%m/%d/%H/" + prefix = "ap-guangzhou-fffsasad-1649734752" + shipper_name = "ap-guangzhou-fffsasad-1649734752" + topic_id = "4d07fba0-b93e-4e0b-9a7f-d58542560bbb" + + compress { + format = "lzop" + } + + content { + format = "json" + + json { + enable_tag = true + meta_fields = [ + "__FILENAME__", + "__SOURCE__", + "__TIMESTAMP__", + ] + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `bucket` - (Required) Destination bucket in the shipping rule to be created. +* `prefix` - (Required) Prefix of the shipping directory in the shipping rule to be created. +* `shipper_name` - (Required) Shipping rule name. +* `topic_id` - (Required) ID of the log topic to which the shipping rule to be created belongs. +* `compress` - (Optional) Compression configuration of shipped log. +* `content` - (Optional) Format configuration of shipped log content. +* `filter_rules` - (Optional) Filter rules for shipped logs. Only logs matching the rules can be shipped. All rules are in the AND relationship, and up to five rules can be added. If the array is empty, no filtering will be performed, and all logs will be shipped. +* `interval` - (Optional) Shipping time interval in seconds. Default value: 300. Value range: 300~900. +* `max_size` - (Optional) Maximum size of a file to be shipped, in MB. Default value: 256. Value range: 100~256. +* `partition` - (Optional) Partition rule of shipped log, which can be represented in strftime time format. + +The `compress` object supports the following: + +* `format` - (Required) Compression format. Valid values: gzip, lzop, none (no compression). + +The `content` object supports the following: + +* `format` - (Required) Content format. Valid values: json, csv. +* `csv` - (Optional) CSV format content description.Note: this field may return null, indicating that no valid values can be obtained. +* `json` - (Optional) JSON format content description.Note: this field may return null, indicating that no valid values can be obtained. + +The `csv` object supports the following: + +* `delimiter` - (Required) Field delimiter. +* `escape_char` - (Required) Field delimiter. +* `keys` - (Required) Names of keys.Note: this field may return null, indicating that no valid values can be obtained. +* `non_existing_field` - (Required) Content used to populate non-existing fields. +* `print_key` - (Required) Whether to print key on the first row of the CSV file. + +The `filter_rules` object supports the following: + +* `key` - (Required) Filter rule key. +* `regex` - (Required) Filter rule. +* `value` - (Required) Filter rule value. + +The `json` object supports the following: + +* `enable_tag` - (Required) Enablement flag. +* `meta_fields` - (Required) Metadata information list +Note: this field may return null, indicating that no valid values can be obtained.. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the resource. + + + +## Import + +cls cos shipper can be imported using the id, e.g. + +``` +$ terraform import tencentcloud_cls_cos_shipper.shipper 5d1b7b2a-c163-4c48-bb01-9ee00584d761 +``` + diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index 23938a185c..1dfb50b382 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -280,6 +280,9 @@
  • tencentcloud_cls_machine_group
  • +
  • + tencentcloud_cls_cos_shipper +