diff --git a/tencentcloud/common.go b/tencentcloud/common.go index c68d0bb345..8911fdfc76 100644 --- a/tencentcloud/common.go +++ b/tencentcloud/common.go @@ -306,3 +306,24 @@ func GetListIncrement(o []int, n []int) (result []int, err error) { } return } + +//GoRoutine Limit +type GoRoutineLimit struct { + Count int + Chan chan struct{} +} + +func NewGoRoutine(num int) *GoRoutineLimit { + return &GoRoutineLimit{ + Count: num, + Chan: make(chan struct{}, num), + } +} + +func (g *GoRoutineLimit) Run(f func()) { + g.Chan <- struct{}{} + go func() { + f() + <-g.Chan + }() +} diff --git a/tencentcloud/data_source_tc_cbs_storages_set.go b/tencentcloud/data_source_tc_cbs_storages_set.go new file mode 100644 index 0000000000..9ecd4333ce --- /dev/null +++ b/tencentcloud/data_source_tc_cbs_storages_set.go @@ -0,0 +1,307 @@ +/* +Use this data source to query detailed information of CBS storages in parallel. + +Example Usage + +```hcl +data "tencentcloud_cbs_storages_set" "storages" { + availability_zone = "ap-guangzhou-3" +} +``` + +*/ +package tencentcloud + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudCbsStoragesSet() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudCbsStoragesSetRead, + + Schema: map[string]*schema.Schema{ + "storage_id": { + Type: schema.TypeString, + Optional: true, + Description: "ID of the CBS to be queried.", + }, + "storage_name": { + Type: schema.TypeString, + Optional: true, + Description: "Name of the CBS to be queried.", + }, + "availability_zone": { + Type: schema.TypeString, + Optional: true, + Description: "The available zone that the CBS instance locates at.", + }, + "project_id": { + Type: schema.TypeInt, + Optional: true, + Description: "ID of the project with which the CBS is associated.", + }, + "storage_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateAllowedStringValue(CBS_STORAGE_TYPE), + Description: "Filter by cloud disk media type (`CLOUD_BASIC`: HDD cloud disk | `CLOUD_PREMIUM`: Premium Cloud Storage | `CLOUD_SSD`: SSD cloud disk).", + }, + "storage_usage": { + Type: schema.TypeString, + Optional: true, + Description: "Filter by cloud disk type (`SYSTEM_DISK`: system disk | `DATA_DISK`: data disk).", + }, + "charge_type": { + Type: schema.TypeList, + Optional: true, + Description: "List filter by disk charge type (`POSTPAID_BY_HOUR` | `PREPAID`).", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "portable": { + Type: schema.TypeBool, + Optional: true, + Description: "Filter by whether the disk is portable (Boolean `true` or `false`).", + }, + "storage_state": { + Type: schema.TypeList, + Optional: true, + Description: "List filter by disk state (`UNATTACHED` | `ATTACHING` | `ATTACHED` | `DETACHING` | `EXPANDING` | `ROLLBACKING` | `TORECYCLE`).", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "instance_ips": { + Type: schema.TypeList, + Optional: true, + Description: "List filter by attached instance public or private IPs.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "instance_name": { + Type: schema.TypeList, + Optional: true, + Description: "List filter by attached instance name.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "tag_keys": { + Type: schema.TypeList, + Optional: true, + Description: "List filter by tag keys.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "tag_values": { + Type: schema.TypeList, + Optional: true, + Description: "List filter by tag values.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + "storage_list": { + Type: schema.TypeList, + Computed: true, + Description: "A list of storage. Each element contains the following attributes:", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "storage_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of CBS.", + }, + "storage_name": { + Type: schema.TypeString, + Computed: true, + Description: "Name of CBS.", + }, + "storage_type": { + Type: schema.TypeString, + Computed: true, + Description: "Types of storage medium.", + }, + "storage_usage": { + Type: schema.TypeString, + Computed: true, + Description: "Types of CBS.", + }, + "availability_zone": { + Type: schema.TypeString, + Computed: true, + Description: "The zone of CBS.", + }, + "project_id": { + Type: schema.TypeInt, + Computed: true, + Description: "ID of the project.", + }, + "storage_size": { + Type: schema.TypeInt, + Computed: true, + Description: "Volume of CBS.", + }, + "attached": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the CBS is mounted the CVM.", + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the CVM instance that be mounted by this CBS.", + }, + "encrypt": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether CBS is encrypted.", + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: "Creation time of CBS.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "Status of CBS.", + }, + "tags": { + Type: schema.TypeMap, + Computed: true, + Description: "The available tags within this CBS.", + }, + "prepaid_renew_flag": { + Type: schema.TypeString, + Computed: true, + Description: "The way that CBS instance will be renew automatically or not when it reach the end of the prepaid tenancy.", + }, + "charge_type": { + Type: schema.TypeString, + Computed: true, + Description: "Pay type of the CBS instance.", + }, + "throughput_performance": { + Type: schema.TypeInt, + Computed: true, + Description: "Add extra performance to the data disk. Only works when disk type is `CLOUD_TSSD` or `CLOUD_HSSD`.", + }, + }, + }, + }, + }, + } +} + +func dataSourceTencentCloudCbsStoragesSetRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("data_source.tencentcloud_cbs_storages.read")() + + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + + params := make(map[string]interface{}) + if v, ok := d.GetOk("storage_id"); ok { + params["disk-id"] = v.(string) + } + if v, ok := d.GetOk("storage_name"); ok { + params["disk-name"] = v.(string) + } + if v, ok := d.GetOk("availability_zone"); ok { + params["zone"] = v.(string) + } + if v, ok := d.GetOkExists("project_id"); ok { + params["project-id"] = fmt.Sprintf("%d", v.(int)) + } + if v, ok := d.GetOk("storage_type"); ok { + params["disk-type"] = v.(string) + } + if v, ok := d.GetOk("storage_usage"); ok { + params["disk-usage"] = v.(string) + } + + if v, ok := d.GetOk("charge_type"); ok { + params["disk-charge-type"] = helper.InterfacesStringsPoint(v.([]interface{})) + } + + if v, ok := d.GetOk("portable"); ok { + if v.(bool) { + params["portable"] = "TRUE" + } else { + params["portable"] = "FALSE" + } + } + + if v, ok := d.GetOk("storage_state"); ok { + params["disk-state"] = helper.InterfacesStringsPoint(v.([]interface{})) + } + if v, ok := d.GetOk("instance_ips"); ok { + params["instance-ip-address"] = helper.InterfacesStringsPoint(v.([]interface{})) + } + if v, ok := d.GetOk("instance_name"); ok { + params["instance-name"] = helper.InterfacesStringsPoint(v.([]interface{})) + } + if v, ok := d.GetOk("tag_keys"); ok { + params["tag-key"] = helper.InterfacesStringsPoint(v.([]interface{})) + } + if v, ok := d.GetOk("tag_values"); ok { + params["tag-value"] = helper.InterfacesStringsPoint(v.([]interface{})) + } + + cbsService := CbsService{ + client: meta.(*TencentCloudClient).apiV3Conn, + } + + storages, e := cbsService.DescribeDisksInParallelByFilter(ctx, params) + if e != nil { + return e + } + ids := make([]string, 0, len(storages)) + storageList := make([]map[string]interface{}, 0, len(storages)) + for _, storage := range storages { + mapping := map[string]interface{}{ + "storage_id": storage.DiskId, + "storage_name": storage.DiskName, + "storage_usage": storage.DiskUsage, + "storage_type": storage.DiskType, + "availability_zone": storage.Placement.Zone, + "project_id": storage.Placement.ProjectId, + "storage_size": storage.DiskSize, + "attached": storage.Attached, + "instance_id": storage.InstanceId, + "encrypt": storage.Encrypt, + "create_time": storage.CreateTime, + "status": storage.DiskState, + "prepaid_renew_flag": storage.RenewFlag, + "charge_type": storage.DiskChargeType, + "throughput_performance": storage.ThroughputPerformance, + } + if storage.Tags != nil { + tags := make(map[string]interface{}, len(storage.Tags)) + for _, t := range storage.Tags { + tags[*t.Key] = *t.Value + } + mapping["tags"] = tags + } + storageList = append(storageList, mapping) + ids = append(ids, *storage.DiskId) + } + + d.SetId(helper.DataResourceIdsHash(ids)) + if e = d.Set("storage_list", storageList); e != nil { + log.Printf("[CRITAL]%s provider set storage list fail, reason:%s\n ", logId, e.Error()) + return e + } + + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if e := writeToFile(output.(string), storageList); e != nil { + return e + } + } + + return nil + +} diff --git a/tencentcloud/data_source_tc_instances_set.go b/tencentcloud/data_source_tc_instances_set.go new file mode 100644 index 0000000000..1bbe88a16e --- /dev/null +++ b/tencentcloud/data_source_tc_instances_set.go @@ -0,0 +1,353 @@ +/* +Use this data source to query cvm instances in parallel. + +Example Usage + +```hcl +data "tencentcloud_instances_set" "foo" { + vpc_id = "vpc-4owdpnwr" +} +``` +*/ +package tencentcloud + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudInstancesSet() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudInstancesSetRead, + + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "ID of the instances to be queried.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateStringLengthInRange(1, 30), + Description: "Name of the instances to be queried.", + }, + "availability_zone": { + Type: schema.TypeString, + Optional: true, + Description: "The available zone that the CVM instance locates at.", + }, + "project_id": { + Type: schema.TypeInt, + Optional: true, + Description: "The project CVM belongs to.", + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Description: "ID of the vpc to be queried.", + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + Description: "ID of a vpc subnetwork.", + }, + "tags": { + Type: schema.TypeMap, + Optional: true, + Description: "Tags of the instance.", + }, + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + + // computed + "instance_list": { + Type: schema.TypeList, + Computed: true, + Description: "An information list of cvm instance. Each element contains the following attributes:", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the instances.", + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: "Name of the instances.", + }, + "instance_type": { + Type: schema.TypeString, + Computed: true, + Description: "Type of the instance.", + }, + "cpu": { + Type: schema.TypeInt, + Computed: true, + Description: "The number of CPU cores of the instance.", + }, + "memory": { + Type: schema.TypeInt, + Computed: true, + Description: "Instance memory capacity, unit in GB.", + }, + "availability_zone": { + Type: schema.TypeString, + Computed: true, + Description: "The available zone that the CVM instance locates at.", + }, + "project_id": { + Type: schema.TypeInt, + Computed: true, + Description: "The project CVM belongs to.", + }, + "image_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the image.", + }, + "instance_charge_type": { + Type: schema.TypeString, + Computed: true, + Description: "The charge type of the instance.", + }, + "system_disk_type": { + Type: schema.TypeString, + Computed: true, + Description: "Type of the system disk.", + }, + "system_disk_size": { + Type: schema.TypeInt, + Computed: true, + Description: "Size of the system disk.", + }, + "system_disk_id": { + Type: schema.TypeString, + Computed: true, + Description: "Image ID of the system disk.", + }, + "data_disks": { + Type: schema.TypeList, + Computed: true, + Description: "An information list of data disk. Each element contains the following attributes:", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data_disk_type": { + Type: schema.TypeString, + Computed: true, + Description: "Type of the data disk.", + }, + "data_disk_size": { + Type: schema.TypeInt, + Computed: true, + Description: "Size of the data disk.", + }, + "data_disk_id": { + Type: schema.TypeString, + Computed: true, + Description: "Image ID of the data disk.", + }, + "delete_with_instance": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether the data disk is destroyed with the instance.", + }, + }, + }, + }, + "vpc_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of the vpc.", + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + Description: "ID of a vpc subnetwork.", + }, + "internet_charge_type": { + Type: schema.TypeString, + Computed: true, + Description: "The charge type of the instance.", + }, + "internet_max_bandwidth_out": { + Type: schema.TypeInt, + Computed: true, + Description: "Public network maximum output bandwidth of the instance.", + }, + "allocate_public_ip": { + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether public ip is assigned.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "Status of the instance.", + }, + "public_ip": { + Type: schema.TypeString, + Computed: true, + Description: "Public IP of the instance.", + }, + "private_ip": { + Type: schema.TypeString, + Computed: true, + Description: "Private IP of the instance.", + }, + "security_groups": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "Security groups of the instance.", + }, + "tags": { + Type: schema.TypeMap, + Computed: true, + Description: "Tags of the instance.", + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: "Creation time of the instance.", + }, + "expired_time": { + Type: schema.TypeString, + Computed: true, + Description: "Expired time of the instance.", + }, + "instance_charge_type_prepaid_renew_flag": { + Type: schema.TypeString, + Computed: true, + Description: "The way that CVM instance will be renew automatically or not when it reach the end of the prepaid tenancy.", + }, + "cam_role_name": { + Type: schema.TypeString, + Computed: true, + Description: "CAM role name authorized to access.", + }, + }, + }, + }, + }, + } +} + +func dataSourceTencentCloudInstancesSetRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("data_source.tencentcloud_instances_set.read")() + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + cvmService := CvmService{ + client: meta.(*TencentCloudClient).apiV3Conn, + } + + filter := make(map[string]string) + if v, ok := d.GetOk("instance_id"); ok { + filter["instance-id"] = v.(string) + } + if v, ok := d.GetOk("instance_name"); ok { + filter["instance-name"] = v.(string) + } + if v, ok := d.GetOk("availability_zone"); ok { + filter["zone"] = v.(string) + } + if v, ok := d.GetOkExists("project_id"); ok { + filter["project-id"] = fmt.Sprintf("%d", v.(int)) + } + if v, ok := d.GetOk("vpc_id"); ok { + filter["vpc-id"] = v.(string) + } + if v, ok := d.GetOk("subnet_id"); ok { + filter["subnet-id"] = v.(string) + } + + if v, ok := d.GetOk("tags"); ok { + for key, value := range v.(map[string]interface{}) { + filter["tag:"+key] = value.(string) + } + } + + var instances []*cvm.Instance + var errRet error + + instances, errRet = cvmService.DescribeInstanceInParallelByFilter(ctx, filter) + + if errRet != nil { + return errRet + } + + instanceList := make([]map[string]interface{}, 0, len(instances)) + ids := make([]string, 0, len(instances)) + for _, instance := range instances { + mapping := map[string]interface{}{ + "instance_id": instance.InstanceId, + "instance_name": instance.InstanceName, + "instance_type": instance.InstanceType, + "cpu": instance.CPU, + "memory": instance.Memory, + "availability_zone": instance.Placement.Zone, + "project_id": instance.Placement.ProjectId, + "image_id": instance.ImageId, + "instance_charge_type": instance.InstanceChargeType, + "system_disk_type": instance.SystemDisk.DiskType, + "system_disk_size": instance.SystemDisk.DiskSize, + "system_disk_id": instance.SystemDisk.DiskId, + "vpc_id": instance.VirtualPrivateCloud.VpcId, + "subnet_id": instance.VirtualPrivateCloud.SubnetId, + "internet_charge_type": instance.InternetAccessible.InternetChargeType, + "internet_max_bandwidth_out": instance.InternetAccessible.InternetMaxBandwidthOut, + "allocate_public_ip": instance.InternetAccessible.PublicIpAssigned, + "status": instance.InstanceState, + "security_groups": helper.StringsInterfaces(instance.SecurityGroupIds), + "tags": flattenCvmTagsMapping(instance.Tags), + "create_time": instance.CreatedTime, + "expired_time": instance.ExpiredTime, + "instance_charge_type_prepaid_renew_flag": instance.RenewFlag, + "cam_role_name": instance.CamRoleName, + } + if len(instance.PublicIpAddresses) > 0 { + mapping["public_ip"] = *instance.PublicIpAddresses[0] + } + if len(instance.PrivateIpAddresses) > 0 { + mapping["private_ip"] = *instance.PrivateIpAddresses[0] + } + dataDisks := make([]map[string]interface{}, 0, len(instance.DataDisks)) + for _, v := range instance.DataDisks { + dataDisk := map[string]interface{}{ + "data_disk_type": v.DiskType, + "data_disk_size": v.DiskSize, + "data_disk_id": v.DiskId, + "delete_with_instance": v.DeleteWithInstance, + } + dataDisks = append(dataDisks, dataDisk) + } + mapping["data_disks"] = dataDisks + instanceList = append(instanceList, mapping) + ids = append(ids, *instance.InstanceId) + } + + d.SetId(helper.DataResourceIdsHash(ids)) + err := d.Set("instance_list", instanceList) + if err != nil { + log.Printf("[CRITAL]%s provider set instance list fail, reason:%s\n ", logId, err.Error()) + return err + } + + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if err := writeToFile(output.(string), instanceList); err != nil { + return err + } + } + return nil + +} diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index e08d9063ea..51556c1fde 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -176,6 +176,7 @@ Cloud Block Storage(CBS) Data Source tencentcloud_cbs_snapshots tencentcloud_cbs_storages + tencentcloud_cbs_storages_set tencentcloud_cbs_snapshot_policies Resource @@ -264,6 +265,7 @@ Cloud Virtual Machine(CVM) tencentcloud_images tencentcloud_instance_types tencentcloud_instances + tencentcloud_instances_set tencentcloud_key_pairs tencentcloud_eip tencentcloud_eips @@ -750,6 +752,7 @@ func Provider() terraform.ResourceProvider { "tencentcloud_availability_zones": dataSourceTencentCloudAvailabilityZones(), "tencentcloud_availability_zones_by_product": dataSourceTencentCloudAvailabilityZonesByProduct(), "tencentcloud_instances": dataSourceTencentCloudInstances(), + "tencentcloud_instances_set": dataSourceTencentCloudInstancesSet(), "tencentcloud_reserved_instances": dataSourceTencentCloudReservedInstances(), "tencentcloud_placement_groups": dataSourceTencentCloudPlacementGroups(), "tencentcloud_key_pairs": dataSourceTencentCloudKeyPairs(), @@ -810,6 +813,7 @@ func Provider() terraform.ResourceProvider { "tencentcloud_as_scaling_groups": dataSourceTencentCloudAsScalingGroups(), "tencentcloud_as_scaling_policies": dataSourceTencentCloudAsScalingPolicies(), "tencentcloud_cbs_storages": dataSourceTencentCloudCbsStorages(), + "tencentcloud_cbs_storages_set": dataSourceTencentCloudCbsStoragesSet(), "tencentcloud_cbs_snapshots": dataSourceTencentCloudCbsSnapshots(), "tencentcloud_cbs_snapshot_policies": dataSourceTencentCloudCbsSnapshotPolicies(), "tencentcloud_clb_instances": dataSourceTencentCloudClbInstances(), diff --git a/tencentcloud/service_tencentcloud_cbs.go b/tencentcloud/service_tencentcloud_cbs.go index f374da76e5..4db396cf56 100644 --- a/tencentcloud/service_tencentcloud_cbs.go +++ b/tencentcloud/service_tencentcloud_cbs.go @@ -3,6 +3,7 @@ package tencentcloud import ( "context" "log" + "sync" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" cbs "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs/v20170312" @@ -117,6 +118,93 @@ func (me *CbsService) DescribeDisksByFilter(ctx context.Context, params map[stri return } +func (me *CbsService) DescribeDisksInParallelByFilter(ctx context.Context, params map[string]interface{}) (disks []*cbs.Disk, errRet error) { + logId := getLogId(ctx) + request := cbs.NewDescribeDisksRequest() + + request.Filters = make([]*cbs.Filter, 0, len(params)) + for k, v := range params { + filter := &cbs.Filter{ + Name: helper.String(k), + } + switch v.(type) { + case string: + filter.Values = []*string{helper.String(v.(string))} + case []*string: + filter.Values = v.([]*string) + } + request.Filters = append(request.Filters, filter) + } + response, err := me.client.UseCbsClient().DescribeDisks(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 + } + + if response == nil || len(response.Response.DiskSet) < 1 { + return + } + + total := response.Response.TotalCount + + var limit = 100 + num := int(*total) / limit + g := NewGoRoutine(num + 1) + wg := sync.WaitGroup{} + + var diskSetList = make([]interface{}, num+1) + + for i := 0; i <= num; i++ { + wg.Add(1) + value := i + goFunc := func() { + offset := value * limit + request := cbs.NewDescribeDisksRequest() + request.Filters = make([]*cbs.Filter, 0, len(params)) + for k, v := range params { + filter := &cbs.Filter{ + Name: helper.String(k), + } + switch v.(type) { + case string: + filter.Values = []*string{helper.String(v.(string))} + case []*string: + filter.Values = v.([]*string) + } + request.Filters = append(request.Filters, filter) + } + + request.Offset = helper.IntUint64(offset) + request.Limit = helper.IntUint64(limit) + + ratelimit.Check(request.GetAction()) + response, err := me.client.UseCbsClient().DescribeDisks(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()) + + diskSetList[value] = response.Response.DiskSet + + wg.Done() + } + g.Run(goFunc) + } + wg.Wait() + + for _, v := range diskSetList { + disks = append(disks, v.([]*cbs.Disk)...) + } + + return +} + func (me *CbsService) ModifyDiskAttributes(ctx context.Context, diskId, diskName string, projectId int) error { logId := getLogId(ctx) request := cbs.NewModifyDiskAttributesRequest() diff --git a/tencentcloud/service_tencentcloud_cvm.go b/tencentcloud/service_tencentcloud_cvm.go index 1dd8706b4f..0c837a6b94 100644 --- a/tencentcloud/service_tencentcloud_cvm.go +++ b/tencentcloud/service_tencentcloud_cvm.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "sort" + "sync" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -122,6 +123,84 @@ func (me *CvmService) DescribeInstanceByFilter(ctx context.Context, instancesId return } +func (me *CvmService) DescribeInstanceInParallelByFilter(ctx context.Context, filters map[string]string) (instances []*cvm.Instance, errRet error) { + logId := getLogId(ctx) + request := cvm.NewDescribeInstancesRequest() + + request.Filters = make([]*cvm.Filter, 0, len(filters)) + for k, v := range filters { + filter := cvm.Filter{ + Name: helper.String(k), + Values: []*string{helper.String(v)}, + } + request.Filters = append(request.Filters, &filter) + } + + response, err := me.client.UseCvmClient().DescribeInstances(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 + } + if response == nil || len(response.Response.InstanceSet) < 1 { + return + } + + total := response.Response.TotalCount + + var limit = 100 + + num := int(*total) / limit + + g := NewGoRoutine(num + 1) + wg := sync.WaitGroup{} + + var instanceSetList = make([]interface{}, num+1) + + for i := 0; i <= num; i++ { + wg.Add(1) + value := i + goFunc := func() { + offset := value * limit + request := cvm.NewDescribeInstancesRequest() + request.Filters = make([]*cvm.Filter, 0, len(filters)) + for k, v := range filters { + filter := cvm.Filter{ + Name: helper.String(k), + Values: []*string{helper.String(v)}, + } + request.Filters = append(request.Filters, &filter) + } + + request.Offset = helper.IntInt64(offset) + request.Limit = helper.IntInt64(limit) + + ratelimit.Check(request.GetAction()) + response, err := me.client.UseCvmClient().DescribeInstances(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()) + + instanceSetList[value] = response.Response.InstanceSet + + wg.Done() + } + g.Run(goFunc) + } + wg.Wait() + + for _, v := range instanceSetList { + instances = append(instances, v.([]*cvm.Instance)...) + } + return +} + func (me *CvmService) ModifyInstanceName(ctx context.Context, instanceId, instanceName string) error { logId := getLogId(ctx) request := cvm.NewModifyInstancesAttributeRequest() diff --git a/website/docs/d/cbs_storages_set.html.markdown b/website/docs/d/cbs_storages_set.html.markdown new file mode 100644 index 0000000000..8cb01e5991 --- /dev/null +++ b/website/docs/d/cbs_storages_set.html.markdown @@ -0,0 +1,63 @@ +--- +subcategory: "Cloud Block Storage(CBS)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_cbs_storages_set" +sidebar_current: "docs-tencentcloud-datasource-cbs_storages_set" +description: |- + Use this data source to query detailed information of CBS storages in parallel. +--- + +# tencentcloud_cbs_storages_set + +Use this data source to query detailed information of CBS storages in parallel. + +## Example Usage + +```hcl +data "tencentcloud_cbs_storages_set" "storages" { + availability_zone = "ap-guangzhou-3" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `availability_zone` - (Optional) The available zone that the CBS instance locates at. +* `charge_type` - (Optional) List filter by disk charge type (`POSTPAID_BY_HOUR` | `PREPAID`). +* `instance_ips` - (Optional) List filter by attached instance public or private IPs. +* `instance_name` - (Optional) List filter by attached instance name. +* `portable` - (Optional) Filter by whether the disk is portable (Boolean `true` or `false`). +* `project_id` - (Optional) ID of the project with which the CBS is associated. +* `result_output_file` - (Optional) Used to save results. +* `storage_id` - (Optional) ID of the CBS to be queried. +* `storage_name` - (Optional) Name of the CBS to be queried. +* `storage_state` - (Optional) List filter by disk state (`UNATTACHED` | `ATTACHING` | `ATTACHED` | `DETACHING` | `EXPANDING` | `ROLLBACKING` | `TORECYCLE`). +* `storage_type` - (Optional) Filter by cloud disk media type (`CLOUD_BASIC`: HDD cloud disk | `CLOUD_PREMIUM`: Premium Cloud Storage | `CLOUD_SSD`: SSD cloud disk). +* `storage_usage` - (Optional) Filter by cloud disk type (`SYSTEM_DISK`: system disk | `DATA_DISK`: data disk). +* `tag_keys` - (Optional) List filter by tag keys. +* `tag_values` - (Optional) List filter by tag values. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `storage_list` - A list of storage. Each element contains the following attributes: + * `attached` - Indicates whether the CBS is mounted the CVM. + * `availability_zone` - The zone of CBS. + * `charge_type` - Pay type of the CBS instance. + * `create_time` - Creation time of CBS. + * `encrypt` - Indicates whether CBS is encrypted. + * `instance_id` - ID of the CVM instance that be mounted by this CBS. + * `prepaid_renew_flag` - The way that CBS instance will be renew automatically or not when it reach the end of the prepaid tenancy. + * `project_id` - ID of the project. + * `status` - Status of CBS. + * `storage_id` - ID of CBS. + * `storage_name` - Name of CBS. + * `storage_size` - Volume of CBS. + * `storage_type` - Types of storage medium. + * `storage_usage` - Types of CBS. + * `tags` - The available tags within this CBS. + * `throughput_performance` - Add extra performance to the data disk. Only works when disk type is `CLOUD_TSSD` or `CLOUD_HSSD`. + + diff --git a/website/docs/d/instances_set.html.markdown b/website/docs/d/instances_set.html.markdown new file mode 100644 index 0000000000..e08c0efdaf --- /dev/null +++ b/website/docs/d/instances_set.html.markdown @@ -0,0 +1,72 @@ +--- +subcategory: "Cloud Virtual Machine(CVM)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_instances_set" +sidebar_current: "docs-tencentcloud-datasource-instances_set" +description: |- + Use this data source to query cvm instances in parallel. +--- + +# tencentcloud_instances_set + +Use this data source to query cvm instances in parallel. + +## Example Usage + +```hcl +data "tencentcloud_instances_set" "foo" { + vpc_id = "vpc-4owdpnwr" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `availability_zone` - (Optional) The available zone that the CVM instance locates at. +* `instance_id` - (Optional) ID of the instances to be queried. +* `instance_name` - (Optional) Name of the instances to be queried. +* `project_id` - (Optional) The project CVM belongs to. +* `result_output_file` - (Optional) Used to save results. +* `subnet_id` - (Optional) ID of a vpc subnetwork. +* `tags` - (Optional) Tags of the instance. +* `vpc_id` - (Optional) ID of the vpc to be queried. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `instance_list` - An information list of cvm instance. Each element contains the following attributes: + * `allocate_public_ip` - Indicates whether public ip is assigned. + * `availability_zone` - The available zone that the CVM instance locates at. + * `cam_role_name` - CAM role name authorized to access. + * `cpu` - The number of CPU cores of the instance. + * `create_time` - Creation time of the instance. + * `data_disks` - An information list of data disk. Each element contains the following attributes: + * `data_disk_id` - Image ID of the data disk. + * `data_disk_size` - Size of the data disk. + * `data_disk_type` - Type of the data disk. + * `delete_with_instance` - Indicates whether the data disk is destroyed with the instance. + * `expired_time` - Expired time of the instance. + * `image_id` - ID of the image. + * `instance_charge_type_prepaid_renew_flag` - The way that CVM instance will be renew automatically or not when it reach the end of the prepaid tenancy. + * `instance_charge_type` - The charge type of the instance. + * `instance_id` - ID of the instances. + * `instance_name` - Name of the instances. + * `instance_type` - Type of the instance. + * `internet_charge_type` - The charge type of the instance. + * `internet_max_bandwidth_out` - Public network maximum output bandwidth of the instance. + * `memory` - Instance memory capacity, unit in GB. + * `private_ip` - Private IP of the instance. + * `project_id` - The project CVM belongs to. + * `public_ip` - Public IP of the instance. + * `security_groups` - Security groups of the instance. + * `status` - Status of the instance. + * `subnet_id` - ID of a vpc subnetwork. + * `system_disk_id` - Image ID of the system disk. + * `system_disk_size` - Size of the system disk. + * `system_disk_type` - Type of the system disk. + * `tags` - Tags of the instance. + * `vpc_id` - ID of the vpc. + + diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index 41bb47d9bf..3fcc6bdbb2 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -452,6 +452,9 @@