diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions.go b/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions.go index a50dd1b8c1..2e7c1c2b16 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions.go @@ -1,14 +1,14 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -17,17 +17,17 @@ func DataSourceTencentCloudCvmChcDeniedActions() *schema.Resource { Read: dataSourceTencentCloudCvmChcDeniedActionsRead, Schema: map[string]*schema.Schema{ "chc_ids": { - Required: true, - Type: schema.TypeSet, + Type: schema.TypeSet, + Required: true, + Description: "CHC host IDs.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "CHC host IDs.", }, "chc_host_denied_action_set": { - Computed: true, Type: schema.TypeList, + Computed: true, Description: "Actions not allowed for the CHC instance.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -42,12 +42,12 @@ func DataSourceTencentCloudCvmChcDeniedActions() *schema.Resource { Description: "CHC instance status.", }, "deny_actions": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Actions not allowed for the current CHC instance.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Actions not allowed for the current CHC instance.", }, }, }, @@ -66,64 +66,70 @@ func dataSourceTencentCloudCvmChcDeniedActionsRead(d *schema.ResourceData, meta defer tccommon.LogElapsed("data_source.tencentcloud_cvm_chc_denied_actions.read")() defer tccommon.InconsistentCheck(d, meta)() - logId := tccommon.GetLogId(tccommon.ContextNil) + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} paramMap := make(map[string]interface{}) if v, ok := d.GetOk("chc_ids"); ok { + chcIdsList := []*string{} chcIdsSet := v.(*schema.Set).List() - paramMap["chc_ids"] = helper.InterfacesStrings(chcIdsSet) + for i := range chcIdsSet { + chcIds := chcIdsSet[i].(string) + chcIdsList = append(chcIdsList, helper.String(chcIds)) + } + paramMap["ChcIds"] = chcIdsList } - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - - var chcHostDeniedActionSet []*cvm.ChcHostDeniedActions - + var respData []*cvm.ChcHostDeniedActions err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { result, e := service.DescribeCvmChcDeniedActionsByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - chcHostDeniedActionSet = result + respData = result return nil }) if err != nil { return err } - ids := make([]string, 0, len(chcHostDeniedActionSet)) - tmpList := make([]map[string]interface{}, 0, len(chcHostDeniedActionSet)) - - if len(chcHostDeniedActionSet) > 0 { - for _, chcHostDeniedActions := range chcHostDeniedActionSet { - chcHostDeniedActionsMap := map[string]interface{}{} + chcIds := make([]string, 0, len(respData)) + chcHostDeniedActionSetList := make([]map[string]interface{}, 0, len(respData)) + if respData != nil { + for _, chcHostDeniedActionSet := range respData { + chcHostDeniedActionSetMap := map[string]interface{}{} - if chcHostDeniedActions.ChcId != nil { - chcHostDeniedActionsMap["chc_id"] = chcHostDeniedActions.ChcId + var chcId string + if chcHostDeniedActionSet.ChcId != nil { + chcHostDeniedActionSetMap["chc_id"] = chcHostDeniedActionSet.ChcId + chcId = *chcHostDeniedActionSet.ChcId } - if chcHostDeniedActions.State != nil { - chcHostDeniedActionsMap["state"] = chcHostDeniedActions.State + if chcHostDeniedActionSet.State != nil { + chcHostDeniedActionSetMap["state"] = chcHostDeniedActionSet.State } - if chcHostDeniedActions.DenyActions != nil { - chcHostDeniedActionsMap["deny_actions"] = chcHostDeniedActions.DenyActions + if chcHostDeniedActionSet.DenyActions != nil { + chcHostDeniedActionSetMap["deny_actions"] = chcHostDeniedActionSet.DenyActions } - ids = append(ids, *chcHostDeniedActions.ChcId) - tmpList = append(tmpList, chcHostDeniedActionsMap) + chcIds = append(chcIds, chcId) + chcHostDeniedActionSetList = append(chcHostDeniedActionSetList, chcHostDeniedActionSetMap) } - _ = d.Set("chc_host_denied_action_set", tmpList) + _ = d.Set("chc_host_denied_action_set", chcHostDeniedActionSetList) } - d.SetId(helper.DataResourceIdsHash(ids)) + d.SetId(helper.DataResourceIdsHash(chcIds)) + output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), tmpList); e != nil { + if e := tccommon.WriteToFile(output.(string), chcHostDeniedActionSetList); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions_extension.go b/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_cvm_chc_denied_actions_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts.go b/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts.go index bf38017e13..049f9ea7a9 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts.go @@ -1,14 +1,14 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -17,23 +17,18 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Read: dataSourceTencentCloudCvmChcHostsRead, Schema: map[string]*schema.Schema{ "chc_ids": { - Optional: true, - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Description: "CHC host ID. Up to 100 instances per request is allowed. ChcIds and Filters cannot be specified at the same time.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "CHC host ID. Up to 100 instances per request is allowed. ChcIds and Filters cannot be specified at the same time.", }, "filters": { - Optional: true, - Type: schema.TypeList, - Description: "- `zone` Filter by the availability zone, such as ap-guangzhou-1. Valid values: See [Regions and Availability Zones](https://www.tencentcloud.com/document/product/213/6091?from_cn_redirect=1).\n" + - "- `instance-name` Filter by the instance name.\n" + - "- `instance-state` Filter by the instance status. For status details, see [InstanceStatus](https://www.tencentcloud.com/document/api/213/15753?from_cn_redirect=1#InstanceStatus).\n" + - "- `device-type` Filter by the device type.\n" + - "- `vpc-id` Filter by the unique VPC ID.\n" + - "- `subnet-id` Filter by the unique VPC subnet ID.", + Type: schema.TypeList, + Optional: true, + Description: "- `zone` Filter by the availability zone, such as ap-guangzhou-1. Valid values: See [Regions and Availability Zones](https://www.tencentcloud.com/document/product/213/6091?from_cn_redirect=1).\n- `instance-name` Filter by the instance name.\n- `instance-state` Filter by the instance status. For status details, see [InstanceStatus](https://www.tencentcloud.com/document/api/213/15753?from_cn_redirect=1#InstanceStatus).\n- `device-type` Filter by the device type.\n- `vpc-id` Filter by the unique VPC ID.\n- `subnet-id` Filter by the unique VPC subnet ID.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -42,20 +37,20 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Description: "Filter name.", }, "values": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Required: true, + Description: "Filter values.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Required: true, - Description: "Filter values.", }, }, }, }, "chc_host_set": { - Computed: true, Type: schema.TypeList, + Computed: true, Description: "List of returned instances.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -101,20 +96,20 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Description: "ID of the project to which the instance belongs. This parameter can be obtained from the projectId returned by DescribeProject. If this is left empty, the default project is used.", }, "host_ids": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "ID list of CDHs from which the instance can be created. If you have purchased CDHs and specify this parameter, the instances you purchase will be randomly deployed on the CDHs.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "ID list of CDHs from which the instance can be created. If you have purchased CDHs and specify this parameter, the instances you purchase will be randomly deployed on the CDHs.", }, "host_ips": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "IPs of the hosts to create CVMs.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "IPs of the hosts to create CVMs.", }, "host_id": { Type: schema.TypeString, @@ -146,12 +141,12 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Description: "Whether to use a CVM instance as a public gateway. The public gateway is only available when the instance has a public IP and resides in a VPC. Valid values:<br><li>TRUE: yes;<br><li>FALSE: no<br><br>Default: FALSE.", }, "private_ip_addresses": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Array of VPC subnet IPs. You can use this parameter when creating instances or modifying VPC attributes of instances. Currently you can specify multiple IPs in one subnet only when creating multiple instances at the same time.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Array of VPC subnet IPs. You can use this parameter when creating instances or modifying VPC attributes of instances. Currently you can specify multiple IPs in one subnet only when creating multiple instances at the same time.", }, "ipv6_address_count": { Type: schema.TypeInt, @@ -167,12 +162,12 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Description: "Out-of-band network IPNote: This field may return null, indicating that no valid values can be obtained.", }, "bmc_security_group_ids": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Out-of-band network security group IDNote: This field may return null, indicating that no valid values can be obtained.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Out-of-band network security group IDNote: This field may return null, indicating that no valid values can be obtained.", }, "deploy_virtual_private_cloud": { Type: schema.TypeList, @@ -196,12 +191,12 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Description: "Whether to use a CVM instance as a public gateway. The public gateway is only available when the instance has a public IP and resides in a VPC. Valid values:<br><li>TRUE: yes;<br><li>FALSE: no<br><br>Default: FALSE.", }, "private_ip_addresses": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Array of VPC subnet IPs. You can use this parameter when creating instances or modifying VPC attributes of instances. Currently you can specify multiple IPs in one subnet only when creating multiple instances at the same time.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Array of VPC subnet IPs. You can use this parameter when creating instances or modifying VPC attributes of instances. Currently you can specify multiple IPs in one subnet only when creating multiple instances at the same time.", }, "ipv6_address_count": { Type: schema.TypeInt, @@ -217,12 +212,12 @@ func DataSourceTencentCloudCvmChcHosts() *schema.Resource { Description: "Deployment network IPNote: This field may return null, indicating that no valid values can be obtained.", }, "deploy_security_group_ids": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Deployment network security group IDNote: This field may return null, indicating that no valid values can be obtained.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Deployment network security group IDNote: This field may return null, indicating that no valid values can be obtained.", }, "cvm_instance_id": { Type: schema.TypeString, @@ -286,222 +281,229 @@ func dataSourceTencentCloudCvmChcHostsRead(d *schema.ResourceData, meta interfac defer tccommon.LogElapsed("data_source.tencentcloud_cvm_chc_hosts.read")() defer tccommon.InconsistentCheck(d, meta)() - logId := tccommon.GetLogId(tccommon.ContextNil) + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} paramMap := make(map[string]interface{}) if v, ok := d.GetOk("chc_ids"); ok { + chcIdsList := []*string{} chcIdsSet := v.(*schema.Set).List() - paramMap["ChcIds"] = helper.InterfacesStringsPoint(chcIdsSet) + for i := range chcIdsSet { + chcIds := chcIdsSet[i].(string) + chcIdsList = append(chcIdsList, helper.String(chcIds)) + } + paramMap["ChcIds"] = chcIdsList } if v, ok := d.GetOk("filters"); ok { filtersSet := v.([]interface{}) tmpSet := make([]*cvm.Filter, 0, len(filtersSet)) - for _, item := range filtersSet { + filtersMap := item.(map[string]interface{}) filter := cvm.Filter{} - filterMap := item.(map[string]interface{}) - - if v, ok := filterMap["name"]; ok { + if v, ok := filtersMap["name"]; ok { filter.Name = helper.String(v.(string)) } - if v, ok := filterMap["values"]; ok { + if v, ok := filtersMap["values"]; ok { valuesSet := v.(*schema.Set).List() - filter.Values = helper.InterfacesStringsPoint(valuesSet) + for i := range valuesSet { + values := valuesSet[i].(string) + filter.Values = append(filter.Values, helper.String(values)) + } } tmpSet = append(tmpSet, &filter) } - paramMap["filters"] = tmpSet + paramMap["Filters"] = tmpSet } - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - - var chcHostSet []*cvm.ChcHost - + var respData []*cvm.ChcHost err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { result, e := service.DescribeCvmChcHostsByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - chcHostSet = result + respData = result return nil }) if err != nil { return err } - ids := make([]string, 0, len(chcHostSet)) - tmpList := make([]map[string]interface{}, 0, len(chcHostSet)) + var chcIds []string + chcHostSetList := make([]map[string]interface{}, 0, len(respData)) + if respData != nil { + for _, chcHostSet := range respData { + chcHostSetMap := map[string]interface{}{} - if chcHostSet != nil { - for _, chcHost := range chcHostSet { - chcHostMap := map[string]interface{}{} - - if chcHost.ChcId != nil { - chcHostMap["chc_id"] = chcHost.ChcId + var chcId string + if chcHostSet.ChcId != nil { + chcHostSetMap["chc_id"] = chcHostSet.ChcId + chcId = *chcHostSet.ChcId } - if chcHost.InstanceName != nil { - chcHostMap["instance_name"] = chcHost.InstanceName + if chcHostSet.InstanceName != nil { + chcHostSetMap["instance_name"] = chcHostSet.InstanceName } - if chcHost.SerialNumber != nil { - chcHostMap["serial_number"] = chcHost.SerialNumber + if chcHostSet.SerialNumber != nil { + chcHostSetMap["serial_number"] = chcHostSet.SerialNumber } - if chcHost.InstanceState != nil { - chcHostMap["instance_state"] = chcHost.InstanceState + if chcHostSet.InstanceState != nil { + chcHostSetMap["instance_state"] = chcHostSet.InstanceState } - if chcHost.DeviceType != nil { - chcHostMap["device_type"] = chcHost.DeviceType + if chcHostSet.DeviceType != nil { + chcHostSetMap["device_type"] = chcHostSet.DeviceType } - if chcHost.Placement != nil { - placementMap := map[string]interface{}{} + placementMap := map[string]interface{}{} - if chcHost.Placement.Zone != nil { - placementMap["zone"] = chcHost.Placement.Zone + if chcHostSet.Placement != nil { + if chcHostSet.Placement.Zone != nil { + placementMap["zone"] = chcHostSet.Placement.Zone } - if chcHost.Placement.ProjectId != nil { - placementMap["project_id"] = chcHost.Placement.ProjectId + if chcHostSet.Placement.ProjectId != nil { + placementMap["project_id"] = chcHostSet.Placement.ProjectId } - if chcHost.Placement.HostIds != nil { - placementMap["host_ids"] = chcHost.Placement.HostIds + if chcHostSet.Placement.HostIds != nil { + placementMap["host_ids"] = chcHostSet.Placement.HostIds } - if chcHost.Placement.HostIps != nil { - placementMap["host_ips"] = chcHost.Placement.HostIps + if chcHostSet.Placement.HostIps != nil { + placementMap["host_ips"] = chcHostSet.Placement.HostIps } - if chcHost.Placement.HostId != nil { - placementMap["host_id"] = chcHost.Placement.HostId + if chcHostSet.Placement.HostId != nil { + placementMap["host_id"] = chcHostSet.Placement.HostId } - chcHostMap["placement"] = []interface{}{placementMap} + chcHostSetMap["placement"] = []interface{}{placementMap} } - if chcHost.BmcVirtualPrivateCloud != nil { - bmcVirtualPrivateCloudMap := map[string]interface{}{} + bmcVirtualPrivateCloudMap := map[string]interface{}{} - if chcHost.BmcVirtualPrivateCloud.VpcId != nil { - bmcVirtualPrivateCloudMap["vpc_id"] = chcHost.BmcVirtualPrivateCloud.VpcId + if chcHostSet.BmcVirtualPrivateCloud != nil { + if chcHostSet.BmcVirtualPrivateCloud.VpcId != nil { + bmcVirtualPrivateCloudMap["vpc_id"] = chcHostSet.BmcVirtualPrivateCloud.VpcId } - if chcHost.BmcVirtualPrivateCloud.SubnetId != nil { - bmcVirtualPrivateCloudMap["subnet_id"] = chcHost.BmcVirtualPrivateCloud.SubnetId + if chcHostSet.BmcVirtualPrivateCloud.SubnetId != nil { + bmcVirtualPrivateCloudMap["subnet_id"] = chcHostSet.BmcVirtualPrivateCloud.SubnetId } - if chcHost.BmcVirtualPrivateCloud.AsVpcGateway != nil { - bmcVirtualPrivateCloudMap["as_vpc_gateway"] = chcHost.BmcVirtualPrivateCloud.AsVpcGateway + if chcHostSet.BmcVirtualPrivateCloud.AsVpcGateway != nil { + bmcVirtualPrivateCloudMap["as_vpc_gateway"] = chcHostSet.BmcVirtualPrivateCloud.AsVpcGateway } - if chcHost.BmcVirtualPrivateCloud.PrivateIpAddresses != nil { - bmcVirtualPrivateCloudMap["private_ip_addresses"] = chcHost.BmcVirtualPrivateCloud.PrivateIpAddresses + if chcHostSet.BmcVirtualPrivateCloud.PrivateIpAddresses != nil { + bmcVirtualPrivateCloudMap["private_ip_addresses"] = chcHostSet.BmcVirtualPrivateCloud.PrivateIpAddresses } - if chcHost.BmcVirtualPrivateCloud.Ipv6AddressCount != nil { - bmcVirtualPrivateCloudMap["ipv6_address_count"] = chcHost.BmcVirtualPrivateCloud.Ipv6AddressCount + if chcHostSet.BmcVirtualPrivateCloud.Ipv6AddressCount != nil { + bmcVirtualPrivateCloudMap["ipv6_address_count"] = chcHostSet.BmcVirtualPrivateCloud.Ipv6AddressCount } - chcHostMap["bmc_virtual_private_cloud"] = []interface{}{bmcVirtualPrivateCloudMap} + chcHostSetMap["bmc_virtual_private_cloud"] = []interface{}{bmcVirtualPrivateCloudMap} } - if chcHost.BmcIp != nil { - chcHostMap["bmc_ip"] = chcHost.BmcIp + if chcHostSet.BmcIp != nil { + chcHostSetMap["bmc_ip"] = chcHostSet.BmcIp } - if chcHost.BmcSecurityGroupIds != nil { - chcHostMap["bmc_security_group_ids"] = chcHost.BmcSecurityGroupIds + if chcHostSet.BmcSecurityGroupIds != nil { + chcHostSetMap["bmc_security_group_ids"] = chcHostSet.BmcSecurityGroupIds } - if chcHost.DeployVirtualPrivateCloud != nil { - deployVirtualPrivateCloudMap := map[string]interface{}{} + deployVirtualPrivateCloudMap := map[string]interface{}{} - if chcHost.DeployVirtualPrivateCloud.VpcId != nil { - deployVirtualPrivateCloudMap["vpc_id"] = chcHost.DeployVirtualPrivateCloud.VpcId + if chcHostSet.DeployVirtualPrivateCloud != nil { + if chcHostSet.DeployVirtualPrivateCloud.VpcId != nil { + deployVirtualPrivateCloudMap["vpc_id"] = chcHostSet.DeployVirtualPrivateCloud.VpcId } - if chcHost.DeployVirtualPrivateCloud.SubnetId != nil { - deployVirtualPrivateCloudMap["subnet_id"] = chcHost.DeployVirtualPrivateCloud.SubnetId + if chcHostSet.DeployVirtualPrivateCloud.SubnetId != nil { + deployVirtualPrivateCloudMap["subnet_id"] = chcHostSet.DeployVirtualPrivateCloud.SubnetId } - if chcHost.DeployVirtualPrivateCloud.AsVpcGateway != nil { - deployVirtualPrivateCloudMap["as_vpc_gateway"] = chcHost.DeployVirtualPrivateCloud.AsVpcGateway + if chcHostSet.DeployVirtualPrivateCloud.AsVpcGateway != nil { + deployVirtualPrivateCloudMap["as_vpc_gateway"] = chcHostSet.DeployVirtualPrivateCloud.AsVpcGateway } - if chcHost.DeployVirtualPrivateCloud.PrivateIpAddresses != nil { - deployVirtualPrivateCloudMap["private_ip_addresses"] = chcHost.DeployVirtualPrivateCloud.PrivateIpAddresses + if chcHostSet.DeployVirtualPrivateCloud.PrivateIpAddresses != nil { + deployVirtualPrivateCloudMap["private_ip_addresses"] = chcHostSet.DeployVirtualPrivateCloud.PrivateIpAddresses } - if chcHost.DeployVirtualPrivateCloud.Ipv6AddressCount != nil { - deployVirtualPrivateCloudMap["ipv6_address_count"] = chcHost.DeployVirtualPrivateCloud.Ipv6AddressCount + if chcHostSet.DeployVirtualPrivateCloud.Ipv6AddressCount != nil { + deployVirtualPrivateCloudMap["ipv6_address_count"] = chcHostSet.DeployVirtualPrivateCloud.Ipv6AddressCount } - chcHostMap["deploy_virtual_private_cloud"] = []interface{}{deployVirtualPrivateCloudMap} + chcHostSetMap["deploy_virtual_private_cloud"] = []interface{}{deployVirtualPrivateCloudMap} } - if chcHost.DeployIp != nil { - chcHostMap["deploy_ip"] = chcHost.DeployIp + if chcHostSet.DeployIp != nil { + chcHostSetMap["deploy_ip"] = chcHostSet.DeployIp } - if chcHost.DeploySecurityGroupIds != nil { - chcHostMap["deploy_security_group_ids"] = chcHost.DeploySecurityGroupIds + if chcHostSet.DeploySecurityGroupIds != nil { + chcHostSetMap["deploy_security_group_ids"] = chcHostSet.DeploySecurityGroupIds } - if chcHost.CvmInstanceId != nil { - chcHostMap["cvm_instance_id"] = chcHost.CvmInstanceId + if chcHostSet.CvmInstanceId != nil { + chcHostSetMap["cvm_instance_id"] = chcHostSet.CvmInstanceId } - if chcHost.CreatedTime != nil { - chcHostMap["created_time"] = chcHost.CreatedTime + if chcHostSet.CreatedTime != nil { + chcHostSetMap["created_time"] = chcHostSet.CreatedTime } - if chcHost.HardwareDescription != nil { - chcHostMap["hardware_description"] = chcHost.HardwareDescription + if chcHostSet.HardwareDescription != nil { + chcHostSetMap["hardware_description"] = chcHostSet.HardwareDescription } - if chcHost.CPU != nil { - chcHostMap["cpu"] = chcHost.CPU + if chcHostSet.CPU != nil { + chcHostSetMap["cpu"] = chcHostSet.CPU } - if chcHost.Memory != nil { - chcHostMap["memory"] = chcHost.Memory + if chcHostSet.Memory != nil { + chcHostSetMap["memory"] = chcHostSet.Memory } - if chcHost.Disk != nil { - chcHostMap["disk"] = chcHost.Disk + if chcHostSet.Disk != nil { + chcHostSetMap["disk"] = chcHostSet.Disk } - if chcHost.BmcMAC != nil { - chcHostMap["bmc_mac"] = chcHost.BmcMAC + if chcHostSet.BmcMAC != nil { + chcHostSetMap["bmc_mac"] = chcHostSet.BmcMAC } - if chcHost.DeployMAC != nil { - chcHostMap["deploy_mac"] = chcHost.DeployMAC + if chcHostSet.DeployMAC != nil { + chcHostSetMap["deploy_mac"] = chcHostSet.DeployMAC } - if chcHost.TenantType != nil { - chcHostMap["tenant_type"] = chcHost.TenantType + if chcHostSet.TenantType != nil { + chcHostSetMap["tenant_type"] = chcHostSet.TenantType } - ids = append(ids, *chcHost.ChcId) - tmpList = append(tmpList, chcHostMap) + chcIds = append(chcIds, chcId) + chcHostSetList = append(chcHostSetList, chcHostSetMap) } - _ = d.Set("chc_host_set", tmpList) + _ = d.Set("chc_host_set", chcHostSetList) } - d.SetId(helper.DataResourceIdsHash(ids)) + d.SetId(helper.DataResourceIdsHash(chcIds)) + output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), tmpList); e != nil { + if e := tccommon.WriteToFile(output.(string), chcHostSetList); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_extension.go b/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_test.go b/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_test.go index 9f9e1bba2c..a036785f71 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_test.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_chc_hosts_test.go @@ -4,6 +4,7 @@ import ( "testing" resource "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" ) @@ -33,11 +34,6 @@ data "tencentcloud_security_groups" "security_groups2" { } data "tencentcloud_cvm_chc_hosts" "chc_hosts" { chc_ids = [tencentcloud_cvm_chc_config.chc_config.chc_id] - - filters { - values = ["ap-guangzhou-7"] - name = "zone" - } } resource "tencentcloud_vpc" "vpc" { name = "tf-cvm-vpc" diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota.go b/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota.go index 2960dd400f..c0581eb531 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota.go @@ -1,16 +1,14 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( - "fmt" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "context" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" ) func DataSourceTencentCloudCvmDisasterRecoverGroupQuota() *schema.Resource { @@ -18,32 +16,32 @@ func DataSourceTencentCloudCvmDisasterRecoverGroupQuota() *schema.Resource { Read: dataSourceTencentCloudCvmDisasterRecoverGroupQuotaRead, Schema: map[string]*schema.Schema{ "group_quota": { - Computed: true, Type: schema.TypeInt, + Computed: true, Description: "The maximum number of placement groups that can be created.", }, "current_num": { - Computed: true, Type: schema.TypeInt, + Computed: true, Description: "The number of placement groups that have been created by the current user.", }, "cvm_in_host_group_quota": { - Computed: true, Type: schema.TypeInt, + Computed: true, Description: "Quota on instances in a physical-machine-type disaster recovery group.", }, "cvm_in_sw_group_quota": { - Computed: true, Type: schema.TypeInt, + Computed: true, Description: "Quota on instances in a switch-type disaster recovery group.", }, "cvm_in_rack_group_quota": { - Computed: true, Type: schema.TypeInt, + Computed: true, Description: "Quota on instances in a rack-type disaster recovery group.", }, @@ -60,43 +58,55 @@ func dataSourceTencentCloudCvmDisasterRecoverGroupQuotaRead(d *schema.ResourceDa defer tccommon.LogElapsed("data_source.tencentcloud_cvm_disaster_recover_group_quota.read")() defer tccommon.InconsistentCheck(d, meta)() - var response *cvm.DescribeDisasterRecoverGroupQuotaResponse + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - request := cvm.NewDescribeDisasterRecoverGroupQuotaRequest() + paramMap := make(map[string]interface{}) + var respData *cvm.DescribeDisasterRecoverGroupQuotaResponseParams err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - ratelimit.Check(request.GetAction()) - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DescribeDisasterRecoverGroupQuota(request) + result, e := service.DescribeCvmDisasterRecoverGroupQuotaByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - response = result + respData = result return nil }) if err != nil { return err } - if response == nil || response.Response == nil { - d.SetId("") - return fmt.Errorf("Response is nil") + + if respData.GroupQuota != nil { + _ = d.Set("group_quota", respData.GroupQuota) + } + + if respData.CurrentNum != nil { + _ = d.Set("current_num", respData.CurrentNum) + } + + if respData.CvmInHostGroupQuota != nil { + _ = d.Set("cvm_in_host_group_quota", respData.CvmInHostGroupQuota) + } + + if respData.CvmInSwGroupQuota != nil { + _ = d.Set("cvm_in_sw_group_quota", respData.CvmInSwGroupQuota) + } + + if respData.CvmInRackGroupQuota != nil { + _ = d.Set("cvm_in_rack_group_quota", respData.CvmInRackGroupQuota) + } + + if err := dataSourceTencentCloudCvmDisasterRecoverGroupQuotaReadPostHandleResponse0(ctx, paramMap, respData); err != nil { + return err } - _ = d.Set("group_quota", response.Response.GroupQuota) - _ = d.Set("current_num", response.Response.CurrentNum) - _ = d.Set("cvm_in_host_group_quota", response.Response.CvmInHostGroupQuota) - _ = d.Set("cvm_in_sw_group_quota", response.Response.CvmInSwGroupQuota) - _ = d.Set("cvm_in_rack_group_quota", response.Response.CvmInRackGroupQuota) - d.SetId(helper.BuildToken()) output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), map[string]interface{}{ - "group_quota": response.Response.GroupQuota, - "current_num": response.Response.CurrentNum, - "cvm_in_host_group_quota": response.Response.CvmInHostGroupQuota, - "cvm_in_sw_group_quota": response.Response.CvmInSwGroupQuota, - "cvm_in_rack_group_quota": response.Response.CvmInRackGroupQuota, - }); e != nil { + if e := tccommon.WriteToFile(output.(string), dataSourceTencentCloudCvmDisasterRecoverGroupQuotaReadOutputContent(ctx)); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_extension.go b/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_extension.go new file mode 100644 index 0000000000..50abcbe42a --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_extension.go @@ -0,0 +1,30 @@ +package cvm + +import ( + "context" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudCvmDisasterRecoverGroupQuotaReadOutputContent(ctx context.Context) interface{} { + d := tccommon.ResourceDataFromContext(ctx) + + return map[string]interface{}{ + "group_quota": d.Get("group_quota"), + "current_num": d.Get("current_num"), + "cvm_in_host_group_quota": d.Get("cvm_in_host_group_quota"), + "cvm_in_sw_group_quota": d.Get("cvm_in_sw_group_quota"), + "cvm_in_rack_group_quota": d.Get("cvm_in_rack_group_quota"), + } +} + +func dataSourceTencentCloudCvmDisasterRecoverGroupQuotaReadPostHandleResponse0(ctx context.Context, req map[string]interface{}, resp *cvm.DescribeDisasterRecoverGroupQuotaResponseParams) error { + d := tccommon.ResourceDataFromContext(ctx) + + d.SetId(helper.BuildToken()) + + return nil +} diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_test.go b/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_test.go index 89833cbae0..c386ad6913 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_test.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_disaster_recover_group_quota_test.go @@ -4,6 +4,7 @@ import ( "testing" resource "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" ) diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_image_quota.go b/tencentcloud/services/cvm/data_source_tc_cvm_image_quota.go index b98fefd2e3..dfd8d4cc04 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_image_quota.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_image_quota.go @@ -1,14 +1,14 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" ) func DataSourceTencentCloudCvmImageQuota() *schema.Resource { @@ -16,8 +16,8 @@ func DataSourceTencentCloudCvmImageQuota() *schema.Resource { Read: dataSourceTencentCloudCvmImageQuotaRead, Schema: map[string]*schema.Schema{ "image_num_quota": { - Computed: true, Type: schema.TypeInt, + Computed: true, Description: "The image quota of an account.", }, @@ -34,36 +34,39 @@ func dataSourceTencentCloudCvmImageQuotaRead(d *schema.ResourceData, meta interf defer tccommon.LogElapsed("data_source.tencentcloud_cvm_image_quota.read")() defer tccommon.InconsistentCheck(d, meta)() - logId := tccommon.GetLogId(tccommon.ContextNil) - - var imageNumQuota int64 - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - paramMap := make(map[string]interface{}) service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + paramMap := make(map[string]interface{}) + var respData *cvm.DescribeImageQuotaResponseParams err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { result, e := service.DescribeCvmImageQuotaByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - imageNumQuota = result + respData = result return nil }) if err != nil { return err } - _ = d.Set("image_num_quota", imageNumQuota) + if respData.ImageNumQuota != nil { + _ = d.Set("image_num_quota", respData.ImageNumQuota) + } + + if err := dataSourceTencentCloudCvmImageQuotaReadPostHandleResponse0(ctx, paramMap, respData); err != nil { + return err + } - d.SetId(helper.BuildToken()) output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), map[string]interface{}{ - "image_num_quota": imageNumQuota, - }); e != nil { + if e := tccommon.WriteToFile(output.(string), dataSourceTencentCloudCvmImageQuotaReadOutputContent(ctx)); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_extension.go b/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_extension.go new file mode 100644 index 0000000000..9f8425c7f7 --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_extension.go @@ -0,0 +1,26 @@ +package cvm + +import ( + "context" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudCvmImageQuotaReadOutputContent(ctx context.Context) interface{} { + d := tccommon.ResourceDataFromContext(ctx) + + return map[string]interface{}{ + "image_num_quota": d.Get("image_num_quota"), + } +} + +func dataSourceTencentCloudCvmImageQuotaReadPostHandleResponse0(ctx context.Context, req map[string]interface{}, resp *cvm.DescribeImageQuotaResponseParams) error { + d := tccommon.ResourceDataFromContext(ctx) + + d.SetId(helper.BuildToken()) + + return nil +} diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_test.go b/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_test.go index ad8c11a369..dd0ff9f1b6 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_test.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_image_quota_test.go @@ -4,6 +4,7 @@ import ( "testing" resource "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" ) diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission.go b/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission.go index 25bd95d412..792b4e7efb 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission.go @@ -1,14 +1,14 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -17,14 +17,14 @@ func DataSourceTencentCloudCvmImageSharePermission() *schema.Resource { Read: dataSourceTencentCloudCvmImageSharePermissionRead, Schema: map[string]*schema.Schema{ "image_id": { - Required: true, Type: schema.TypeString, + Required: true, Description: "The ID of the image to be shared.", }, "share_permission_set": { - Computed: true, Type: schema.TypeList, + Computed: true, Description: "Information on image sharing.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -55,59 +55,60 @@ func dataSourceTencentCloudCvmImageSharePermissionRead(d *schema.ResourceData, m defer tccommon.LogElapsed("data_source.tencentcloud_cvm_image_share_permission.read")() defer tccommon.InconsistentCheck(d, meta)() - logId := tccommon.GetLogId(tccommon.ContextNil) + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} paramMap := make(map[string]interface{}) if v, ok := d.GetOk("image_id"); ok { paramMap["ImageId"] = helper.String(v.(string)) } - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - - var sharePermissionSet []*cvm.SharePermission - + var respData []*cvm.SharePermission err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { result, e := service.DescribeCvmImageSharePermissionByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - sharePermissionSet = result + respData = result return nil }) if err != nil { return err } - ids := make([]string, 0, len(sharePermissionSet)) - tmpList := make([]map[string]interface{}, 0, len(sharePermissionSet)) + ids := make([]string, 0, len(respData)) + sharePermissionSetList := make([]map[string]interface{}, 0, len(respData)) + if respData != nil { + for _, sharePermissionSet := range respData { + sharePermissionSetMap := map[string]interface{}{} - if sharePermissionSet != nil { - for _, sharePermission := range sharePermissionSet { - sharePermissionMap := map[string]interface{}{} - - if sharePermission.CreatedTime != nil { - sharePermissionMap["created_time"] = sharePermission.CreatedTime + if sharePermissionSet.CreatedTime != nil { + sharePermissionSetMap["created_time"] = sharePermissionSet.CreatedTime } - if sharePermission.AccountId != nil { - sharePermissionMap["account_id"] = sharePermission.AccountId + var accountId string + if sharePermissionSet.AccountId != nil { + sharePermissionSetMap["account_id"] = sharePermissionSet.AccountId + accountId = *sharePermissionSet.AccountId } - ids = append(ids, *sharePermission.AccountId) - tmpList = append(tmpList, sharePermissionMap) + ids = append(ids, accountId) + sharePermissionSetList = append(sharePermissionSetList, sharePermissionSetMap) } - _ = d.Set("share_permission_set", tmpList) + _ = d.Set("share_permission_set", sharePermissionSetList) } d.SetId(helper.DataResourceIdsHash(ids)) + output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), tmpList); e != nil { + if e := tccommon.WriteToFile(output.(string), sharePermissionSetList); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission_extension.go b/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_cvm_image_share_permission_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os.go b/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os.go index f117587d89..be35bb3be0 100644 --- a/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os.go +++ b/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os.go @@ -1,15 +1,14 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( - "fmt" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "context" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" ) func DataSourceTencentCloudCvmImportImageOs() *schema.Resource { @@ -17,34 +16,34 @@ func DataSourceTencentCloudCvmImportImageOs() *schema.Resource { Read: dataSourceTencentCloudCvmImportImageOsRead, Schema: map[string]*schema.Schema{ "import_image_os_list_supported": { - Computed: true, Type: schema.TypeList, + Computed: true, Description: "Supported operating system types of imported images.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "windows": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Supported Windows OS Note: This field may return null, indicating that no valid values can be obtained.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Supported Windows OS Note: This field may return null, indicating that no valid values can be obtained.", }, "linux": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Supported Linux OS Note: This field may return null, indicating that no valid values can be obtained.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Supported Linux OS Note: This field may return null, indicating that no valid values can be obtained.", }, }, }, }, "import_image_os_version_set": { - Computed: true, Type: schema.TypeList, + Computed: true, Description: "Supported operating system versions of imported images.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -54,20 +53,20 @@ func DataSourceTencentCloudCvmImportImageOs() *schema.Resource { Description: "Operating system type.", }, "os_versions": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Supported operating system versions.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Supported operating system versions.", }, "architecture": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Computed: true, + Description: "Supported operating system architecture.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Computed: true, - Description: "Supported operating system architecture.", }, }, }, @@ -86,80 +85,72 @@ func dataSourceTencentCloudCvmImportImageOsRead(d *schema.ResourceData, meta int defer tccommon.LogElapsed("data_source.tencentcloud_cvm_import_image_os.read")() defer tccommon.InconsistentCheck(d, meta)() - var ( - request = cvm.NewDescribeImportImageOsRequest() - response = cvm.NewDescribeImportImageOsResponse() - ) + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + paramMap := make(map[string]interface{}) + var respData *cvm.DescribeImportImageOsResponseParams err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - resule, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DescribeImportImageOs(request) + result, e := service.DescribeCvmImportImageOsByFilter(ctx, paramMap) if e != nil { return tccommon.RetryError(e) } - response = resule + respData = result return nil }) if err != nil { return err } - if response == nil || response.Response == nil { - d.SetId("") - return fmt.Errorf("Response is null") - } - imageOsList := response.Response.ImportImageOsListSupported - importImageOsVersionSet := response.Response.ImportImageOsVersionSet - result := make(map[string]interface{}) - if imageOsList != nil { - imageOsListMap := make(map[string]interface{}) - - if len(imageOsList.Windows) != 0 { - windowsList := make([]string, 0, len(imageOsList.Windows)) - for _, v := range imageOsList.Windows { - windowsList = append(windowsList, *v) - } - imageOsListMap["windows"] = windowsList + importImageOsListSupportedMap := map[string]interface{}{} + + if respData.ImportImageOsListSupported != nil { + if respData.ImportImageOsListSupported.Windows != nil { + importImageOsListSupportedMap["windows"] = respData.ImportImageOsListSupported.Windows } - if len(imageOsList.Linux) != 0 { - linuxList := make([]string, 0, len(imageOsList.Linux)) - for _, v := range imageOsList.Linux { - linuxList = append(linuxList, *v) - } - imageOsListMap["linux"] = linuxList + if respData.ImportImageOsListSupported.Linux != nil { + importImageOsListSupportedMap["linux"] = respData.ImportImageOsListSupported.Linux } - result["import_image_os_list_supported"] = imageOsListMap - _ = d.Set("import_image_os_list_supported", []map[string]interface{}{imageOsListMap}) + _ = d.Set("import_image_os_list_supported", []interface{}{importImageOsListSupportedMap}) } - if importImageOsVersionSet != nil { - tmpList := make([]map[string]interface{}, 0) - for _, osVersion := range importImageOsVersionSet { - osVersionMap := map[string]interface{}{} - if osVersion.OsName != nil { - osVersionMap["os_name"] = osVersion.OsName + importImageOsVersionSetList := make([]map[string]interface{}, 0, len(respData.ImportImageOsVersionSet)) + if respData.ImportImageOsVersionSet != nil { + for _, importImageOsVersionSet := range respData.ImportImageOsVersionSet { + importImageOsVersionSetMap := map[string]interface{}{} + + if importImageOsVersionSet.OsName != nil { + importImageOsVersionSetMap["os_name"] = importImageOsVersionSet.OsName } - if osVersion.OsVersions != nil { - osVersionMap["os_versions"] = osVersion.OsVersions + if importImageOsVersionSet.OsVersions != nil { + importImageOsVersionSetMap["os_versions"] = importImageOsVersionSet.OsVersions } - if osVersion.Architecture != nil { - osVersionMap["architecture"] = osVersion.Architecture + if importImageOsVersionSet.Architecture != nil { + importImageOsVersionSetMap["architecture"] = importImageOsVersionSet.Architecture } - tmpList = append(tmpList, osVersionMap) + importImageOsVersionSetList = append(importImageOsVersionSetList, importImageOsVersionSetMap) } - result["import_image_os_version_set"] = tmpList - _ = d.Set("import_image_os_version_set", tmpList) + + _ = d.Set("import_image_os_version_set", importImageOsVersionSetList) + } + + if err := dataSourceTencentCloudCvmImportImageOsReadPostHandleResponse0(ctx, paramMap, respData); err != nil { + return err } - d.SetId(helper.BuildToken()) output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if e := tccommon.WriteToFile(output.(string), result); e != nil { + if e := tccommon.WriteToFile(output.(string), dataSourceTencentCloudCvmImportImageOsReadOutputContent(ctx)); e != nil { return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os_extension.go b/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os_extension.go new file mode 100644 index 0000000000..ce4409eeea --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_cvm_import_image_os_extension.go @@ -0,0 +1,28 @@ +package cvm + +import ( + "context" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" +) + +func dataSourceTencentCloudCvmImportImageOsReadOutputContent(ctx context.Context) interface{} { + d := tccommon.ResourceDataFromContext(ctx) + + return map[string]interface{}{ + "import_image_os_list_supported": d.Get("import_image_os_list_supported"), + "import_image_os_version_set": d.Get("import_image_os_version_set"), + } +} + +func dataSourceTencentCloudCvmImportImageOsReadPostHandleResponse0(ctx context.Context, req map[string]interface{}, resp *cvm.DescribeImportImageOsResponseParams) error { + d := tccommon.ResourceDataFromContext(ctx) + + d.SetId(helper.BuildToken()) + + return nil +} diff --git a/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs.go b/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs.go index 9ab88dc31f..b14f8487f8 100644 --- a/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs.go +++ b/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs.go @@ -1,57 +1,52 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - "log" - "strconv" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) func DataSourceTencentCloudReservedInstanceConfigs() *schema.Resource { return &schema.Resource{ Read: dataSourceTencentCloudReservedInstanceConfigsRead, - Schema: map[string]*schema.Schema{ "availability_zone": { Type: schema.TypeString, Optional: true, Description: "The available zone that the reserved instance locates at.", }, + "duration": { Type: schema.TypeInt, Optional: true, - ValidateFunc: tccommon.ValidateAllowedIntValue([]int{31536000, 94608000}), Description: "Validity period of the reserved instance. Valid values are `31536000`(1 year) and `94608000`(3 years).", + ValidateFunc: tccommon.ValidateAllowedIntValue([]int{31536000, 94608000}), }, + "instance_type": { Type: schema.TypeString, Optional: true, Description: "The type of reserved instance.", }, + "offering_type": { Type: schema.TypeString, Optional: true, Description: "Filter by Payment Type. Such as All Upfront.", }, + "product_description": { Type: schema.TypeString, Optional: true, Description: "Filter by the Platform Description (that is, operating system) for Reserved Instance billing. Shaped like: linux.", }, - "result_output_file": { - Type: schema.TypeString, - Optional: true, - Description: "Used to save results.", - }, - // computed "config_list": { Type: schema.TypeList, Computed: true, @@ -106,6 +101,12 @@ func DataSourceTencentCloudReservedInstanceConfigs() *schema.Resource { }, }, }, + + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, }, } } @@ -114,72 +115,138 @@ func dataSourceTencentCloudReservedInstanceConfigsRead(d *schema.ResourceData, m defer tccommon.LogElapsed("data_source.tencentcloud_reserved_instance_configs.read")() defer tccommon.InconsistentCheck(d, meta)() - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - filter := make(map[string]string) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + paramMap := make(map[string]interface{}) + var filtersList []*cvm.Filter + filtersMap := map[string]*cvm.Filter{} + filter := cvm.Filter{} + name := "zone" + filter.Name = &name if v, ok := d.GetOk("availability_zone"); ok { - filter["zone"] = v.(string) + filter.Values = []*string{helper.String(v.(string))} + } + filtersMap["Temp0"] = &filter + if v, ok := filtersMap["Temp0"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) } + filter2 := cvm.Filter{} + name2 := "duration" + filter2.Name = &name2 if v, ok := d.GetOk("duration"); ok { - filter["duration"] = strconv.Itoa(v.(int)) + filter2.Values = []*string{helper.String(v.(string))} + } + filtersMap["Temp1"] = &filter2 + if v, ok := filtersMap["Temp1"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) } + filter3 := cvm.Filter{} + name3 := "instance-type" + filter3.Name = &name3 if v, ok := d.GetOk("instance_type"); ok { - filter["instance-type"] = v.(string) + filter3.Values = []*string{helper.String(v.(string))} } + filtersMap["Temp2"] = &filter3 + if v, ok := filtersMap["Temp2"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) + } + filter4 := cvm.Filter{} + name4 := "offering-type" + filter4.Name = &name4 if v, ok := d.GetOk("offering_type"); ok { - filter["offering-type"] = v.(string) + filter4.Values = []*string{helper.String(v.(string))} + } + filtersMap["Temp3"] = &filter4 + if v, ok := filtersMap["Temp3"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) } + filter5 := cvm.Filter{} + name5 := "product-description" + filter5.Name = &name5 if v, ok := d.GetOk("product_description"); ok { - filter["product-description"] = v.(string) + filter5.Values = []*string{helper.String(v.(string))} + } + filtersMap["Temp4"] = &filter5 + if v, ok := filtersMap["Temp4"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) } + paramMap["Filters"] = filtersList - var configs []*cvm.ReservedInstancesOffering - var errRet error + var respData []*cvm.ReservedInstancesOffering err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - configs, errRet = cvmService.DescribeReservedInstanceConfigs(ctx, filter) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) + result, e := service.DescribeReservedInstanceConfigsByFilter(ctx, paramMap) + if e != nil { + return tccommon.RetryError(e) } + respData = result return nil }) if err != nil { return err } - configList := make([]map[string]interface{}, 0, len(configs)) - ids := make([]string, 0, len(configs)) - for _, config := range configs { - mapping := map[string]interface{}{ - "config_id": config.ReservedInstancesOfferingId, - "availability_zone": config.Zone, - "instance_type": config.InstanceType, - "duration": config.Duration, - "price": config.FixedPrice, - "currency_code": config.CurrencyCode, - "platform": config.ProductDescription, - "offering_type": config.OfferingType, - "usage_price": config.UsagePrice, + var ids []string + reservedInstancesOfferingsSetList := make([]map[string]interface{}, 0, len(respData)) + if respData != nil { + for _, reservedInstancesOfferingsSet := range respData { + reservedInstancesOfferingsSetMap := map[string]interface{}{} + + var reservedInstancesOfferingId string + if reservedInstancesOfferingsSet.ReservedInstancesOfferingId != nil { + reservedInstancesOfferingsSetMap["config_id"] = reservedInstancesOfferingsSet.ReservedInstancesOfferingId + reservedInstancesOfferingId = *reservedInstancesOfferingsSet.ReservedInstancesOfferingId + } + + if reservedInstancesOfferingsSet.Zone != nil { + reservedInstancesOfferingsSetMap["availability_zone"] = reservedInstancesOfferingsSet.Zone + } + + if reservedInstancesOfferingsSet.InstanceType != nil { + reservedInstancesOfferingsSetMap["instance_type"] = reservedInstancesOfferingsSet.InstanceType + } + + if reservedInstancesOfferingsSet.Duration != nil { + reservedInstancesOfferingsSetMap["duration"] = reservedInstancesOfferingsSet.Duration + } + + if reservedInstancesOfferingsSet.FixedPrice != nil { + reservedInstancesOfferingsSetMap["price"] = reservedInstancesOfferingsSet.FixedPrice + } + + if reservedInstancesOfferingsSet.CurrencyCode != nil { + reservedInstancesOfferingsSetMap["currency_code"] = reservedInstancesOfferingsSet.CurrencyCode + } + + if reservedInstancesOfferingsSet.ProductDescription != nil { + reservedInstancesOfferingsSetMap["platform"] = reservedInstancesOfferingsSet.ProductDescription + } + + if reservedInstancesOfferingsSet.OfferingType != nil { + reservedInstancesOfferingsSetMap["offering_type"] = reservedInstancesOfferingsSet.OfferingType + } + + if reservedInstancesOfferingsSet.UsagePrice != nil { + reservedInstancesOfferingsSetMap["usage_price"] = reservedInstancesOfferingsSet.UsagePrice + } + + ids = append(ids, reservedInstancesOfferingId) + reservedInstancesOfferingsSetList = append(reservedInstancesOfferingsSetList, reservedInstancesOfferingsSetMap) } - configList = append(configList, mapping) - ids = append(ids, *config.ReservedInstancesOfferingId) + + _ = d.Set("config_list", reservedInstancesOfferingsSetList) } d.SetId(helper.DataResourceIdsHash(ids)) - err = d.Set("config_list", configList) - if err != nil { - log.Printf("[CRITAL]%s provider set config list fail, reason:%s\n ", logId, err.Error()) - return err - } output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if err := tccommon.WriteToFile(output.(string), configList); err != nil { - return err + if e := tccommon.WriteToFile(output.(string), reservedInstancesOfferingsSetList); e != nil { + return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_extension.go b/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_test.go b/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_test.go index 63f40b8542..8301ec31d1 100644 --- a/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_test.go +++ b/tencentcloud/services/cvm/data_source_tc_reserved_instance_configs_test.go @@ -4,6 +4,7 @@ import ( "testing" resource "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" ) @@ -18,7 +19,7 @@ func TestAccTencentCloudReservedInstanceConfigsDataSource_Basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccReservedInstanceConfigsDataSource_BasicCreate, - Check: resource.ComposeTestCheckFunc(acctest.AccCheckTencentCloudDataSourceID("data.tencentcloud_reserved_instance_configs.configs"), resource.TestCheckResourceAttrSet("data.tencentcloud_reserved_instance_configs.configs", "config_list.#")), + Check: resource.ComposeTestCheckFunc(acctest.AccCheckTencentCloudDataSourceID("data.tencentcloud_reserved_instance_configs.configs"), resource.TestCheckResourceAttr("data.tencentcloud_reserved_instance_configs.configs", "config_list.#", "0")), }, }, }) diff --git a/tencentcloud/services/cvm/data_source_tc_reserved_instances.go b/tencentcloud/services/cvm/data_source_tc_reserved_instances.go index 2bdbc5394c..ade0cf6b75 100644 --- a/tencentcloud/services/cvm/data_source_tc_reserved_instances.go +++ b/tencentcloud/services/cvm/data_source_tc_reserved_instances.go @@ -1,45 +1,39 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - "log" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) func DataSourceTencentCloudReservedInstances() *schema.Resource { return &schema.Resource{ Read: dataSourceTencentCloudReservedInstancesRead, - Schema: map[string]*schema.Schema{ "reserved_instance_id": { Type: schema.TypeString, Optional: true, Description: "ID of the reserved instance to be query.", }, + "availability_zone": { Type: schema.TypeString, Optional: true, Description: "The available zone that the reserved instance locates at.", }, + "instance_type": { Type: schema.TypeString, Optional: true, Description: "The type of reserved instance.", }, - "result_output_file": { - Type: schema.TypeString, - Optional: true, - Description: "Used to save results.", - }, - // computed "reserved_instance_list": { Type: schema.TypeList, Computed: true, @@ -84,69 +78,124 @@ func DataSourceTencentCloudReservedInstances() *schema.Resource { }, }, }, + + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, }, } } func dataSourceTencentCloudReservedInstancesRead(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("data_source.tencentcloud_reserved_instances.read") - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } + defer tccommon.LogElapsed("data_source.tencentcloud_reserved_instances.read")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - filter := make(map[string]string) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + paramMap := make(map[string]interface{}) + var filtersList []*cvm.Filter + filtersMap := map[string]*cvm.Filter{} + filter := cvm.Filter{} + name := "reserved-instances-id" + filter.Name = &name if v, ok := d.GetOk("reserved_instance_id"); ok { - filter["reserved-instances-id"] = v.(string) + filter.Values = []*string{helper.String(v.(string))} + } + filtersMap["Temp0"] = &filter + if v, ok := filtersMap["Temp0"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) } + filter2 := cvm.Filter{} + name2 := "zone" + filter2.Name = &name2 if v, ok := d.GetOk("availability_zone"); ok { - filter["zone"] = v.(string) + filter2.Values = []*string{helper.String(v.(string))} + } + filtersMap["Temp1"] = &filter2 + if v, ok := filtersMap["Temp1"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) } + filter3 := cvm.Filter{} + name3 := "instance-type" + filter3.Name = &name3 if v, ok := d.GetOk("instance_type"); ok { - filter["instance-type"] = v.(string) + filter3.Values = []*string{helper.String(v.(string))} } + filtersMap["Temp2"] = &filter3 + if v, ok := filtersMap["Temp2"]; ok && len(v.Values) > 0 { + filtersList = append(filtersList, v) + } + paramMap["Filters"] = filtersList - var instances []*cvm.ReservedInstances - var errRet error + var respData []*cvm.ReservedInstances err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - instances, errRet = cvmService.DescribeReservedInstanceByFilter(ctx, filter) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) + result, e := service.DescribeReservedInstancesByFilter(ctx, paramMap) + if e != nil { + return tccommon.RetryError(e) } + respData = result return nil }) if err != nil { return err } - instanceList := make([]map[string]interface{}, 0, len(instances)) - ids := make([]string, 0, len(instances)) - for _, instance := range instances { - mapping := map[string]interface{}{ - "reserved_instance_id": instance.ReservedInstancesId, - "instance_type": instance.InstanceType, - "instance_count": instance.InstanceCount, - "availability_zone": instance.Zone, - "start_time": instance.StartTime, - "end_time": instance.EndTime, - "status": instance.State, + var ids []string + reservedInstancesSetList := make([]map[string]interface{}, 0, len(respData)) + if respData != nil { + for _, reservedInstancesSet := range respData { + reservedInstancesSetMap := map[string]interface{}{} + + var reservedInstancesId string + if reservedInstancesSet.ReservedInstancesId != nil { + reservedInstancesSetMap["reserved_instance_id"] = reservedInstancesSet.ReservedInstancesId + reservedInstancesId = *reservedInstancesSet.ReservedInstancesId + } + + if reservedInstancesSet.InstanceType != nil { + reservedInstancesSetMap["instance_type"] = reservedInstancesSet.InstanceType + } + + if reservedInstancesSet.InstanceCount != nil { + reservedInstancesSetMap["instance_count"] = reservedInstancesSet.InstanceCount + } + + if reservedInstancesSet.Zone != nil { + reservedInstancesSetMap["availability_zone"] = reservedInstancesSet.Zone + } + + if reservedInstancesSet.StartTime != nil { + reservedInstancesSetMap["start_time"] = reservedInstancesSet.StartTime + } + + if reservedInstancesSet.EndTime != nil { + reservedInstancesSetMap["end_time"] = reservedInstancesSet.EndTime + } + + if reservedInstancesSet.State != nil { + reservedInstancesSetMap["status"] = reservedInstancesSet.State + } + + ids = append(ids, reservedInstancesId) + reservedInstancesSetList = append(reservedInstancesSetList, reservedInstancesSetMap) } - instanceList = append(instanceList, mapping) - ids = append(ids, *instance.ReservedInstancesId) + + _ = d.Set("reserved_instance_list", reservedInstancesSetList) } + d.SetId(helper.DataResourceIdsHash(ids)) - err = d.Set("reserved_instance_list", instanceList) - if err != nil { - log.Printf("[CRITAL]%s provider set reserved instance list fail, reason:%s\n ", logId, err.Error()) - return err - } output, ok := d.GetOk("result_output_file") if ok && output.(string) != "" { - if err := tccommon.WriteToFile(output.(string), instanceList); err != nil { - return err + if e := tccommon.WriteToFile(output.(string), reservedInstancesSetList); e != nil { + return e } } + return nil } diff --git a/tencentcloud/services/cvm/data_source_tc_reserved_instances_extension.go b/tencentcloud/services/cvm/data_source_tc_reserved_instances_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/data_source_tc_reserved_instances_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/data_source_tc_reserved_instances_test.go b/tencentcloud/services/cvm/data_source_tc_reserved_instances_test.go index 4b1704d28f..72b6920352 100644 --- a/tencentcloud/services/cvm/data_source_tc_reserved_instances_test.go +++ b/tencentcloud/services/cvm/data_source_tc_reserved_instances_test.go @@ -4,6 +4,7 @@ import ( "testing" resource "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" ) diff --git a/tencentcloud/services/cvm/resource_tc_cvm_chc_config.go b/tencentcloud/services/cvm/resource_tc_cvm_chc_config.go index 5ae69a2a4c..acfdc8d70f 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_chc_config.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_chc_config.go @@ -1,71 +1,69 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" "log" - "time" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) func ResourceTencentCloudCvmChcConfig() *schema.Resource { return &schema.Resource{ Create: resourceTencentCloudCvmChcConfigCreate, - Update: resourceTencentCloudCvmChcConfigUpdate, Read: resourceTencentCloudCvmChcConfigRead, + Update: resourceTencentCloudCvmChcConfigUpdate, Delete: resourceTencentCloudCvmChcConfigDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, Schema: map[string]*schema.Schema{ "chc_id": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "CHC host ID.", }, "instance_name": { + Type: schema.TypeString, Optional: true, Computed: true, - Type: schema.TypeString, Description: "CHC host name.", }, "device_type": { + Type: schema.TypeString, Optional: true, Computed: true, - Type: schema.TypeString, Description: "Server type.", }, "bmc_user": { + Type: schema.TypeString, Optional: true, RequiredWith: []string{"password"}, - Type: schema.TypeString, Description: "Valid characters: Letters, numbers, hyphens and underscores. Only set when update password.", }, "password": { + Type: schema.TypeString, Optional: true, Sensitive: true, RequiredWith: []string{"bmc_user"}, - Type: schema.TypeString, - - Description: "The password can contain 8 to 16 characters, including letters, numbers and special symbols (()`~!@#$%^&amp;*-+=_|{}).", + Description: "The password can contain 8 to 16 characters, including letters, numbers and special symbols (()`~!@#$%^&amp;*-+=_|{}).", }, "bmc_virtual_private_cloud": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "Out-of-band network information.", Elem: &schema.Resource{ @@ -89,14 +87,14 @@ func ResourceTencentCloudCvmChcConfig() *schema.Resource { Description: "Whether to use a CVM instance as a public gateway. The public gateway is only available when the instance has a public IP and resides in a VPC. Valid values:<br><li>TRUE: yes;<br><li>FALSE: no<br><br>Default: FALSE.", }, "private_ip_addresses": { - Type: schema.TypeList, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, Description: "Array of VPC subnet IPs. You can use this parameter when creating instances or modifying VPC attributes of instances. Currently you can specify multiple IPs in one subnet only when creating multiple instances at the same time.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, "ipv6_address_count": { Type: schema.TypeInt, @@ -110,22 +108,22 @@ func ResourceTencentCloudCvmChcConfig() *schema.Resource { }, "bmc_security_group_ids": { - Optional: true, - Computed: true, - ForceNew: true, - Type: schema.TypeList, + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + RequiredWith: []string{"bmc_virtual_private_cloud"}, + Description: "Out-of-band network security group list.", Elem: &schema.Schema{ Type: schema.TypeString, }, - RequiredWith: []string{"bmc_virtual_private_cloud"}, - Description: "Out-of-band network security group list.", }, "deploy_virtual_private_cloud": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "Deployment network information.", Elem: &schema.Resource{ @@ -149,14 +147,14 @@ func ResourceTencentCloudCvmChcConfig() *schema.Resource { Description: "Whether to use a CVM instance as a public gateway. The public gateway is only available when the instance has a public IP and resides in a VPC. Valid values:<br><li>TRUE: yes;<br><li>FALSE: no<br><br>Default: FALSE.", }, "private_ip_addresses": { - Type: schema.TypeList, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, Description: "Array of VPC subnet IPs. You can use this parameter when creating instances or modifying VPC attributes of instances. Currently you can specify multiple IPs in one subnet only when creating multiple instances at the same time.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, "ipv6_address_count": { Type: schema.TypeInt, @@ -170,15 +168,15 @@ func ResourceTencentCloudCvmChcConfig() *schema.Resource { }, "deploy_security_group_ids": { - Optional: true, - Computed: true, - ForceNew: true, - Type: schema.TypeList, + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + RequiredWith: []string{"deploy_virtual_private_cloud"}, + Description: "Deployment network security group list.", Elem: &schema.Schema{ Type: schema.TypeString, }, - RequiredWith: []string{"deploy_virtual_private_cloud"}, - Description: "Deployment network security group list.", }, }, } @@ -190,195 +188,119 @@ func resourceTencentCloudCvmChcConfigCreate(d *schema.ResourceData, meta interfa logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( - assistChange bool - deployChange bool - chcId string - vpcId string - assistRequest = cvm.NewConfigureChcAssistVpcRequest() - deployRequest = cvm.NewConfigureChcDeployVpcRequest() + chcId string ) + d.SetId(chcId) + + if err := resourceTencentCloudCvmChcConfigCreateOnExit(ctx); err != nil { + return err + } + + _ = ctx + return resourceTencentCloudCvmChcConfigRead(d, meta) +} + +func resourceTencentCloudCvmChcConfigRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_cvm_chc_config.read")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - if v, ok := d.GetOk("chc_id"); ok { - chcId = v.(string) + + chcId := d.Id() + + _ = d.Set("chc_id", chcId) + + respData, err := service.DescribeCvmChcConfigById(ctx, chcId) + if err != nil { + return err } - if v, ok := d.GetOk("instance_name"); ok { - attributeRequest := cvm.NewModifyChcAttributeRequest() - attributeRequest.InstanceName = helper.String(v.(string)) - attributeRequest.ChcIds = []*string{&chcId} - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) - return err - } + if respData == nil { + d.SetId("") + log.Printf("[WARN]%s resource `cvm_chc_config` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil + } + if respData.ChcId != nil { + _ = d.Set("chc_id", respData.ChcId) + chcId = *respData.ChcId } - if v, ok := d.GetOk("device_type"); ok { - attributeRequest := cvm.NewModifyChcAttributeRequest() - attributeRequest.DeviceType = helper.String(v.(string)) - attributeRequest.ChcIds = []*string{&chcId} - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) - return err - } + if respData.InstanceName != nil { + _ = d.Set("instance_name", respData.InstanceName) } - bmcUser, bmcUserok := d.GetOk("bmc_user") - password, passwordOk := d.GetOk("password") - if bmcUserok && passwordOk { - attributeRequest := cvm.NewModifyChcAttributeRequest() - attributeRequest.BmcUser = helper.String(bmcUser.(string)) - attributeRequest.Password = helper.String(password.(string)) - attributeRequest.ChcIds = []*string{&chcId} - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) - return err - } + + if respData.DeviceType != nil { + _ = d.Set("device_type", respData.DeviceType) } - if dMap, ok := helper.InterfacesHeadMap(d, "bmc_virtual_private_cloud"); ok { - virtualPrivateCloud := cvm.VirtualPrivateCloud{} - if v, ok := dMap["vpc_id"]; ok { - virtualPrivateCloud.VpcId = helper.String(v.(string)) + bmcVirtualPrivateCloudMap := map[string]interface{}{} + + if respData.BmcVirtualPrivateCloud != nil { + if respData.BmcVirtualPrivateCloud.VpcId != nil { + bmcVirtualPrivateCloudMap["vpc_id"] = respData.BmcVirtualPrivateCloud.VpcId } - if v, ok := dMap["subnet_id"]; ok { - virtualPrivateCloud.SubnetId = helper.String(v.(string)) + + if respData.BmcVirtualPrivateCloud.SubnetId != nil { + bmcVirtualPrivateCloudMap["subnet_id"] = respData.BmcVirtualPrivateCloud.SubnetId } - if v, ok := dMap["as_vpc_gateway"]; ok { - virtualPrivateCloud.AsVpcGateway = helper.Bool(v.(bool)) + + if respData.BmcVirtualPrivateCloud.AsVpcGateway != nil { + bmcVirtualPrivateCloudMap["as_vpc_gateway"] = respData.BmcVirtualPrivateCloud.AsVpcGateway } - if v, ok := dMap["private_ip_addresses"]; ok { - privateIpAddresses := v.([]interface{}) - for i := range privateIpAddresses { - privateIpAddresses := privateIpAddresses[i].(string) - virtualPrivateCloud.PrivateIpAddresses = append(virtualPrivateCloud.PrivateIpAddresses, &privateIpAddresses) - } + + if respData.BmcVirtualPrivateCloud.PrivateIpAddresses != nil { + bmcVirtualPrivateCloudMap["private_ip_addresses"] = respData.BmcVirtualPrivateCloud.PrivateIpAddresses } - if v, ok := dMap["ipv6_address_count"]; ok { - virtualPrivateCloud.Ipv6AddressCount = helper.IntUint64(v.(int)) + + if respData.BmcVirtualPrivateCloud.Ipv6AddressCount != nil { + bmcVirtualPrivateCloudMap["ipv6_address_count"] = respData.BmcVirtualPrivateCloud.Ipv6AddressCount } - assistChange = true - assistRequest.BmcVirtualPrivateCloud = &virtualPrivateCloud + + _ = d.Set("bmc_virtual_private_cloud", []interface{}{bmcVirtualPrivateCloudMap}) } - if v, ok := d.GetOk("bmc_security_group_ids"); ok { - bmcSecurityGroupIds := v.([]interface{}) - for i := range bmcSecurityGroupIds { - bmcSecurityGroupIds := bmcSecurityGroupIds[i].(string) - assistRequest.BmcSecurityGroupIds = append(assistRequest.BmcSecurityGroupIds, &bmcSecurityGroupIds) - } - assistChange = true + if respData.BmcSecurityGroupIds != nil { + _ = d.Set("bmc_security_group_ids", respData.BmcSecurityGroupIds) } - if assistChange { - assistRequest.ChcIds = []*string{&chcId} - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ConfigureChcAssistVpc(assistRequest) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, assistRequest.GetAction(), assistRequest.ToJsonString(), result.ToJsonString()) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s create cvm chcAssistVpc failed, reason:%+v", logId, err) - return err - } - conf := tccommon.BuildStateChangeConf([]string{}, []string{"READY"}, 20*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceStateRefreshFunc(chcId, []string{})) + deployVirtualPrivateCloudMap := map[string]interface{}{} - if _, e := conf.WaitForState(); e != nil { - return e + if respData.DeployVirtualPrivateCloud != nil { + if respData.DeployVirtualPrivateCloud.VpcId != nil { + deployVirtualPrivateCloudMap["vpc_id"] = respData.DeployVirtualPrivateCloud.VpcId } - } - if dMap, ok := helper.InterfacesHeadMap(d, "deploy_virtual_private_cloud"); ok { - virtualPrivateCloud := cvm.VirtualPrivateCloud{} - if v, ok := dMap["vpc_id"]; ok { - vpcId = v.(string) - virtualPrivateCloud.VpcId = helper.String(vpcId) - } - if v, ok := dMap["subnet_id"]; ok { - virtualPrivateCloud.SubnetId = helper.String(v.(string)) - } - if v, ok := dMap["as_vpc_gateway"]; ok { - virtualPrivateCloud.AsVpcGateway = helper.Bool(v.(bool)) - } - if v, ok := dMap["private_ip_addresses"]; ok { - privateIpAddresses := v.([]interface{}) - for i := range privateIpAddresses { - privateIpAddresses := privateIpAddresses[i].(string) - virtualPrivateCloud.PrivateIpAddresses = append(virtualPrivateCloud.PrivateIpAddresses, &privateIpAddresses) - } - } - if v, ok := dMap["ipv6_address_count"]; ok { - virtualPrivateCloud.Ipv6AddressCount = helper.IntUint64(v.(int)) + if respData.DeployVirtualPrivateCloud.SubnetId != nil { + deployVirtualPrivateCloudMap["subnet_id"] = respData.DeployVirtualPrivateCloud.SubnetId } - deployRequest.DeployVirtualPrivateCloud = &virtualPrivateCloud - deployChange = true - } - if v, ok := d.GetOk("deploy_security_group_ids"); ok { - deploySecurityGroupIds := v.([]interface{}) - for i := range deploySecurityGroupIds { - deploySecurityGroupIds := deploySecurityGroupIds[i].(string) - deployRequest.DeploySecurityGroupIds = append(deployRequest.DeploySecurityGroupIds, &deploySecurityGroupIds) + if respData.DeployVirtualPrivateCloud.AsVpcGateway != nil { + deployVirtualPrivateCloudMap["as_vpc_gateway"] = respData.DeployVirtualPrivateCloud.AsVpcGateway } - deployChange = true - } - if deployChange { - deployRequest.ChcIds = []*string{&chcId} - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ConfigureChcDeployVpc(deployRequest) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, deployRequest.GetAction(), deployRequest.ToJsonString(), result.ToJsonString()) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s create cvm chcDeployVpc failed, reason:%+v", logId, err) - return err + if respData.DeployVirtualPrivateCloud.PrivateIpAddresses != nil { + deployVirtualPrivateCloudMap["private_ip_addresses"] = respData.DeployVirtualPrivateCloud.PrivateIpAddresses } - conf := tccommon.BuildStateChangeConf([]string{}, []string{vpcId}, 10*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceDeployVpcStateRefreshFunc(chcId, []string{})) - - if _, e := conf.WaitForState(); e != nil { - return e + if respData.DeployVirtualPrivateCloud.Ipv6AddressCount != nil { + deployVirtualPrivateCloudMap["ipv6_address_count"] = respData.DeployVirtualPrivateCloud.Ipv6AddressCount } + + _ = d.Set("deploy_virtual_private_cloud", []interface{}{deployVirtualPrivateCloudMap}) } - d.SetId(chcId) + if respData.DeploySecurityGroupIds != nil { + _ = d.Set("deploy_security_group_ids", respData.DeploySecurityGroupIds) + } - return resourceTencentCloudCvmChcConfigRead(d, meta) + return nil } func resourceTencentCloudCvmChcConfigUpdate(d *schema.ResourceData, meta interface{}) error { @@ -387,236 +309,178 @@ func resourceTencentCloudCvmChcConfigUpdate(d *schema.ResourceData, meta interfa logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + chcId := d.Id() - if d.HasChange("instance_name") { - attributeRequest := cvm.NewModifyChcAttributeRequest() - attributeRequest.ChcIds = []*string{&chcId} + needChange := false + mutableArgs := []string{"instance_name"} + for _, v := range mutableArgs { + if d.HasChange(v) { + needChange = true + break + } + } + + if needChange { + request := cvm.NewModifyChcAttributeRequest() + + request.ChcIds = []*string{helper.String(chcId)} + if v, ok := d.GetOk("instance_name"); ok { - attributeRequest.InstanceName = helper.String(v.(string)) + request.InstanceName = helper.String(v.(string)) } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttributeWithContext(ctx, request) if e != nil { return tccommon.RetryError(e) } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) + 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 operate cvm chcAttribute failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s update cvm chc config failed, reason:%+v", logId, err) return err } } - if d.HasChange("device_type") { - attributeRequest := cvm.NewModifyChcAttributeRequest() - attributeRequest.ChcIds = []*string{&chcId} + + needChange1 := false + mutableArgs1 := []string{"device_type"} + for _, v := range mutableArgs1 { + if d.HasChange(v) { + needChange1 = true + break + } + } + + if needChange1 { + request1 := cvm.NewModifyChcAttributeRequest() + + request1.ChcIds = []*string{helper.String(chcId)} + if v, ok := d.GetOk("device_type"); ok { - attributeRequest.DeviceType = helper.String(v.(string)) + request1.DeviceType = helper.String(v.(string)) } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttributeWithContext(ctx, request1) if e != nil { return tccommon.RetryError(e) } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request1.GetAction(), request1.ToJsonString(), result.ToJsonString()) } return nil }) if err != nil { - log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s update cvm chc config failed, reason:%+v", logId, err) return err } } - if d.HasChange("bmc_user") || d.HasChange("password") { - attributeRequest := cvm.NewModifyChcAttributeRequest() - attributeRequest.ChcIds = []*string{&chcId} + + needChange2 := false + mutableArgs2 := []string{"bmc_user", "password"} + for _, v := range mutableArgs2 { + if d.HasChange(v) { + needChange2 = true + break + } + } + + if needChange2 { + request2 := cvm.NewModifyChcAttributeRequest() + + request2.ChcIds = []*string{helper.String(chcId)} + if v, ok := d.GetOk("bmc_user"); ok { - attributeRequest.BmcUser = helper.String(v.(string)) + request2.BmcUser = helper.String(v.(string)) } if v, ok := d.GetOk("password"); ok { - attributeRequest.Password = helper.String(v.(string)) + request2.Password = helper.String(v.(string)) } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttributeWithContext(ctx, request2) if e != nil { return tccommon.RetryError(e) } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request2.GetAction(), request2.ToJsonString(), result.ToJsonString()) } return nil }) if err != nil { - log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s update cvm chc config failed, reason:%+v", logId, err) return err } } return resourceTencentCloudCvmChcConfigRead(d, meta) } -func resourceTencentCloudCvmChcConfigRead(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_cvm_chc_config.read")() - defer tccommon.InconsistentCheck(d, meta)() - - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - chcId := d.Id() - - params := map[string]interface{}{ - "chc_ids": []string{chcId}, - } - chcHosts, err := service.DescribeCvmChcHostsByFilter(ctx, params) - if err != nil { - return err - } - - if len(chcHosts) < 1 { - d.SetId("") - log.Printf("[WARN]%s resource `CvmChcAssistVpc` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) - return nil - } - - chcHost := chcHosts[0] - if chcHost.ChcId != nil { - _ = d.Set("chc_id", chcHost.ChcId) - } - _ = d.Set("instance_name", chcHost.InstanceName) - _ = d.Set("device_type", chcHost.DeviceType) - if chcHost.BmcVirtualPrivateCloud != nil { - bmcVirtualPrivateCloudMap := map[string]interface{}{} - - if chcHost.BmcVirtualPrivateCloud.VpcId != nil { - bmcVirtualPrivateCloudMap["vpc_id"] = chcHost.BmcVirtualPrivateCloud.VpcId - } - - if chcHost.BmcVirtualPrivateCloud.SubnetId != nil { - bmcVirtualPrivateCloudMap["subnet_id"] = chcHost.BmcVirtualPrivateCloud.SubnetId - } - - if chcHost.BmcVirtualPrivateCloud.AsVpcGateway != nil { - bmcVirtualPrivateCloudMap["as_vpc_gateway"] = chcHost.BmcVirtualPrivateCloud.AsVpcGateway - } - - if chcHost.BmcVirtualPrivateCloud.PrivateIpAddresses != nil { - privateIpAddresses := make([]string, 0) - for _, p := range chcHost.BmcVirtualPrivateCloud.PrivateIpAddresses { - privateIpAddresses = append(privateIpAddresses, *p) - } - bmcVirtualPrivateCloudMap["private_ip_addresses"] = privateIpAddresses - } - - if chcHost.BmcVirtualPrivateCloud.Ipv6AddressCount != nil { - bmcVirtualPrivateCloudMap["ipv6_address_count"] = chcHost.BmcVirtualPrivateCloud.Ipv6AddressCount - } - - _ = d.Set("bmc_virtual_private_cloud", []interface{}{bmcVirtualPrivateCloudMap}) - } - - if chcHost.BmcSecurityGroupIds != nil { - bmcSecurityGroupIds := make([]string, 0) - for _, sgId := range chcHost.BmcSecurityGroupIds { - bmcSecurityGroupIds = append(bmcSecurityGroupIds, *sgId) - } - _ = d.Set("bmc_security_group_ids", bmcSecurityGroupIds) - } - - if chcHost.DeployVirtualPrivateCloud != nil { - deployVirtualPrivateCloudMap := map[string]interface{}{} - - if chcHost.DeployVirtualPrivateCloud.VpcId != nil { - deployVirtualPrivateCloudMap["vpc_id"] = chcHost.DeployVirtualPrivateCloud.VpcId - } - - if chcHost.DeployVirtualPrivateCloud.SubnetId != nil { - deployVirtualPrivateCloudMap["subnet_id"] = chcHost.DeployVirtualPrivateCloud.SubnetId - } - - if chcHost.DeployVirtualPrivateCloud.AsVpcGateway != nil { - deployVirtualPrivateCloudMap["as_vpc_gateway"] = chcHost.DeployVirtualPrivateCloud.AsVpcGateway - } - - if chcHost.DeployVirtualPrivateCloud.PrivateIpAddresses != nil { - privateIpAddresses := make([]string, 0) - for _, p := range chcHost.DeployVirtualPrivateCloud.PrivateIpAddresses { - privateIpAddresses = append(privateIpAddresses, *p) - } - deployVirtualPrivateCloudMap["private_ip_addresses"] = privateIpAddresses - } - - if chcHost.DeployVirtualPrivateCloud.Ipv6AddressCount != nil { - deployVirtualPrivateCloudMap["ipv6_address_count"] = chcHost.DeployVirtualPrivateCloud.Ipv6AddressCount - } - - _ = d.Set("deploy_virtual_private_cloud", []interface{}{deployVirtualPrivateCloudMap}) - } - - if chcHost.DeploySecurityGroupIds != nil { - deploySecurityGroupIds := make([]string, 0) - for _, sgId := range chcHost.DeploySecurityGroupIds { - deploySecurityGroupIds = append(deploySecurityGroupIds, *sgId) - } - _ = d.Set("deploy_security_group_ids", deploySecurityGroupIds) - } - - return nil -} func resourceTencentCloudCvmChcConfigDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_cvm_chc_config.delete")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} chcId := d.Id() - request := cvm.NewRemoveChcDeployVpcRequest() - request.ChcIds = []*string{&chcId} + var ( + request = cvm.NewRemoveChcDeployVpcRequest() + response = cvm.NewRemoveChcDeployVpcResponse() + ) + + request.ChcIds = []*string{helper.String(chcId)} + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().RemoveChcDeployVpc(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().RemoveChcDeployVpcWithContext(ctx, request) if e != nil { return tccommon.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 remove Chc deploy vpc failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s delete cvm chc config failed, reason:%+v", logId, err) return err } - conf := tccommon.BuildStateChangeConf([]string{}, []string{""}, 5*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceDeployVpcStateRefreshFunc(d.Id(), []string{})) - - if _, e := conf.WaitForState(); e != nil { - return e + _ = response + if err := resourceTencentCloudCvmChcConfigDeletePostHandleResponse0(ctx, response); err != nil { + return err } - params := map[string]interface{}{ - "chc_ids": []string{chcId}, - } - chcHosts, err := service.DescribeCvmChcHostsByFilter(ctx, params) + var ( + request1 = cvm.NewRemoveChcAssistVpcRequest() + response1 = cvm.NewRemoveChcAssistVpcResponse() + ) + + request1.ChcIds = []*string{helper.String(chcId)} + + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().RemoveChcAssistVpcWithContext(ctx, request1) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request1.GetAction(), request1.ToJsonString(), result.ToJsonString()) + } + response1 = result + return nil + }) if err != nil { + log.Printf("[CRITAL]%s delete cvm chc config failed, reason:%+v", logId, err) return err } - if len(chcHosts) > 0 && *chcHosts[0].InstanceState == "INIT" { - return nil - } - if err := service.DeleteCvmChcAssistVpcById(ctx, chcId); err != nil { + _ = response1 + if err := resourceTencentCloudCvmChcConfigDeletePostHandleResponse1(ctx, response1); err != nil { return err } - conf = tccommon.BuildStateChangeConf([]string{}, []string{"INIT"}, 10*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceStateRefreshFunc(d.Id(), []string{})) - - if _, e := conf.WaitForState(); e != nil { - return e - } - return nil } diff --git a/tencentcloud/services/cvm/resource_tc_cvm_chc_config_extension.go b/tencentcloud/services/cvm/resource_tc_cvm_chc_config_extension.go new file mode 100644 index 0000000000..dffc0fe155 --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_cvm_chc_config_extension.go @@ -0,0 +1,249 @@ +package cvm + +import ( + "context" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" +) + +func resourceTencentCloudCvmChcConfigCreateOnExit(ctx context.Context) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + logId := ctx.Value(tccommon.LogIdKey).(string) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + var ( + assistChange bool + deployChange bool + chcId string + vpcId string + assistRequest = cvm.NewConfigureChcAssistVpcRequest() + deployRequest = cvm.NewConfigureChcDeployVpcRequest() + ) + if v, ok := d.GetOk("chc_id"); ok { + chcId = v.(string) + } + + if v, ok := d.GetOk("instance_name"); ok { + attributeRequest := cvm.NewModifyChcAttributeRequest() + attributeRequest.InstanceName = helper.String(v.(string)) + attributeRequest.ChcIds = []*string{&chcId} + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) + return err + } + } + + if v, ok := d.GetOk("device_type"); ok { + attributeRequest := cvm.NewModifyChcAttributeRequest() + attributeRequest.DeviceType = helper.String(v.(string)) + attributeRequest.ChcIds = []*string{&chcId} + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) + return err + } + } + bmcUser, bmcUserok := d.GetOk("bmc_user") + password, passwordOk := d.GetOk("password") + if bmcUserok && passwordOk { + attributeRequest := cvm.NewModifyChcAttributeRequest() + attributeRequest.BmcUser = helper.String(bmcUser.(string)) + attributeRequest.Password = helper.String(password.(string)) + attributeRequest.ChcIds = []*string{&chcId} + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyChcAttribute(attributeRequest) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, attributeRequest.GetAction(), attributeRequest.ToJsonString(), result.ToJsonString()) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s operate cvm chcAttribute failed, reason:%+v", logId, err) + return err + } + } + + if dMap, ok := helper.InterfacesHeadMap(d, "bmc_virtual_private_cloud"); ok { + virtualPrivateCloud := cvm.VirtualPrivateCloud{} + if v, ok := dMap["vpc_id"]; ok { + virtualPrivateCloud.VpcId = helper.String(v.(string)) + } + if v, ok := dMap["subnet_id"]; ok { + virtualPrivateCloud.SubnetId = helper.String(v.(string)) + } + if v, ok := dMap["as_vpc_gateway"]; ok { + virtualPrivateCloud.AsVpcGateway = helper.Bool(v.(bool)) + } + if v, ok := dMap["private_ip_addresses"]; ok { + privateIpAddresses := v.([]interface{}) + for i := range privateIpAddresses { + privateIpAddresses := privateIpAddresses[i].(string) + virtualPrivateCloud.PrivateIpAddresses = append(virtualPrivateCloud.PrivateIpAddresses, &privateIpAddresses) + } + } + if v, ok := dMap["ipv6_address_count"]; ok { + virtualPrivateCloud.Ipv6AddressCount = helper.IntUint64(v.(int)) + } + assistChange = true + assistRequest.BmcVirtualPrivateCloud = &virtualPrivateCloud + } + + if v, ok := d.GetOk("bmc_security_group_ids"); ok { + bmcSecurityGroupIds := v.([]interface{}) + for i := range bmcSecurityGroupIds { + bmcSecurityGroupIds := bmcSecurityGroupIds[i].(string) + assistRequest.BmcSecurityGroupIds = append(assistRequest.BmcSecurityGroupIds, &bmcSecurityGroupIds) + } + assistChange = true + } + + if assistChange { + assistRequest.ChcIds = []*string{&chcId} + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ConfigureChcAssistVpc(assistRequest) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, assistRequest.GetAction(), assistRequest.ToJsonString(), result.ToJsonString()) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s create cvm chcAssistVpc failed, reason:%+v", logId, err) + return err + } + conf := tccommon.BuildStateChangeConf([]string{}, []string{"READY"}, 20*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceStateRefreshFunc(chcId, []string{})) + + if _, e := conf.WaitForState(); e != nil { + return e + } + } + + if dMap, ok := helper.InterfacesHeadMap(d, "deploy_virtual_private_cloud"); ok { + virtualPrivateCloud := cvm.VirtualPrivateCloud{} + if v, ok := dMap["vpc_id"]; ok { + vpcId = v.(string) + virtualPrivateCloud.VpcId = helper.String(vpcId) + } + if v, ok := dMap["subnet_id"]; ok { + virtualPrivateCloud.SubnetId = helper.String(v.(string)) + } + if v, ok := dMap["as_vpc_gateway"]; ok { + virtualPrivateCloud.AsVpcGateway = helper.Bool(v.(bool)) + } + if v, ok := dMap["private_ip_addresses"]; ok { + privateIpAddresses := v.([]interface{}) + for i := range privateIpAddresses { + privateIpAddresses := privateIpAddresses[i].(string) + virtualPrivateCloud.PrivateIpAddresses = append(virtualPrivateCloud.PrivateIpAddresses, &privateIpAddresses) + } + } + if v, ok := dMap["ipv6_address_count"]; ok { + virtualPrivateCloud.Ipv6AddressCount = helper.IntUint64(v.(int)) + } + deployRequest.DeployVirtualPrivateCloud = &virtualPrivateCloud + deployChange = true + } + + if v, ok := d.GetOk("deploy_security_group_ids"); ok { + deploySecurityGroupIds := v.([]interface{}) + for i := range deploySecurityGroupIds { + deploySecurityGroupIds := deploySecurityGroupIds[i].(string) + deployRequest.DeploySecurityGroupIds = append(deployRequest.DeploySecurityGroupIds, &deploySecurityGroupIds) + } + deployChange = true + } + + if deployChange { + deployRequest.ChcIds = []*string{&chcId} + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ConfigureChcDeployVpc(deployRequest) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, deployRequest.GetAction(), deployRequest.ToJsonString(), result.ToJsonString()) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s create cvm chcDeployVpc failed, reason:%+v", logId, err) + return err + } + + conf := tccommon.BuildStateChangeConf([]string{}, []string{vpcId}, 10*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceDeployVpcStateRefreshFunc(chcId, []string{})) + + if _, e := conf.WaitForState(); e != nil { + return e + } + } + + d.SetId(chcId) + + return nil +} + +func resourceTencentCloudCvmChcConfigDeletePostHandleResponse0(ctx context.Context, resp *cvm.RemoveChcDeployVpcResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + chcId := d.Id() + + conf := tccommon.BuildStateChangeConf([]string{}, []string{""}, 5*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceDeployVpcStateRefreshFunc(chcId, []string{})) + if _, e := conf.WaitForState(); e != nil { + return e + } + + params := map[string]interface{}{ + "chc_ids": []string{chcId}, + } + chcHosts, err := service.DescribeCvmChcHostsByFilter(ctx, params) + if err != nil { + return err + } + if len(chcHosts) > 0 && *chcHosts[0].InstanceState == "INIT" { + return nil + } + + return nil +} + +func resourceTencentCloudCvmChcConfigDeletePostHandleResponse1(ctx context.Context, resp *cvm.RemoveChcAssistVpcResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + conf := tccommon.BuildStateChangeConf([]string{}, []string{"INIT"}, 10*tccommon.ReadRetryTimeout, time.Second, service.CvmChcInstanceStateRefreshFunc(d.Id(), []string{})) + if _, e := conf.WaitForState(); e != nil { + return e + } + + return nil +} diff --git a/tencentcloud/services/cvm/resource_tc_cvm_chc_config_test.go b/tencentcloud/services/cvm/resource_tc_cvm_chc_config_test.go index fc0bab4d3b..cd9b5b1d16 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_chc_config_test.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_chc_config_test.go @@ -26,7 +26,7 @@ func TestAccTencentCloudCvmChcConfigResource_Basic(t *testing.T) { { ResourceName: "tencentcloud_cvm_chc_config.chc_config", ImportState: true, - ImportStateVerify: true, + ImportStateVerify: false, ImportStateVerifyIgnore: []string{"bmc_user", "password"}, }, }, diff --git a/tencentcloud/services/cvm/resource_tc_cvm_export_images.go b/tencentcloud/services/cvm/resource_tc_cvm_export_images.go index bf77f54f5b..1494ffd10a 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_export_images.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_export_images.go @@ -1,15 +1,15 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( + "context" "log" - "time" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -18,53 +18,56 @@ func ResourceTencentCloudCvmExportImages() *schema.Resource { Create: resourceTencentCloudCvmExportImagesCreate, Read: resourceTencentCloudCvmExportImagesRead, Delete: resourceTencentCloudCvmExportImagesDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, Schema: map[string]*schema.Schema{ "bucket_name": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "COS bucket name.", }, "image_id": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "Image ID.", }, "file_name_prefix": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "Prefix of exported file.", }, "export_format": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "Format of the exported image file. Valid values: RAW, QCOW2, VHD and VMDK. Default value: RAW.", }, "only_export_root_disk": { + Type: schema.TypeBool, Optional: true, ForceNew: true, - Type: schema.TypeBool, Description: "Whether to export only the system disk.", }, "dry_run": { + Type: schema.TypeBool, Optional: true, ForceNew: true, - Type: schema.TypeBool, Description: "Check whether the image can be exported.", }, "role_name": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "Role name (Default: CVM_QcsRole). Before exporting the images, make sure the role exists, and it has write permission to COS.", }, }, @@ -77,28 +80,39 @@ func resourceTencentCloudCvmExportImagesCreate(d *schema.ResourceData, meta inte logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + var ( + imageId string + ) var ( - request = cvm.NewExportImagesRequest() - imageId string - bucketName string - fileNamePrefix string + request = cvm.NewExportImagesRequest() + response = cvm.NewExportImagesResponse() ) - imageId = d.Get("image_id").(string) - bucketName = d.Get("bucket_name").(string) - fileNamePrefix = d.Get("file_name_prefix").(string) - request.ImageIds = []*string{&imageId} - request.BucketName = helper.String(bucketName) - request.FileNamePrefixList = []*string{&fileNamePrefix} + + if v, ok := d.GetOk("image_id"); ok { + imageId = v.(string) + } + + if v, ok := d.GetOk("bucket_name"); ok { + request.BucketName = helper.String(v.(string)) + } + + request.ImageIds = []*string{helper.String(imageId)} if v, ok := d.GetOk("export_format"); ok { request.ExportFormat = helper.String(v.(string)) } - if v, _ := d.GetOk("only_export_root_disk"); v != nil { + if v, ok := d.GetOk("file_name_prefix_list"); ok { + request.FileNamePrefixList = []*string{helper.String(v.(string))} + } + + if v, ok := d.GetOkExists("only_export_root_disk"); ok { request.OnlyExportRootDisk = helper.Bool(v.(bool)) } - if v, _ := d.GetOk("dry_run"); v != nil { + if v, ok := d.GetOkExists("dry_run"); ok { request.DryRun = helper.Bool(v.(bool)) } @@ -107,27 +121,26 @@ func resourceTencentCloudCvmExportImagesCreate(d *schema.ResourceData, meta inte } err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ExportImages(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ExportImagesWithContext(ctx, request) if e != nil { return tccommon.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 operate cvm exportImages failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create cvm export images failed, reason:%+v", logId, err) return err } - d.SetId(imageId) - - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + _ = response - conf := tccommon.BuildStateChangeConf([]string{}, []string{"NORMAL"}, 20*tccommon.ReadRetryTimeout, time.Second, service.CvmSyncImagesStateRefreshFunc(d.Id(), []string{})) + d.SetId(imageId) - if _, e := conf.WaitForState(); e != nil { - return e + if err := resourceTencentCloudCvmExportImagesCreateOnExit(ctx); err != nil { + return err } return resourceTencentCloudCvmExportImagesRead(d, meta) diff --git a/tencentcloud/services/cvm/resource_tc_cvm_export_images_extension.go b/tencentcloud/services/cvm/resource_tc_cvm_export_images_extension.go new file mode 100644 index 0000000000..503bf2f05f --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_cvm_export_images_extension.go @@ -0,0 +1,21 @@ +package cvm + +import ( + "context" + "time" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" +) + +func resourceTencentCloudCvmExportImagesCreateOnExit(ctx context.Context) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + conf := tccommon.BuildStateChangeConf([]string{}, []string{"NORMAL"}, 20*tccommon.ReadRetryTimeout, time.Second, service.CvmSyncImagesStateRefreshFunc(d.Id(), []string{})) + if _, e := conf.WaitForState(); e != nil { + return e + } + + return nil +} diff --git a/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster.go b/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster.go index 70f450f5a7..67b5baa5f1 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster.go @@ -1,3 +1,4 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( @@ -5,12 +6,11 @@ import ( "fmt" "log" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -25,20 +25,20 @@ func ResourceTencentCloudCvmHpcCluster() *schema.Resource { }, Schema: map[string]*schema.Schema{ "zone": { - Required: true, Type: schema.TypeString, + Required: true, Description: "Available zone.", }, "name": { - Required: true, Type: schema.TypeString, + Required: true, Description: "Name of Hpc Cluster.", }, "remark": { - Optional: true, Type: schema.TypeString, + Optional: true, Description: "Remark of Hpc Cluster.", }, }, @@ -51,11 +51,16 @@ func resourceTencentCloudCvmHpcClusterCreate(d *schema.ResourceData, meta interf logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( - request = cvm.NewCreateHpcClusterRequest() - response = cvm.NewCreateHpcClusterResponse() hpcClusterId string ) + var ( + request = cvm.NewCreateHpcClusterRequest() + response = cvm.NewCreateHpcClusterResponse() + ) + if v, ok := d.GetOk("zone"); ok { request.Zone = helper.String(v.(string)) } @@ -69,7 +74,7 @@ func resourceTencentCloudCvmHpcClusterCreate(d *schema.ResourceData, meta interf } err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateHpcCluster(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateHpcClusterWithContext(ctx, request) if e != nil { return tccommon.RetryError(e) } else { @@ -79,7 +84,7 @@ func resourceTencentCloudCvmHpcClusterCreate(d *schema.ResourceData, meta interf return nil }) if err != nil { - log.Printf("[CRITAL]%s create cvm hpcCluster failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create cvm hpc cluster failed, reason:%+v", logId, err) return err } @@ -88,6 +93,7 @@ func resourceTencentCloudCvmHpcClusterCreate(d *schema.ResourceData, meta interf } hpcClusterId = *response.Response.HpcClusterSet[0].HpcClusterId + d.SetId(hpcClusterId) return resourceTencentCloudCvmHpcClusterRead(d, meta) @@ -99,32 +105,32 @@ func resourceTencentCloudCvmHpcClusterRead(d *schema.ResourceData, meta interfac logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} hpcClusterId := d.Id() - hpcCluster, err := service.DescribeCvmHpcClusterById(ctx, hpcClusterId) + respData, err := service.DescribeCvmHpcClusterById(ctx, hpcClusterId) if err != nil { return err } - if hpcCluster == nil { + if respData == nil { d.SetId("") - return fmt.Errorf("resource `tencentcloud_cvm_hpc_cluster` %s does not exist", d.Id()) + log.Printf("[WARN]%s resource `cvm_hpc_cluster` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil } - - if hpcCluster.Zone != nil { - _ = d.Set("zone", hpcCluster.Zone) + if respData.Zone != nil { + _ = d.Set("zone", respData.Zone) } - if hpcCluster.Name != nil { - _ = d.Set("name", hpcCluster.Name) + if respData.Name != nil { + _ = d.Set("name", respData.Name) } - if hpcCluster.Remark != nil { - _ = d.Set("remark", hpcCluster.Remark) + if respData.Remark != nil { + _ = d.Set("remark", respData.Remark) } return nil @@ -136,36 +142,51 @@ func resourceTencentCloudCvmHpcClusterUpdate(d *schema.ResourceData, meta interf logId := tccommon.GetLogId(tccommon.ContextNil) - request := cvm.NewModifyHpcClusterAttributeRequest() + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + immutableArgs := []string{"zone"} + for _, v := range immutableArgs { + if d.HasChange(v) { + return fmt.Errorf("argument `%s` cannot be changed", v) + } + } hpcClusterId := d.Id() - request.HpcClusterId = &hpcClusterId + needChange := false + mutableArgs := []string{"name", "remark"} + for _, v := range mutableArgs { + if d.HasChange(v) { + needChange = true + break + } + } + + if needChange { + request := cvm.NewModifyHpcClusterAttributeRequest() + + request.HpcClusterId = helper.String(hpcClusterId) - if d.HasChange("name") { if v, ok := d.GetOk("name"); ok { request.Name = helper.String(v.(string)) } - } - if d.HasChange("remark") { if v, ok := d.GetOk("remark"); ok { request.Remark = helper.String(v.(string)) } - } - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyHpcClusterAttribute(request) - if e != nil { - return tccommon.RetryError(e) - } else { - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyHpcClusterAttributeWithContext(ctx, request) + if e != nil { + return tccommon.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 update cvm hpc cluster failed, reason:%+v", logId, err) + return err } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s create cvm hpcCluster failed, reason:%+v", logId, err) - return nil } return resourceTencentCloudCvmHpcClusterRead(d, meta) @@ -176,14 +197,32 @@ func resourceTencentCloudCvmHpcClusterDelete(d *schema.ResourceData, meta interf defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} hpcClusterId := d.Id() - if err := service.DeleteCvmHpcClusterById(ctx, hpcClusterId); err != nil { + var ( + request = cvm.NewDeleteHpcClustersRequest() + response = cvm.NewDeleteHpcClustersResponse() + ) + + request.HpcClusterIds = []*string{helper.String(hpcClusterId)} + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DeleteHpcClustersWithContext(ctx, request) + if e != nil { + return tccommon.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 delete cvm hpc cluster failed, reason:%+v", logId, err) + return err } + _ = response return nil } diff --git a/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster_extension.go b/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_cvm_hpc_cluster_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission.go b/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission.go index e50943bb2e..d7e1e70a10 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission.go @@ -1,42 +1,42 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" "log" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) func ResourceTencentCloudCvmImageSharePermission() *schema.Resource { return &schema.Resource{ Create: resourceTencentCloudCvmImageSharePermissionCreate, - Update: resourceTencentCloudCvmImageSharePermissionUpdate, Read: resourceTencentCloudCvmImageSharePermissionRead, + Update: resourceTencentCloudCvmImageSharePermissionUpdate, Delete: resourceTencentCloudCvmImageSharePermissionDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, Schema: map[string]*schema.Schema{ "image_id": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "Image ID such as `img-gvbnzy6f`. You can only specify an image in the NORMAL state.", }, "account_ids": { - Required: true, - Type: schema.TypeSet, + Type: schema.TypeSet, + Required: true, + Description: "List of account IDs with which an image is shared.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "List of account IDs with which an image is shared.", }, }, } @@ -48,135 +48,145 @@ func resourceTencentCloudCvmImageSharePermissionCreate(d *schema.ResourceData, m logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( - request = cvm.NewModifyImageSharePermissionRequest() imageId string ) + var ( + request = cvm.NewModifyImageSharePermissionRequest() + response = cvm.NewModifyImageSharePermissionResponse() + ) + if v, ok := d.GetOk("image_id"); ok { imageId = v.(string) - request.ImageId = helper.String(imageId) } + request.ImageId = &imageId + if v, ok := d.GetOk("account_ids"); ok { accountIdsSet := v.(*schema.Set).List() for i := range accountIdsSet { accountIds := accountIdsSet[i].(string) - request.AccountIds = append(request.AccountIds, &accountIds) + request.AccountIds = append(request.AccountIds, helper.String(accountIds)) } } - request.Permission = helper.String(IMAGE_SHARE_PERMISSION_SHARE) + permission := "SHARE" + request.Permission = &permission err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyImageSharePermission(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyImageSharePermissionWithContext(ctx, request) if e != nil { return tccommon.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 operate cvm modifyImageSharePermission failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create cvm image share permission failed, reason:%+v", logId, err) return err } + _ = response + d.SetId(imageId) return resourceTencentCloudCvmImageSharePermissionRead(d, meta) } -func resourceTencentCloudCvmImageSharePermissionUpdate(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_cvm_image_share_permission.update")() +func resourceTencentCloudCvmImageSharePermissionRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_cvm_image_share_permission.read")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - if d.HasChange("account_ids") { - old, new := d.GetChange("account_ids") - oldSet := old.(*schema.Set) - newSet := new.(*schema.Set) - add := newSet.Difference(oldSet).List() - remove := oldSet.Difference(newSet).List() - if len(add) > 0 { - addError := service.ModifyImageSharePermission(ctx, d.Id(), IMAGE_SHARE_PERMISSION_SHARE, helper.InterfacesStrings(add)) - if addError != nil { - return addError - } - } - if len(remove) > 0 { - removeError := service.ModifyImageSharePermission(ctx, d.Id(), IMAGE_SHARE_PERMISSION_CANCEL, helper.InterfacesStrings(remove)) - if removeError != nil { - return removeError - } - } + imageId := d.Id() + + _ = d.Set("image_id", imageId) + + respData, err := service.DescribeCvmImageSharePermissionById(ctx, imageId) + if err != nil { + return err } - return resourceTencentCloudCvmImageSharePermissionRead(d, meta) + if respData == nil { + d.SetId("") + log.Printf("[WARN]%s resource `cvm_image_share_permission` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil + } + if err := resourceTencentCloudCvmImageSharePermissionReadPreHandleResponse0(ctx, respData); err != nil { + return err + } + + return nil } -func resourceTencentCloudCvmImageSharePermissionRead(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_cvm_image_share_permission.read")() +func resourceTencentCloudCvmImageSharePermissionUpdate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_cvm_image_share_permission.update")() defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - var sharePermissionSet []*cvm.SharePermission - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - result, e := service.DescribeCvmImageSharePermissionByFilter(ctx, map[string]interface{}{"ImageId": helper.String(d.Id())}) - if e != nil { - return tccommon.RetryError(e) - } - sharePermissionSet = result - return nil - }) - if err != nil { - return err - } + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + imageId := d.Id() - accountIds := make([]string, 0) - for _, sharePermission := range sharePermissionSet { - accountIds = append(accountIds, *sharePermission.AccountId) + if err := resourceTencentCloudCvmImageSharePermissionUpdateOnStart(ctx); err != nil { + return err } - _ = d.Set("account_ids", accountIds) - _ = d.Set("image_id", d.Id()) - return nil + _ = imageId + return resourceTencentCloudCvmImageSharePermissionRead(d, meta) } func resourceTencentCloudCvmImageSharePermissionDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_cvm_image_share_permission.delete")() defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - var sharePermissionSet []*cvm.SharePermission + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - result, e := service.DescribeCvmImageSharePermissionByFilter(ctx, map[string]interface{}{"ImageId": helper.String(d.Id())}) + imageId := d.Id() + + var ( + request = cvm.NewModifyImageSharePermissionRequest() + response = cvm.NewModifyImageSharePermissionResponse() + ) + + if v, ok := d.GetOk("image_id"); ok { + request.ImageId = helper.String(v.(string)) + } + + permission := "CANCEL" + request.Permission = &permission + + if err := resourceTencentCloudCvmImageSharePermissionDeletePostFillRequest0(ctx, request); err != nil { + return err + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyImageSharePermissionWithContext(ctx, request) if e != nil { return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) } - sharePermissionSet = result + response = result return nil }) if err != nil { + log.Printf("[CRITAL]%s create cvm image share permission failed, reason:%+v", logId, err) return err } - accountIds := make([]string, 0) - for _, sharePermission := range sharePermissionSet { - accountIds = append(accountIds, *sharePermission.AccountId) - } - - err = service.ModifyImageSharePermission(ctx, d.Id(), IMAGE_SHARE_PERMISSION_CANCEL, accountIds) - if err != nil { - return err - } - + _ = response + _ = imageId return nil } diff --git a/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission_extension.go b/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission_extension.go new file mode 100644 index 0000000000..691b3fc4df --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_cvm_image_share_permission_extension.go @@ -0,0 +1,89 @@ +package cvm + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" +) + +func resourceTencentCloudCvmImageSharePermissionReadPreHandleResponse0(ctx context.Context, resp *cvm.DescribeImageSharePermissionResponseParams) error { + d := tccommon.ResourceDataFromContext(ctx) + + if len(resp.SharePermissionSet) < 1 { + return fmt.Errorf("resource `tencentcloud_cvm_image_share_permission` read failed") + } + sharePermissionSet := resp.SharePermissionSet + + accountIds := make([]string, 0) + for _, sharePermission := range sharePermissionSet { + accountIds = append(accountIds, *sharePermission.AccountId) + } + _ = d.Set("account_ids", accountIds) + + return nil +} + +func resourceTencentCloudCvmImageSharePermissionUpdateOnStart(ctx context.Context) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + if d.HasChange("account_ids") { + old, new := d.GetChange("account_ids") + oldSet := old.(*schema.Set) + newSet := new.(*schema.Set) + add := newSet.Difference(oldSet).List() + remove := oldSet.Difference(newSet).List() + if len(add) > 0 { + addError := service.ModifyImageSharePermission(ctx, d.Id(), IMAGE_SHARE_PERMISSION_SHARE, helper.InterfacesStrings(add)) + if addError != nil { + return addError + } + } + if len(remove) > 0 { + removeError := service.ModifyImageSharePermission(ctx, d.Id(), IMAGE_SHARE_PERMISSION_CANCEL, helper.InterfacesStrings(remove)) + if removeError != nil { + return removeError + } + } + } + + return nil +} + +func resourceTencentCloudCvmImageSharePermissionDeletePostFillRequest0(ctx context.Context, req *cvm.ModifyImageSharePermissionRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + var sharePermissionSet []*cvm.SharePermission + + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeCvmImageSharePermissionByFilter(ctx, map[string]interface{}{"ImageId": helper.String(d.Id())}) + if e != nil { + return tccommon.RetryError(e) + } + sharePermissionSet = result + return nil + }) + if err != nil { + return err + } + + accountIds := make([]string, 0) + for _, sharePermission := range sharePermissionSet { + accountIds = append(accountIds, *sharePermission.AccountId) + } + req.AccountIds = helper.StringsStringsPoint(accountIds) + + return nil +} diff --git a/tencentcloud/services/cvm/resource_tc_cvm_import_image.go b/tencentcloud/services/cvm/resource_tc_cvm_import_image.go index c2179f5e7a..eb6e5d531d 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_import_image.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_import_image.go @@ -1,14 +1,15 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( + "context" "log" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -22,65 +23,65 @@ func ResourceTencentCloudCvmImportImage() *schema.Resource { }, Schema: map[string]*schema.Schema{ "architecture": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "OS architecture of the image to be imported, `x86_64` or `i386`.", }, "os_type": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "OS type of the image to be imported. You can call `DescribeImportImageOs` to obtain the list of supported operating systems.", }, "os_version": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "OS version of the image to be imported. You can call `DescribeImportImageOs` to obtain the list of supported operating systems.", }, "image_url": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "Address on COS where the image to be imported is stored.", }, "image_name": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, - Description: "Image name.", + Description: "Image name", }, "image_description": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, - Description: "Image description.", + Description: "Image description", }, "dry_run": { + Type: schema.TypeBool, Optional: true, ForceNew: true, - Type: schema.TypeBool, - Description: "Dry run to check the parameters without performing the operation.", + Description: "Dry run to check the parameters without performing the operation", }, "force": { + Type: schema.TypeBool, Optional: true, ForceNew: true, - Type: schema.TypeBool, Description: "Whether to force import the image.", }, "tag_specification": { + Type: schema.TypeList, Optional: true, ForceNew: true, - Type: schema.TypeList, Description: "Tag description list. This parameter is used to bind a tag to a custom image.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -113,16 +114,16 @@ func ResourceTencentCloudCvmImportImage() *schema.Resource { }, "license_type": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, - Description: "The license type used to activate the OS after importing an image. Valid values: TencentCloud: Tencent Cloud official license BYOL: Bring Your Own License.", + Description: "The license type used to activate the OS after importing an image. Valid values: TencentCloud: Tencent Cloud official license BYOL: Bring Your Own License", }, "boot_mode": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "Boot mode.", }, }, @@ -135,10 +136,20 @@ func resourceTencentCloudCvmImportImageCreate(d *schema.ResourceData, meta inter logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( - request = cvm.NewImportImageRequest() imageUrl string ) + var ( + request = cvm.NewImportImageRequest() + response = cvm.NewImportImageResponse() + ) + + if v, ok := d.GetOk("image_url"); ok { + imageUrl = v.(string) + } + if v, ok := d.GetOk("architecture"); ok { request.Architecture = helper.String(v.(string)) } @@ -151,10 +162,7 @@ func resourceTencentCloudCvmImportImageCreate(d *schema.ResourceData, meta inter request.OsVersion = helper.String(v.(string)) } - if v, ok := d.GetOk("image_url"); ok { - imageUrl = v.(string) - request.ImageUrl = helper.String(imageUrl) - } + request.ImageUrl = &imageUrl if v, ok := d.GetOk("image_name"); ok { request.ImageName = helper.String(v.(string)) @@ -164,22 +172,22 @@ func resourceTencentCloudCvmImportImageCreate(d *schema.ResourceData, meta inter request.ImageDescription = helper.String(v.(string)) } - if v, _ := d.GetOk("dry_run"); v != nil { + if v, ok := d.GetOkExists("dry_run"); ok { request.DryRun = helper.Bool(v.(bool)) } - if v, _ := d.GetOk("force"); v != nil { + if v, ok := d.GetOkExists("force"); ok { request.Force = helper.Bool(v.(bool)) } if v, ok := d.GetOk("tag_specification"); ok { for _, item := range v.([]interface{}) { - dMap := item.(map[string]interface{}) + tagSpecificationMap := item.(map[string]interface{}) tagSpecification := cvm.TagSpecification{} - if v, ok := dMap["resource_type"]; ok { + if v, ok := tagSpecificationMap["resource_type"]; ok { tagSpecification.ResourceType = helper.String(v.(string)) } - if v, ok := dMap["tags"]; ok { + if v, ok := tagSpecificationMap["tags"]; ok { for _, item := range v.([]interface{}) { tagsMap := item.(map[string]interface{}) tag := cvm.Tag{} @@ -200,24 +208,27 @@ func resourceTencentCloudCvmImportImageCreate(d *schema.ResourceData, meta inter request.LicenseType = helper.String(v.(string)) } - if v, ok := d.GetOk("boot_mode"); ok { + if v, ok := d.GetOk("boot_modexwwwww"); ok { request.BootMode = helper.String(v.(string)) } err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ImportImage(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ImportImageWithContext(ctx, request) if e != nil { return tccommon.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 operate cvm importImage failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create cvm import image failed, reason:%+v", logId, err) return err } + _ = response + d.SetId(imageUrl) return resourceTencentCloudCvmImportImageRead(d, meta) diff --git a/tencentcloud/services/cvm/resource_tc_cvm_import_image_extension.go b/tencentcloud/services/cvm/resource_tc_cvm_import_image_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_cvm_import_image_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/resource_tc_cvm_launch_template.go b/tencentcloud/services/cvm/resource_tc_cvm_launch_template.go index 2341836046..e503a4bbe3 100644 --- a/tencentcloud/services/cvm/resource_tc_cvm_launch_template.go +++ b/tencentcloud/services/cvm/resource_tc_cvm_launch_template.go @@ -1,15 +1,15 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" "log" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) @@ -20,16 +20,16 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { Delete: resourceTencentCloudCvmLaunchTemplateDelete, Schema: map[string]*schema.Schema{ "launch_template_name": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "The name of launch template.", }, "placement": { + Type: schema.TypeList, Required: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "The location of instance.", Elem: &schema.Resource{ @@ -45,52 +45,52 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { Description: "The project ID of the instance.", }, "host_ids": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Description: "The CDH ID list of the instance(input).", Elem: &schema.Schema{ Type: schema.TypeString, }, - Optional: true, - Description: "The CDH ID list of the instance(input).", }, "host_ips": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Description: "Specify the host machine ip.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Optional: true, - Description: "Specify the host machine ip.", }, }, }, }, "image_id": { + Type: schema.TypeString, Required: true, ForceNew: true, - Type: schema.TypeString, Description: "Image ID.", }, "launch_template_version_description": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "Instance launch template version description.", }, "instance_type": { + Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeString, Description: "The type of the instance. If this parameter is not specified, the system will dynamically specify the default model according to the resource sales in the current region.", }, "system_disk": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "System disk configuration information of the instance. If this parameter is not specified, it is assigned according to the system default.", Elem: &schema.Resource{ @@ -120,9 +120,9 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "data_disks": { + Type: schema.TypeList, Optional: true, ForceNew: true, - Type: schema.TypeList, Description: "Data disk configuration information of the instance.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -176,10 +176,10 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "virtual_private_cloud": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "The configuration information of VPC. If this parameter is not specified, the basic network is used by default.", Elem: &schema.Resource{ @@ -200,12 +200,12 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { Description: "Is it used as a Public network gateway, TRUE or FALSE.", }, "private_ip_addresses": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Description: "The address of private ip.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Optional: true, - Description: "The address of private ip.", }, "ipv6_address_count": { Type: schema.TypeInt, @@ -217,10 +217,10 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "internet_accessible": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "The information settings of public network bandwidth. If you do not specify this parameter, the default Internet bandwidth is 0 Mbps.", Elem: &schema.Resource{ @@ -250,26 +250,26 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "instance_count": { + Type: schema.TypeInt, Optional: true, ForceNew: true, Default: 1, - Type: schema.TypeInt, Description: "The number of instances purchased.", }, "instance_name": { + Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeString, Description: "The name of instance. If you do not specify an instance display name, 'Unnamed' is displayed by default.", }, "login_settings": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "The login settings of instance. By default, passwords are randomly generated and notified to users via internal messages.", Elem: &schema.Resource{ @@ -280,12 +280,12 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { Description: "The login password of instance.", }, "key_ids": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Description: "List of key ID.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Optional: true, - Description: "List of key ID.", }, "keep_image_login": { Type: schema.TypeString, @@ -297,29 +297,29 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "security_group_ids": { - Optional: true, - Computed: true, - ForceNew: true, - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The security group ID of instance. If this parameter is not specified, the default security group is bound.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "The security group ID of instance. If this parameter is not specified, the default security group is bound.", }, "enhanced_service": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "Enhanced service. If this parameter is not specified, cloud monitoring and cloud security services will be enabled by default in public images.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "security_service": { Type: schema.TypeList, - MaxItems: 1, Optional: true, + MaxItems: 1, Description: "Enable cloud security service.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -333,8 +333,8 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "monitor_service": { Type: schema.TypeList, - MaxItems: 1, Optional: true, + MaxItems: 1, Description: "Enable cloud monitor service.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -348,8 +348,8 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "automation_service": { Type: schema.TypeList, - MaxItems: 1, Optional: true, + MaxItems: 1, Description: "Enable TencentCloud Automation Tools(TAT).", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -366,24 +366,24 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "client_token": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "A string to used guarantee request idempotency.", }, "host_name": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "The host name of CVM.", }, "action_timer": { + Type: schema.TypeList, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "Timed task.", Elem: &schema.Resource{ @@ -400,8 +400,8 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "externals": { Type: schema.TypeList, - MaxItems: 1, Optional: true, + MaxItems: 1, Description: "Extended data.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -411,17 +411,17 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { Description: "Release address.", }, "unsupport_networks": { - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + Description: "Unsupported network type.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Optional: true, - Description: "Unsupported network type.", }, "storage_block_attr": { Type: schema.TypeList, - MaxItems: 1, Optional: true, + MaxItems: 1, Description: "HDD local storage attributes.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -451,19 +451,19 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "disaster_recover_group_ids": { - Optional: true, - ForceNew: true, - Type: schema.TypeSet, + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Description: "The ID of disaster recover group.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "The ID of disaster recover group.", }, "tag_specification": { + Type: schema.TypeList, Optional: true, ForceNew: true, - Type: schema.TypeList, Description: "Tag description list.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -496,17 +496,17 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "instance_market_options": { + Type: schema.TypeList, Optional: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "The marketplace options of instance.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "spot_options": { Type: schema.TypeList, - MaxItems: 1, Required: true, + MaxItems: 1, Description: "Bidding related options.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -533,45 +533,45 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "user_data": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "The data of users.", }, "dry_run": { + Type: schema.TypeBool, Optional: true, ForceNew: true, - Type: schema.TypeBool, Description: "Whether to preflight only this request, true or false.", }, "cam_role_name": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "The role name of CAM.", }, "hpc_cluster_id": { + Type: schema.TypeString, Optional: true, ForceNew: true, - Type: schema.TypeString, Description: "The ID of HPC cluster.", }, "instance_charge_type": { + Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, - Type: schema.TypeString, Description: "The charge type of instance. Default value: POSTPAID_BY_HOUR.", }, "instance_charge_prepaid": { + Type: schema.TypeList, Optional: true, ForceNew: true, - Type: schema.TypeList, MaxItems: 1, Description: "The configuration of charge prepaid.", Elem: &schema.Resource{ @@ -591,16 +591,16 @@ func ResourceTencentCloudCvmLaunchTemplate() *schema.Resource { }, "disable_api_termination": { + Type: schema.TypeBool, Optional: true, ForceNew: true, - Type: schema.TypeBool, Description: "Instance destruction protection flag.", }, "tags": { Type: schema.TypeMap, - ForceNew: true, Optional: true, + ForceNew: true, Description: "Tag description list.", }, }, @@ -613,40 +613,42 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( - request = cvm.NewCreateLaunchTemplateRequest() - response = cvm.NewCreateLaunchTemplateResponse() launchTemplateId string ) + var ( + request = cvm.NewCreateLaunchTemplateRequest() + response = cvm.NewCreateLaunchTemplateResponse() + ) + if v, ok := d.GetOk("launch_template_name"); ok { request.LaunchTemplateName = helper.String(v.(string)) } - if dMap, ok := helper.InterfacesHeadMap(d, "placement"); ok { + if placementMap, ok := helper.InterfacesHeadMap(d, "placement"); ok { placement := cvm.Placement{} - if v, ok := dMap["zone"]; ok { + if v, ok := placementMap["zone"]; ok { placement.Zone = helper.String(v.(string)) } - if v, ok := dMap["project_id"]; ok { + if v, ok := placementMap["project_id"]; ok { placement.ProjectId = helper.IntInt64(v.(int)) } - if v, ok := dMap["host_ids"]; ok { + if v, ok := placementMap["host_ids"]; ok { hostIdsSet := v.(*schema.Set).List() for i := range hostIdsSet { hostIds := hostIdsSet[i].(string) - placement.HostIds = append(placement.HostIds, &hostIds) + placement.HostIds = append(placement.HostIds, helper.String(hostIds)) } } - if v, ok := dMap["host_ips"]; ok { + if v, ok := placementMap["host_ips"]; ok { hostIpsSet := v.(*schema.Set).List() for i := range hostIpsSet { hostIps := hostIpsSet[i].(string) - placement.HostIps = append(placement.HostIps, &hostIps) + placement.HostIps = append(placement.HostIps, helper.String(hostIps)) } } - // if v, ok := dMap["host_id"]; ok { - // placement.HostId = helper.String(v.(string)) - // } request.Placement = &placement } @@ -662,18 +664,18 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in request.InstanceType = helper.String(v.(string)) } - if dMap, ok := helper.InterfacesHeadMap(d, "system_disk"); ok { + if systemDiskMap, ok := helper.InterfacesHeadMap(d, "system_disk"); ok { systemDisk := cvm.SystemDisk{} - if v, ok := dMap["disk_type"]; ok { + if v, ok := systemDiskMap["disk_type"]; ok { systemDisk.DiskType = helper.String(v.(string)) } - if v, ok := dMap["disk_id"]; ok { + if v, ok := systemDiskMap["disk_id"]; ok { systemDisk.DiskId = helper.String(v.(string)) } - if v, ok := dMap["disk_size"]; ok { + if v, ok := systemDiskMap["disk_size"]; ok { systemDisk.DiskSize = helper.IntInt64(v.(int)) } - if v, ok := dMap["cdc_id"]; ok { + if v, ok := systemDiskMap["cdc_id"]; ok { systemDisk.CdcId = helper.String(v.(string)) } request.SystemDisk = &systemDisk @@ -681,81 +683,81 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in if v, ok := d.GetOk("data_disks"); ok { for _, item := range v.([]interface{}) { - dMap := item.(map[string]interface{}) + dataDisksMap := item.(map[string]interface{}) dataDisk := cvm.DataDisk{} - if v, ok := dMap["disk_size"]; ok { + if v, ok := dataDisksMap["disk_size"]; ok { dataDisk.DiskSize = helper.IntInt64(v.(int)) } - if v, ok := dMap["disk_type"]; ok { + if v, ok := dataDisksMap["disk_type"]; ok { dataDisk.DiskType = helper.String(v.(string)) } - if v, ok := dMap["disk_id"]; ok { + if v, ok := dataDisksMap["disk_id"]; ok { dataDisk.DiskId = helper.String(v.(string)) } - if v, ok := dMap["delete_with_instance"]; ok { + if v, ok := dataDisksMap["delete_with_instance"]; ok { dataDisk.DeleteWithInstance = helper.Bool(v.(bool)) } - if v, ok := dMap["snapshot_id"]; ok { + if v, ok := dataDisksMap["snapshot_id"]; ok { dataDisk.SnapshotId = helper.String(v.(string)) } - if v, ok := dMap["encrypt"]; ok { + if v, ok := dataDisksMap["encrypt"]; ok { dataDisk.Encrypt = helper.Bool(v.(bool)) } - if v, ok := dMap["kms_key_id"]; ok { + if v, ok := dataDisksMap["kms_key_id"]; ok { dataDisk.KmsKeyId = helper.String(v.(string)) } - if v, ok := dMap["throughput_performance"]; ok { + if v, ok := dataDisksMap["throughput_performance"]; ok { dataDisk.ThroughputPerformance = helper.IntInt64(v.(int)) } - if v, ok := dMap["cdc_id"]; ok { + if v, ok := dataDisksMap["cdc_id"]; ok { dataDisk.CdcId = helper.String(v.(string)) } request.DataDisks = append(request.DataDisks, &dataDisk) } } - if dMap, ok := helper.InterfacesHeadMap(d, "virtual_private_cloud"); ok { + if virtualPrivateCloudMap, ok := helper.InterfacesHeadMap(d, "virtual_private_cloud"); ok { virtualPrivateCloud := cvm.VirtualPrivateCloud{} - if v, ok := dMap["vpc_id"]; ok { + if v, ok := virtualPrivateCloudMap["vpc_id"]; ok { virtualPrivateCloud.VpcId = helper.String(v.(string)) } - if v, ok := dMap["subnet_id"]; ok { + if v, ok := virtualPrivateCloudMap["subnet_id"]; ok { virtualPrivateCloud.SubnetId = helper.String(v.(string)) } - if v, ok := dMap["as_vpc_gateway"]; ok { + if v, ok := virtualPrivateCloudMap["as_vpc_gateway"]; ok { virtualPrivateCloud.AsVpcGateway = helper.Bool(v.(bool)) } - if v, ok := dMap["private_ip_addresses"]; ok { + if v, ok := virtualPrivateCloudMap["private_ip_addresses"]; ok { privateIpAddressesSet := v.(*schema.Set).List() for i := range privateIpAddressesSet { privateIpAddresses := privateIpAddressesSet[i].(string) - virtualPrivateCloud.PrivateIpAddresses = append(virtualPrivateCloud.PrivateIpAddresses, &privateIpAddresses) + virtualPrivateCloud.PrivateIpAddresses = append(virtualPrivateCloud.PrivateIpAddresses, helper.String(privateIpAddresses)) } } - if v, ok := dMap["ipv6_address_count"]; ok { + if v, ok := virtualPrivateCloudMap["ipv6_address_count"]; ok { virtualPrivateCloud.Ipv6AddressCount = helper.IntUint64(v.(int)) } request.VirtualPrivateCloud = &virtualPrivateCloud } - if dMap, ok := helper.InterfacesHeadMap(d, "internet_accessible"); ok { + if internetAccessibleMap, ok := helper.InterfacesHeadMap(d, "internet_accessible"); ok { internetAccessible := cvm.InternetAccessible{} - if v, ok := dMap["internet_charge_type"]; ok { + if v, ok := internetAccessibleMap["internet_charge_type"]; ok { internetAccessible.InternetChargeType = helper.String(v.(string)) } - if v, ok := dMap["internet_max_bandwidth_out"]; ok { + if v, ok := internetAccessibleMap["internet_max_bandwidth_out"]; ok { internetAccessible.InternetMaxBandwidthOut = helper.IntInt64(v.(int)) } - if v, ok := dMap["public_ip_assigned"]; ok { + if v, ok := internetAccessibleMap["public_ip_assigned"]; ok { internetAccessible.PublicIpAssigned = helper.Bool(v.(bool)) } - if v, ok := dMap["bandwidth_package_id"]; ok { + if v, ok := internetAccessibleMap["bandwidth_package_id"]; ok { internetAccessible.BandwidthPackageId = helper.String(v.(string)) } request.InternetAccessible = &internetAccessible } - if v, _ := d.GetOk("instance_count"); v != nil { + if v, ok := d.GetOkExists("instance_count"); ok { request.InstanceCount = helper.IntInt64(v.(int)) } @@ -763,19 +765,19 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in request.InstanceName = helper.String(v.(string)) } - if dMap, ok := helper.InterfacesHeadMap(d, "login_settings"); ok { + if loginSettingsMap, ok := helper.InterfacesHeadMap(d, "login_settings"); ok { loginSettings := cvm.LoginSettings{} - if v, ok := dMap["password"]; ok { + if v, ok := loginSettingsMap["password"]; ok { loginSettings.Password = helper.String(v.(string)) } - if v, ok := dMap["key_ids"]; ok { + if v, ok := loginSettingsMap["key_ids"]; ok { keyIdsSet := v.(*schema.Set).List() for i := range keyIdsSet { keyIds := keyIdsSet[i].(string) - loginSettings.KeyIds = append(loginSettings.KeyIds, &keyIds) + loginSettings.KeyIds = append(loginSettings.KeyIds, helper.String(keyIds)) } } - if v, ok := dMap["keep_image_login"]; ok { + if v, ok := loginSettingsMap["keep_image_login"]; ok { loginSettings.KeepImageLogin = helper.String(v.(string)) } request.LoginSettings = &loginSettings @@ -785,27 +787,27 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in securityGroupIdsSet := v.(*schema.Set).List() for i := range securityGroupIdsSet { securityGroupIds := securityGroupIdsSet[i].(string) - request.SecurityGroupIds = append(request.SecurityGroupIds, &securityGroupIds) + request.SecurityGroupIds = append(request.SecurityGroupIds, helper.String(securityGroupIds)) } } - if dMap, ok := helper.InterfacesHeadMap(d, "enhanced_service"); ok { + if enhancedServiceMap, ok := helper.InterfacesHeadMap(d, "enhanced_service"); ok { enhancedService := cvm.EnhancedService{} - if securityServiceMap, ok := helper.InterfaceToMap(dMap, "security_service"); ok { + if securityServiceMap, ok := helper.ConvertInterfacesHeadToMap(enhancedServiceMap["security_service"]); ok { runSecurityServiceEnabled := cvm.RunSecurityServiceEnabled{} if v, ok := securityServiceMap["enabled"]; ok { runSecurityServiceEnabled.Enabled = helper.Bool(v.(bool)) } enhancedService.SecurityService = &runSecurityServiceEnabled } - if monitorServiceMap, ok := helper.InterfaceToMap(dMap, "monitor_service"); ok { + if monitorServiceMap, ok := helper.ConvertInterfacesHeadToMap(enhancedServiceMap["monitor_service"]); ok { runMonitorServiceEnabled := cvm.RunMonitorServiceEnabled{} if v, ok := monitorServiceMap["enabled"]; ok { runMonitorServiceEnabled.Enabled = helper.Bool(v.(bool)) } enhancedService.MonitorService = &runMonitorServiceEnabled } - if automationServiceMap, ok := helper.InterfaceToMap(dMap, "automation_service"); ok { + if automationServiceMap, ok := helper.ConvertInterfacesHeadToMap(enhancedServiceMap["automation_service"]); ok { runAutomationServiceEnabled := cvm.RunAutomationServiceEnabled{} if v, ok := automationServiceMap["enabled"]; ok { runAutomationServiceEnabled.Enabled = helper.Bool(v.(bool)) @@ -823,15 +825,15 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in request.HostName = helper.String(v.(string)) } - if dMap, ok := helper.InterfacesHeadMap(d, "action_timer"); ok { + if actionTimerMap, ok := helper.InterfacesHeadMap(d, "action_timer"); ok { actionTimer := cvm.ActionTimer{} - if v, ok := dMap["timer_action"]; ok { + if v, ok := actionTimerMap["timer_action"]; ok { actionTimer.TimerAction = helper.String(v.(string)) } - if v, ok := dMap["action_time"]; ok { + if v, ok := actionTimerMap["action_time"]; ok { actionTimer.ActionTime = helper.String(v.(string)) } - if externalsMap, ok := helper.InterfaceToMap(dMap, "externals"); ok { + if externalsMap, ok := helper.ConvertInterfacesHeadToMap(actionTimerMap["externals"]); ok { externals := cvm.Externals{} if v, ok := externalsMap["release_address"]; ok { externals.ReleaseAddress = helper.Bool(v.(bool)) @@ -840,10 +842,10 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in unsupportNetworksSet := v.(*schema.Set).List() for i := range unsupportNetworksSet { unsupportNetworks := unsupportNetworksSet[i].(string) - externals.UnsupportNetworks = append(externals.UnsupportNetworks, &unsupportNetworks) + externals.UnsupportNetworks = append(externals.UnsupportNetworks, helper.String(unsupportNetworks)) } } - if storageBlockAttrMap, ok := helper.InterfaceToMap(externalsMap, "storage_block_attr"); ok { + if storageBlockAttrMap, ok := helper.ConvertInterfacesHeadToMap(externalsMap["storage_block_attr"]); ok { storageBlock := cvm.StorageBlock{} if v, ok := storageBlockAttrMap["type"]; ok { storageBlock.Type = helper.String(v.(string)) @@ -865,18 +867,18 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in disasterRecoverGroupIdsSet := v.(*schema.Set).List() for i := range disasterRecoverGroupIdsSet { disasterRecoverGroupIds := disasterRecoverGroupIdsSet[i].(string) - request.DisasterRecoverGroupIds = append(request.DisasterRecoverGroupIds, &disasterRecoverGroupIds) + request.DisasterRecoverGroupIds = append(request.DisasterRecoverGroupIds, helper.String(disasterRecoverGroupIds)) } } if v, ok := d.GetOk("tag_specification"); ok { for _, item := range v.([]interface{}) { - dMap := item.(map[string]interface{}) + tagSpecificationMap := item.(map[string]interface{}) tagSpecification := cvm.TagSpecification{} - if v, ok := dMap["resource_type"]; ok { + if v, ok := tagSpecificationMap["resource_type"]; ok { tagSpecification.ResourceType = helper.String(v.(string)) } - if v, ok := dMap["tags"]; ok { + if v, ok := tagSpecificationMap["tags"]; ok { for _, item := range v.([]interface{}) { tagsMap := item.(map[string]interface{}) tag := cvm.Tag{} @@ -893,9 +895,9 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in } } - if dMap, ok := helper.InterfacesHeadMap(d, "instance_market_options"); ok { + if instanceMarketOptionsMap, ok := helper.InterfacesHeadMap(d, "instance_market_options"); ok { instanceMarketOptionsRequest := cvm.InstanceMarketOptionsRequest{} - if spotOptionsMap, ok := helper.InterfaceToMap(dMap, "spot_options"); ok { + if spotOptionsMap, ok := helper.ConvertInterfacesHeadToMap(instanceMarketOptionsMap["spot_options"]); ok { spotMarketOptions := cvm.SpotMarketOptions{} if v, ok := spotOptionsMap["max_price"]; ok { spotMarketOptions.MaxPrice = helper.String(v.(string)) @@ -905,7 +907,7 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in } instanceMarketOptionsRequest.SpotOptions = &spotMarketOptions } - if v, ok := dMap["market_type"]; ok { + if v, ok := instanceMarketOptionsMap["market_type"]; ok { instanceMarketOptionsRequest.MarketType = helper.String(v.(string)) } request.InstanceMarketOptions = &instanceMarketOptionsRequest @@ -915,7 +917,7 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in request.UserData = helper.String(v.(string)) } - if v, _ := d.GetOk("dry_run"); v != nil { + if v, ok := d.GetOkExists("dry_run"); ok { request.DryRun = helper.Bool(v.(bool)) } @@ -931,23 +933,23 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in request.InstanceChargeType = helper.String(v.(string)) } - if dMap, ok := helper.InterfacesHeadMap(d, "instance_charge_prepaid"); ok { + if instanceChargePrepaidMap, ok := helper.InterfacesHeadMap(d, "instance_charge_prepaid"); ok { instanceChargePrepaid := cvm.InstanceChargePrepaid{} - if v, ok := dMap["period"]; ok { + if v, ok := instanceChargePrepaidMap["period"]; ok { instanceChargePrepaid.Period = helper.IntInt64(v.(int)) } - if v, ok := dMap["renew_flag"]; ok { + if v, ok := instanceChargePrepaidMap["renew_flag"]; ok { instanceChargePrepaid.RenewFlag = helper.String(v.(string)) } request.InstanceChargePrepaid = &instanceChargePrepaid } - if v, _ := d.GetOk("disable_api_termination"); v != nil { + if v, ok := d.GetOkExists("disable_api_termination"); ok { request.DisableApiTermination = helper.Bool(v.(bool)) } err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateLaunchTemplate(request) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateLaunchTemplateWithContext(ctx, request) if e != nil { return tccommon.RetryError(e) } else { @@ -957,11 +959,12 @@ func resourceTencentCloudCvmLaunchTemplateCreate(d *schema.ResourceData, meta in return nil }) if err != nil { - log.Printf("[CRITAL]%s create cvm launchTemplate failed, reason:%+v", logId, err) + log.Printf("[CRITAL]%s create cvm launch template failed, reason:%+v", logId, err) return err } launchTemplateId = *response.Response.LaunchTemplateId + d.SetId(launchTemplateId) return resourceTencentCloudCvmLaunchTemplateRead(d, meta) @@ -973,410 +976,398 @@ func resourceTencentCloudCvmLaunchTemplateRead(d *schema.ResourceData, meta inte logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} launchTemplateId := d.Id() - launchTemplate, err := service.DescribeCvmLaunchTemplateById(ctx, launchTemplateId) + respData, err := service.DescribeCvmLaunchTemplateById(ctx, launchTemplateId) if err != nil { return err } - if launchTemplate == nil { + if respData == nil { d.SetId("") - log.Printf("[WARN]%s resource `CvmLaunchTemplate` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + log.Printf("[WARN]%s resource `cvm_launch_template` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } - - if launchTemplate.LaunchTemplateName != nil { - _ = d.Set("launch_template_name", launchTemplate.LaunchTemplateName) + if respData.LaunchTemplateName != nil { + _ = d.Set("launch_template_name", respData.LaunchTemplateName) } - launchTemplateVersion, err := service.DescribeLaunchTemplateVersionsById(ctx, launchTemplateId) + respData1, err := service.DescribeCvmLaunchTemplateById1(ctx, launchTemplateId) if err != nil { return err } - if launchTemplateVersion == nil { + if respData1 == nil { d.SetId("") - log.Printf("[WARN]%s resource `CvmLaunchTemplateVersion` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + log.Printf("[WARN]%s resource `cvm_launch_template` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } - - if launchTemplateVersion.LaunchTemplateVersionData != nil && launchTemplateVersion.LaunchTemplateVersionData.Placement != nil { + if respData1.LaunchTemplateVersionData != nil { placementMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.Placement.Zone != nil { - placementMap["zone"] = launchTemplateVersion.LaunchTemplateVersionData.Placement.Zone - } + if respData1.LaunchTemplateVersionData.Placement != nil { + if respData1.LaunchTemplateVersionData.Placement.Zone != nil { + placementMap["zone"] = respData1.LaunchTemplateVersionData.Placement.Zone + } + + if respData1.LaunchTemplateVersionData.Placement.ProjectId != nil { + placementMap["project_id"] = respData1.LaunchTemplateVersionData.Placement.ProjectId + } + + if respData1.LaunchTemplateVersionData.Placement.HostIds != nil { + placementMap["host_ids"] = respData1.LaunchTemplateVersionData.Placement.HostIds + } + + if respData1.LaunchTemplateVersionData.Placement.HostId != nil { + placementMap["host_id"] = respData1.LaunchTemplateVersionData.Placement.HostId + } - if launchTemplateVersion.LaunchTemplateVersionData.Placement.ProjectId != nil { - placementMap["project_id"] = launchTemplateVersion.LaunchTemplateVersionData.Placement.ProjectId + _ = d.Set("placement", []interface{}{placementMap}) } - if launchTemplateVersion.LaunchTemplateVersionData.Placement.HostIds != nil { - placementMap["host_ids"] = launchTemplateVersion.LaunchTemplateVersionData.Placement.HostIds + if respData1.LaunchTemplateVersionData.InstanceType != nil { + _ = d.Set("instance_type", respData1.LaunchTemplateVersionData.InstanceType) } - if launchTemplateVersion.LaunchTemplateVersionData.Placement.HostIps != nil { - placementMap["host_ips"] = launchTemplateVersion.LaunchTemplateVersionData.Placement.HostIps + if respData1.LaunchTemplateVersionData.InstanceName != nil { + _ = d.Set("instance_name", respData1.LaunchTemplateVersionData.InstanceName) } - if launchTemplateVersion.LaunchTemplateVersionData.Placement.HostId != nil { - placementMap["host_id"] = launchTemplateVersion.LaunchTemplateVersionData.Placement.HostId + if respData1.LaunchTemplateVersionData.InstanceChargeType != nil { + _ = d.Set("instance_charge_type", respData1.LaunchTemplateVersionData.InstanceChargeType) } - _ = d.Set("placement", []interface{}{placementMap}) - } + systemDiskMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData != nil && launchTemplateVersion.LaunchTemplateVersionData.ImageId != nil { - _ = d.Set("image_id", launchTemplateVersion.LaunchTemplateVersionData.ImageId) - } + if respData1.LaunchTemplateVersionData.SystemDisk != nil { + if respData1.LaunchTemplateVersionData.SystemDisk.DiskType != nil { + systemDiskMap["disk_type"] = respData1.LaunchTemplateVersionData.SystemDisk.DiskType + } - if launchTemplateVersion.LaunchTemplateVersionDescription != nil { - _ = d.Set("launch_template_version_description", launchTemplateVersion.LaunchTemplateVersionDescription) - } + if respData1.LaunchTemplateVersionData.SystemDisk.DiskId != nil { + systemDiskMap["disk_id"] = respData1.LaunchTemplateVersionData.SystemDisk.DiskId + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceType != nil { - _ = d.Set("instance_type", launchTemplateVersion.LaunchTemplateVersionData.InstanceType) - } + if respData1.LaunchTemplateVersionData.SystemDisk.DiskSize != nil { + systemDiskMap["disk_size"] = respData1.LaunchTemplateVersionData.SystemDisk.DiskSize + } - if launchTemplateVersion.LaunchTemplateVersionData != nil && launchTemplateVersion.LaunchTemplateVersionData.SystemDisk != nil { - systemDiskMap := map[string]interface{}{} + if respData1.LaunchTemplateVersionData.SystemDisk.CdcId != nil { + systemDiskMap["cdc_id"] = respData1.LaunchTemplateVersionData.SystemDisk.CdcId + } - if launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.DiskType != nil { - systemDiskMap["disk_type"] = launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.DiskType + _ = d.Set("system_disk", []interface{}{systemDiskMap}) } - if launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.DiskId != nil { - systemDiskMap["disk_id"] = launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.DiskId - } + dataDisksList := make([]map[string]interface{}, 0, len(respData1.LaunchTemplateVersionData.DataDisks)) + if respData1.LaunchTemplateVersionData.DataDisks != nil { + for _, dataDisks := range respData1.LaunchTemplateVersionData.DataDisks { + dataDisksMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.DiskSize != nil { - systemDiskMap["disk_size"] = launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.DiskSize - } + if dataDisks.DiskSize != nil { + dataDisksMap["disk_size"] = dataDisks.DiskSize + } - if launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.CdcId != nil { - systemDiskMap["cdc_id"] = launchTemplateVersion.LaunchTemplateVersionData.SystemDisk.CdcId - } + if dataDisks.DiskType != nil { + dataDisksMap["disk_type"] = dataDisks.DiskType + } - _ = d.Set("system_disk", []interface{}{systemDiskMap}) - } + if dataDisks.DiskId != nil { + dataDisksMap["disk_id"] = dataDisks.DiskId + } - if launchTemplateVersion.LaunchTemplateVersionData.DataDisks != nil { - dataDisksList := []interface{}{} - for _, dataDisk := range launchTemplateVersion.LaunchTemplateVersionData.DataDisks { - dataDisksMap := map[string]interface{}{} + if dataDisks.DeleteWithInstance != nil { + dataDisksMap["delete_with_instance"] = dataDisks.DeleteWithInstance + } - if dataDisk.DiskSize != nil { - dataDisksMap["disk_size"] = dataDisk.DiskSize - } + if dataDisks.SnapshotId != nil { + dataDisksMap["snapshot_id"] = dataDisks.SnapshotId + } - if dataDisk.DiskType != nil { - dataDisksMap["disk_type"] = dataDisk.DiskType - } + if dataDisks.Encrypt != nil { + dataDisksMap["encrypt"] = dataDisks.Encrypt + } - if dataDisk.DiskId != nil { - dataDisksMap["disk_id"] = dataDisk.DiskId - } + if dataDisks.KmsKeyId != nil { + dataDisksMap["kms_key_id"] = dataDisks.KmsKeyId + } - if dataDisk.DeleteWithInstance != nil { - dataDisksMap["delete_with_instance"] = dataDisk.DeleteWithInstance - } + if dataDisks.ThroughputPerformance != nil { + dataDisksMap["throughput_performance"] = dataDisks.ThroughputPerformance + } + + if dataDisks.CdcId != nil { + dataDisksMap["cdc_id"] = dataDisks.CdcId + } - if dataDisk.SnapshotId != nil { - dataDisksMap["snapshot_id"] = dataDisk.SnapshotId + dataDisksList = append(dataDisksList, dataDisksMap) } - if dataDisk.Encrypt != nil { - dataDisksMap["encrypt"] = dataDisk.Encrypt + _ = d.Set("data_disks", dataDisksList) + } + internetAccessibleMap := map[string]interface{}{} + + if respData1.LaunchTemplateVersionData.InternetAccessible != nil { + if respData1.LaunchTemplateVersionData.InternetAccessible.InternetChargeType != nil { + internetAccessibleMap["internet_charge_type"] = respData1.LaunchTemplateVersionData.InternetAccessible.InternetChargeType } - if dataDisk.KmsKeyId != nil { - dataDisksMap["kms_key_id"] = dataDisk.KmsKeyId + if respData1.LaunchTemplateVersionData.InternetAccessible.InternetMaxBandwidthOut != nil { + internetAccessibleMap["internet_max_bandwidth_out"] = respData1.LaunchTemplateVersionData.InternetAccessible.InternetMaxBandwidthOut } - if dataDisk.ThroughputPerformance != nil { - dataDisksMap["throughput_performance"] = dataDisk.ThroughputPerformance + if respData1.LaunchTemplateVersionData.InternetAccessible.PublicIpAssigned != nil { + internetAccessibleMap["public_ip_assigned"] = respData1.LaunchTemplateVersionData.InternetAccessible.PublicIpAssigned } - if dataDisk.CdcId != nil { - dataDisksMap["cdc_id"] = dataDisk.CdcId + if respData1.LaunchTemplateVersionData.InternetAccessible.BandwidthPackageId != nil { + internetAccessibleMap["bandwidth_package_id"] = respData1.LaunchTemplateVersionData.InternetAccessible.BandwidthPackageId } - dataDisksList = append(dataDisksList, dataDisksMap) + _ = d.Set("internet_accessible", []interface{}{internetAccessibleMap}) } - _ = d.Set("data_disks", dataDisksList) - - } - - if launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud != nil { virtualPrivateCloudMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.VpcId != nil { - virtualPrivateCloudMap["vpc_id"] = launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.VpcId - } - - if launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.SubnetId != nil { - virtualPrivateCloudMap["subnet_id"] = launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.SubnetId - } - - if launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.AsVpcGateway != nil { - virtualPrivateCloudMap["as_vpc_gateway"] = launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.AsVpcGateway - } - - if launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.PrivateIpAddresses != nil { - virtualPrivateCloudMap["private_ip_addresses"] = launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.PrivateIpAddresses - } + if respData1.LaunchTemplateVersionData.VirtualPrivateCloud != nil { + if respData1.LaunchTemplateVersionData.VirtualPrivateCloud.VpcId != nil { + virtualPrivateCloudMap["vpc_id"] = respData1.LaunchTemplateVersionData.VirtualPrivateCloud.VpcId + } - if launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.Ipv6AddressCount != nil { - virtualPrivateCloudMap["ipv6_address_count"] = launchTemplateVersion.LaunchTemplateVersionData.VirtualPrivateCloud.Ipv6AddressCount - } + if respData1.LaunchTemplateVersionData.VirtualPrivateCloud.SubnetId != nil { + virtualPrivateCloudMap["subnet_id"] = respData1.LaunchTemplateVersionData.VirtualPrivateCloud.SubnetId + } - _ = d.Set("virtual_private_cloud", []interface{}{virtualPrivateCloudMap}) - } + if respData1.LaunchTemplateVersionData.VirtualPrivateCloud.AsVpcGateway != nil { + virtualPrivateCloudMap["as_vpc_gateway"] = respData1.LaunchTemplateVersionData.VirtualPrivateCloud.AsVpcGateway + } - if launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible != nil { - internetAccessibleMap := map[string]interface{}{} + if respData1.LaunchTemplateVersionData.VirtualPrivateCloud.PrivateIpAddresses != nil { + virtualPrivateCloudMap["private_ip_addresses"] = respData1.LaunchTemplateVersionData.VirtualPrivateCloud.PrivateIpAddresses + } - if launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.InternetChargeType != nil { - internetAccessibleMap["internet_charge_type"] = launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.InternetChargeType - } + if respData1.LaunchTemplateVersionData.VirtualPrivateCloud.Ipv6AddressCount != nil { + virtualPrivateCloudMap["ipv6_address_count"] = respData1.LaunchTemplateVersionData.VirtualPrivateCloud.Ipv6AddressCount + } - if launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.InternetMaxBandwidthOut != nil { - internetAccessibleMap["internet_max_bandwidth_out"] = launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.InternetMaxBandwidthOut + _ = d.Set("virtual_private_cloud", []interface{}{virtualPrivateCloudMap}) } - if launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.PublicIpAssigned != nil { - internetAccessibleMap["public_ip_assigned"] = launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.PublicIpAssigned + if respData1.LaunchTemplateVersionData.ImageId != nil { + _ = d.Set("image_id", respData1.LaunchTemplateVersionData.ImageId) } - if launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.BandwidthPackageId != nil { - internetAccessibleMap["bandwidth_package_id"] = launchTemplateVersion.LaunchTemplateVersionData.InternetAccessible.BandwidthPackageId + if respData1.LaunchTemplateVersionData.SecurityGroupIds != nil { + _ = d.Set("security_group_ids", respData1.LaunchTemplateVersionData.SecurityGroupIds) } - _ = d.Set("internet_accessible", []interface{}{internetAccessibleMap}) - } + loginSettingsMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.InstanceCount != nil { - _ = d.Set("instance_count", launchTemplateVersion.LaunchTemplateVersionData.InstanceCount) - } + if respData1.LaunchTemplateVersionData.LoginSettings != nil { + if respData1.LaunchTemplateVersionData.LoginSettings.Password != nil { + loginSettingsMap["password"] = respData1.LaunchTemplateVersionData.LoginSettings.Password + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceName != nil { - _ = d.Set("instance_name", launchTemplateVersion.LaunchTemplateVersionData.InstanceName) - } + if respData1.LaunchTemplateVersionData.LoginSettings.KeyIds != nil { + loginSettingsMap["key_ids"] = respData1.LaunchTemplateVersionData.LoginSettings.KeyIds + } - if launchTemplateVersion.LaunchTemplateVersionData.LoginSettings != nil { - loginSettingsMap := map[string]interface{}{} + if respData1.LaunchTemplateVersionData.LoginSettings.KeepImageLogin != nil { + loginSettingsMap["keep_image_login"] = respData1.LaunchTemplateVersionData.LoginSettings.KeepImageLogin + } - if launchTemplateVersion.LaunchTemplateVersionData.LoginSettings.Password != nil { - loginSettingsMap["password"] = launchTemplateVersion.LaunchTemplateVersionData.LoginSettings.Password + _ = d.Set("login_settings", []interface{}{loginSettingsMap}) } - if launchTemplateVersion.LaunchTemplateVersionData.LoginSettings.KeyIds != nil { - loginSettingsMap["key_ids"] = launchTemplateVersion.LaunchTemplateVersionData.LoginSettings.KeyIds + if respData1.LaunchTemplateVersionData.CamRoleName != nil { + _ = d.Set("cam_role_name", respData1.LaunchTemplateVersionData.CamRoleName) } - if launchTemplateVersion.LaunchTemplateVersionData.LoginSettings.KeepImageLogin != nil { - loginSettingsMap["keep_image_login"] = launchTemplateVersion.LaunchTemplateVersionData.LoginSettings.KeepImageLogin + if respData1.LaunchTemplateVersionData.HpcClusterId != nil { + _ = d.Set("hpc_cluster_id", respData1.LaunchTemplateVersionData.HpcClusterId) } - _ = d.Set("login_settings", []interface{}{loginSettingsMap}) - } - - if launchTemplateVersion.LaunchTemplateVersionData.SecurityGroupIds != nil { - _ = d.Set("security_group_ids", launchTemplateVersion.LaunchTemplateVersionData.SecurityGroupIds) - } + if respData1.LaunchTemplateVersionData.InstanceCount != nil { + _ = d.Set("instance_count", respData1.LaunchTemplateVersionData.InstanceCount) + } - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService != nil { enhancedServiceMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.SecurityService != nil { + if respData1.LaunchTemplateVersionData.EnhancedService != nil { securityServiceMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.SecurityService.Enabled != nil { - securityServiceMap["enabled"] = launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.SecurityService.Enabled - } + if respData1.LaunchTemplateVersionData.EnhancedService.SecurityService != nil { + if respData1.LaunchTemplateVersionData.EnhancedService.SecurityService.Enabled != nil { + securityServiceMap["enabled"] = respData1.LaunchTemplateVersionData.EnhancedService.SecurityService.Enabled + } - enhancedServiceMap["security_service"] = []interface{}{securityServiceMap} - } + enhancedServiceMap["security_service"] = []interface{}{securityServiceMap} + } - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.MonitorService != nil { monitorServiceMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.MonitorService.Enabled != nil { - monitorServiceMap["enabled"] = launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.MonitorService.Enabled - } + if respData1.LaunchTemplateVersionData.EnhancedService.MonitorService != nil { + if respData1.LaunchTemplateVersionData.EnhancedService.MonitorService.Enabled != nil { + monitorServiceMap["enabled"] = respData1.LaunchTemplateVersionData.EnhancedService.MonitorService.Enabled + } - enhancedServiceMap["monitor_service"] = []interface{}{monitorServiceMap} - } + enhancedServiceMap["monitor_service"] = []interface{}{monitorServiceMap} + } - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.AutomationService != nil { automationServiceMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.AutomationService.Enabled != nil { - automationServiceMap["enabled"] = launchTemplateVersion.LaunchTemplateVersionData.EnhancedService.AutomationService.Enabled + if respData1.LaunchTemplateVersionData.EnhancedService.AutomationService != nil { + if respData1.LaunchTemplateVersionData.EnhancedService.AutomationService.Enabled != nil { + automationServiceMap["enabled"] = respData1.LaunchTemplateVersionData.EnhancedService.AutomationService.Enabled + } + + enhancedServiceMap["automation_service"] = []interface{}{automationServiceMap} } - enhancedServiceMap["automation_service"] = []interface{}{automationServiceMap} + _ = d.Set("enhanced_service", []interface{}{enhancedServiceMap}) } - _ = d.Set("enhanced_service", []interface{}{enhancedServiceMap}) - } - - if launchTemplateVersion.LaunchTemplateVersionData.ClientToken != nil { - _ = d.Set("client_token", launchTemplateVersion.LaunchTemplateVersionData.ClientToken) - } - - if launchTemplateVersion.LaunchTemplateVersionData.HostName != nil { - _ = d.Set("host_name", launchTemplateVersion.LaunchTemplateVersionData.HostName) - } - - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer != nil { - actionTimerMap := map[string]interface{}{} - - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.TimerAction != nil { - actionTimerMap["timer_action"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.TimerAction + if respData1.LaunchTemplateVersionData.UserData != nil { + _ = d.Set("user_data", respData1.LaunchTemplateVersionData.UserData) } - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.ActionTime != nil { - actionTimerMap["action_time"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.ActionTime + if respData1.LaunchTemplateVersionData.DisasterRecoverGroupIds != nil { + _ = d.Set("disaster_recover_group_ids", respData1.LaunchTemplateVersionData.DisasterRecoverGroupIds) } - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals != nil { - externalsMap := map[string]interface{}{} + actionTimerMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.ReleaseAddress != nil { - externalsMap["release_address"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.ReleaseAddress + if respData1.LaunchTemplateVersionData.ActionTimer != nil { + if respData1.LaunchTemplateVersionData.ActionTimer.TimerAction != nil { + actionTimerMap["timer_action"] = respData1.LaunchTemplateVersionData.ActionTimer.TimerAction } - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.UnsupportNetworks != nil { - externalsMap["unsupport_networks"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.UnsupportNetworks + if respData1.LaunchTemplateVersionData.ActionTimer.ActionTime != nil { + actionTimerMap["action_time"] = respData1.LaunchTemplateVersionData.ActionTimer.ActionTime } - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr != nil { - storageBlockAttrMap := map[string]interface{}{} - - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.Type != nil { - storageBlockAttrMap["type"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.Type - } + externalsMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MinSize != nil { - storageBlockAttrMap["min_size"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MinSize + if respData1.LaunchTemplateVersionData.ActionTimer.Externals != nil { + if respData1.LaunchTemplateVersionData.ActionTimer.Externals.ReleaseAddress != nil { + externalsMap["release_address"] = respData1.LaunchTemplateVersionData.ActionTimer.Externals.ReleaseAddress } - if launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MaxSize != nil { - storageBlockAttrMap["max_size"] = launchTemplateVersion.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MaxSize + if respData1.LaunchTemplateVersionData.ActionTimer.Externals.UnsupportNetworks != nil { + externalsMap["unsupport_networks"] = respData1.LaunchTemplateVersionData.ActionTimer.Externals.UnsupportNetworks } - externalsMap["storage_block_attr"] = []interface{}{storageBlockAttrMap} - } + storageBlockAttrMap := map[string]interface{}{} - actionTimerMap["externals"] = []interface{}{externalsMap} - } + if respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr != nil { + if respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.Type != nil { + storageBlockAttrMap["type"] = respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.Type + } - _ = d.Set("action_timer", []interface{}{actionTimerMap}) - } + if respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MinSize != nil { + storageBlockAttrMap["min_size"] = respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MinSize + } - if launchTemplateVersion.LaunchTemplateVersionData.DisasterRecoverGroupIds != nil { - _ = d.Set("disaster_recover_group_ids", launchTemplateVersion.LaunchTemplateVersionData.DisasterRecoverGroupIds) - } + if respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MaxSize != nil { + storageBlockAttrMap["max_size"] = respData1.LaunchTemplateVersionData.ActionTimer.Externals.StorageBlockAttr.MaxSize + } - if launchTemplateVersion.LaunchTemplateVersionData.TagSpecification != nil { - tagSpecificationList := []interface{}{} - for _, tagSpecification := range launchTemplateVersion.LaunchTemplateVersionData.TagSpecification { - tagSpecificationMap := map[string]interface{}{} + externalsMap["storage_block_attr"] = []interface{}{storageBlockAttrMap} + } - if tagSpecification.ResourceType != nil { - tagSpecificationMap["resource_type"] = tagSpecification.ResourceType + actionTimerMap["externals"] = []interface{}{externalsMap} } - if tagSpecification.Tags != nil { - tagsList := []interface{}{} - for _, tag := range tagSpecification.Tags { - tagsMap := map[string]interface{}{} + _ = d.Set("action_timer", []interface{}{actionTimerMap}) + } - if tag.Key != nil { - tagsMap["key"] = tag.Key - } + instanceMarketOptionsMap := map[string]interface{}{} - if tag.Value != nil { - tagsMap["value"] = tag.Value - } + if respData1.LaunchTemplateVersionData.InstanceMarketOptions != nil { + spotOptionsMap := map[string]interface{}{} + + if respData1.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions != nil { + if respData1.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.MaxPrice != nil { + spotOptionsMap["max_price"] = respData1.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.MaxPrice + } - tagsList = append(tagsList, tagsMap) + if respData1.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.SpotInstanceType != nil { + spotOptionsMap["spot_instance_type"] = respData1.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.SpotInstanceType } - tagSpecificationMap["tags"] = []interface{}{tagsList} + instanceMarketOptionsMap["spot_options"] = []interface{}{spotOptionsMap} } - tagSpecificationList = append(tagSpecificationList, tagSpecificationMap) - } + if respData1.LaunchTemplateVersionData.InstanceMarketOptions.MarketType != nil { + instanceMarketOptionsMap["market_type"] = respData1.LaunchTemplateVersionData.InstanceMarketOptions.MarketType + } - _ = d.Set("tag_specification", tagSpecificationList) + _ = d.Set("instance_market_options", []interface{}{instanceMarketOptionsMap}) + } - } + if respData1.LaunchTemplateVersionData.HostName != nil { + _ = d.Set("host_name", respData1.LaunchTemplateVersionData.HostName) + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions != nil { - instanceMarketOptionsMap := map[string]interface{}{} + if respData1.LaunchTemplateVersionData.ClientToken != nil { + _ = d.Set("client_token", respData1.LaunchTemplateVersionData.ClientToken) + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions != nil { - spotOptionsMap := map[string]interface{}{} + instanceChargePrepaidMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.MaxPrice != nil { - spotOptionsMap["max_price"] = launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.MaxPrice + if respData1.LaunchTemplateVersionData.InstanceChargePrepaid != nil { + if respData1.LaunchTemplateVersionData.InstanceChargePrepaid.Period != nil { + instanceChargePrepaidMap["period"] = respData1.LaunchTemplateVersionData.InstanceChargePrepaid.Period } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.SpotInstanceType != nil { - spotOptionsMap["spot_instance_type"] = launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.SpotOptions.SpotInstanceType + if respData1.LaunchTemplateVersionData.InstanceChargePrepaid.RenewFlag != nil { + instanceChargePrepaidMap["renew_flag"] = respData1.LaunchTemplateVersionData.InstanceChargePrepaid.RenewFlag } - instanceMarketOptionsMap["spot_options"] = []interface{}{spotOptionsMap} - } - - if launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.MarketType != nil { - instanceMarketOptionsMap["market_type"] = launchTemplateVersion.LaunchTemplateVersionData.InstanceMarketOptions.MarketType + _ = d.Set("instance_charge_prepaid", []interface{}{instanceChargePrepaidMap}) } - _ = d.Set("instance_market_options", []interface{}{instanceMarketOptionsMap}) - } + tagSpecificationList := make([]map[string]interface{}, 0, len(respData1.LaunchTemplateVersionData.TagSpecification)) + if respData1.LaunchTemplateVersionData.TagSpecification != nil { + for _, tagSpecification := range respData1.LaunchTemplateVersionData.TagSpecification { + tagSpecificationMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.UserData != nil { - _ = d.Set("user_data", launchTemplateVersion.LaunchTemplateVersionData.UserData) - } + if tagSpecification.ResourceType != nil { + tagSpecificationMap["resource_type"] = tagSpecification.ResourceType + } - if launchTemplateVersion.LaunchTemplateVersionData.CamRoleName != nil { - _ = d.Set("cam_role_name", launchTemplateVersion.LaunchTemplateVersionData.CamRoleName) - } + tagsList := make([]map[string]interface{}, 0, len(tagSpecification.Tags)) + if tagSpecification.Tags != nil { + for _, tags := range tagSpecification.Tags { + tagsMap := map[string]interface{}{} - if launchTemplateVersion.LaunchTemplateVersionData.HpcClusterId != nil { - _ = d.Set("hpc_cluster_id", launchTemplateVersion.LaunchTemplateVersionData.HpcClusterId) - } + if tags.Key != nil { + tagsMap["key"] = tags.Key + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceChargeType != nil { - _ = d.Set("instance_charge_type", launchTemplateVersion.LaunchTemplateVersionData.InstanceChargeType) - } + if tags.Value != nil { + tagsMap["value"] = tags.Value + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceChargePrepaid != nil { - instanceChargePrepaidMap := map[string]interface{}{} + tagsList = append(tagsList, tagsMap) + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceChargePrepaid.Period != nil { - instanceChargePrepaidMap["period"] = launchTemplateVersion.LaunchTemplateVersionData.InstanceChargePrepaid.Period - } + tagSpecificationMap["tags"] = tagsList + } + tagSpecificationList = append(tagSpecificationList, tagSpecificationMap) + } - if launchTemplateVersion.LaunchTemplateVersionData.InstanceChargePrepaid.RenewFlag != nil { - instanceChargePrepaidMap["renew_flag"] = launchTemplateVersion.LaunchTemplateVersionData.InstanceChargePrepaid.RenewFlag + _ = d.Set("tag_specification", tagSpecificationList) } - - _ = d.Set("instance_charge_prepaid", []interface{}{instanceChargePrepaidMap}) } - // if launchTemplateVersion.LaunchTemplateVersionData.DisableApiTermination != nil { - // _ = d.Set("disable_api_termination", launchTemplateVersion.LaunchTemplateVersionData.DisableApiTermination) - // } + if respData1.LaunchTemplateVersionDescription != nil { + _ = d.Set("launch_template_version_description", respData1.LaunchTemplateVersionDescription) + } return nil } @@ -1386,14 +1377,32 @@ func resourceTencentCloudCvmLaunchTemplateDelete(d *schema.ResourceData, meta in defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} launchTemplateId := d.Id() - if err := service.DeleteCvmLaunchTemplateById(ctx, launchTemplateId); err != nil { + var ( + request = cvm.NewDeleteLaunchTemplateRequest() + response = cvm.NewDeleteLaunchTemplateResponse() + ) + + request.LaunchTemplateId = helper.String(launchTemplateId) + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DeleteLaunchTemplateWithContext(ctx, request) + if e != nil { + return tccommon.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 delete cvm launch template failed, reason:%+v", logId, err) return err } + _ = response return nil } diff --git a/tencentcloud/services/cvm/resource_tc_cvm_launch_template_extension.go b/tencentcloud/services/cvm/resource_tc_cvm_launch_template_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_cvm_launch_template_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/resource_tc_image.go b/tencentcloud/services/cvm/resource_tc_image.go index 57d1e8ffbc..4d7a3bf3c6 100644 --- a/tencentcloud/services/cvm/resource_tc_image.go +++ b/tencentcloud/services/cvm/resource_tc_image.go @@ -1,3 +1,4 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( @@ -5,15 +6,13 @@ import ( "fmt" "log" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit" + svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" ) func ResourceTencentCloudImage() *schema.Resource { @@ -25,13 +24,13 @@ func ResourceTencentCloudImage() *schema.Resource { Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - Schema: map[string]*schema.Schema{ "image_name": { Type: schema.TypeString, Required: true, Description: "Image name.", }, + "instance_id": { Type: schema.TypeString, Optional: true, @@ -39,46 +38,52 @@ func ResourceTencentCloudImage() *schema.Resource { ExactlyOneOf: []string{"snapshot_ids"}, Description: "Cloud server instance ID.", }, + "snapshot_ids": { Type: schema.TypeSet, Optional: true, ForceNew: true, ExactlyOneOf: []string{"instance_id"}, + Description: "Cloud disk snapshot ID list; creating a mirror based on a snapshot must include a system disk snapshot. It cannot be passed in simultaneously with InstanceId.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "Cloud disk snapshot ID list; creating a mirror based on a snapshot must include a system disk snapshot. It cannot be passed in simultaneously with InstanceId.", }, + "image_description": { Type: schema.TypeString, Optional: true, Description: "Image Description.", }, + "force_poweroff": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Set whether to force shutdown during mirroring. The default value is `false`, when set to true, it means that the mirror will be made after shutdown.", }, + "sysprep": { Type: schema.TypeBool, Optional: true, Description: "Sysprep function under Windows. When creating a Windows image, you can select true or false to enable or disable the Syspre function.", }, + "data_disk_ids": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - ForceNew: true, + Type: schema.TypeSet, + Optional: true, + Computed: true, + ForceNew: true, + Description: "Cloud disk ID list, When creating a whole machine image based on an instance, specify the data disk ID contained in the image.", Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "Cloud disk ID list, When creating a whole machine image based on an instance, specify the data disk ID contained in the image.", }, + "tags": { Type: schema.TypeMap, Optional: true, - Description: "Tags of the image.", + Description: "Tag description list.", }, }, } @@ -86,110 +91,84 @@ func ResourceTencentCloudImage() *schema.Resource { func resourceTencentCloudImageCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_image.create")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + var ( + imageId string + ) + var ( + request = cvm.NewCreateImageRequest() + response = cvm.NewCreateImageResponse() + ) + + if v, ok := d.GetOk("image_name"); ok { + request.ImageName = helper.String(v.(string)) } - request := cvm.NewCreateImageRequest() - request.ImageName = helper.String(d.Get("image_name").(string)) - if d.Get("force_poweroff").(bool) { - request.ForcePoweroff = helper.String(TRUE) - } else { - request.ForcePoweroff = helper.String(FALSE) + if v, ok := d.GetOk("instance_id"); ok { + request.InstanceId = helper.String(v.(string)) } if v, ok := d.GetOk("image_description"); ok { request.ImageDescription = helper.String(v.(string)) } - if v, ok := d.GetOkExists("sysprep"); ok { - value := v.(bool) - if value { - request.Sysprep = helper.String(TRUE) - } else { - request.Sysprep = helper.String(FALSE) - } - } + if v, ok := d.GetOk("data_disk_ids"); ok { - diskIds := v.(*schema.Set).List() - diskArr := make([]*string, 0, len(diskIds)) - for _, id := range diskIds { - diskArr = append(diskArr, helper.String(id.(string))) + dataDiskIdsSet := v.(*schema.Set).List() + for i := range dataDiskIdsSet { + dataDiskIds := dataDiskIdsSet[i].(string) + request.DataDiskIds = append(request.DataDiskIds, helper.String(dataDiskIds)) } - request.DataDiskIds = diskArr - } - if v, ok := d.GetOk("instance_id"); ok { - request.InstanceId = helper.String(v.(string)) } + if v, ok := d.GetOk("snapshot_ids"); ok { - ids := v.(*schema.Set).List() - snapshotIds := make([]*string, 0, len(ids)) - for _, v := range ids { - snapshotIds = append(snapshotIds, helper.String(v.(string))) + snapshotIdsSet := v.(*schema.Set).List() + for i := range snapshotIdsSet { + snapshotIds := snapshotIdsSet[i].(string) + request.SnapshotIds = append(request.SnapshotIds, helper.String(snapshotIds)) } - request.SnapshotIds = snapshotIds } - if len(request.SnapshotIds) > 0 && len(request.DataDiskIds) > 0 { - return fmt.Errorf("`%s` and `%s` Can't appear in the profile China at the same time,The parameter `%s` depends on the pre_parameter `%s`", - "snapshot_ids", "data_disk_ids", "data_disk_ids", "instance_id") - } - - if v := helper.GetTags(d, "tags"); len(v) > 0 { - tags := make([]*cvm.Tag, 0) - for tagKey, tagValue := range v { - tag := cvm.Tag{ - Key: helper.String(tagKey), - Value: helper.String(tagValue), - } - tags = append(tags, &tag) - } - tagSpecification := cvm.TagSpecification{ - ResourceType: helper.String("image"), - Tags: tags, - } - request.TagSpecification = append(request.TagSpecification, &tagSpecification) + if err := resourceTencentCloudImageCreatePostFillRequest0(ctx, request); err != nil { + return err } - imageId := "" err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - ratelimit.Check(request.GetAction()) - response, err := cvmService.client.UseCvmClient().CreateImage(request) - if err != nil { - log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", - logId, request.GetAction(), request.ToJsonString(), err.Error()) - return tccommon.RetryError(err) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateImageWithContext(ctx, request) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) } - imageId = *response.Response.ImageId + response = result return nil }) if err != nil { + log.Printf("[CRITAL]%s create image failed, reason:%+v", logId, err) + return err + } + + imageId = *response.Response.ImageId + + if err := resourceTencentCloudImageCreatePostHandleResponse0(ctx, response); err != nil { return err } + d.SetId(imageId) - // Wait for the tags attached to the vm since tags attachment it's async while vm creation. if tags := helper.GetTags(d, "tags"); len(tags) > 0 { - tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - tagService := svctag.NewTagService(tcClient) - resourceName := tccommon.BuildTagResourceName("cvm", "image", tcClient.Region, imageId) + tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region + resourceName := fmt.Sprintf("qcs::cvm:%s:uin/:image/%s", region, d.Id()) if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil { - // If tags attachment failed, the user will be notified, then plan/apply/update with terraform. return err } } - // wait for status - _, has, errRet := cvmService.DescribeImageById(ctx, imageId, false) - if errRet != nil { - return errRet - } - if !has { - return fmt.Errorf("[CRITAL]%s creating cvm image failed, image doesn't exist", logId) - } - return resourceTencentCloudImageRead(d, meta) } @@ -198,84 +177,113 @@ func resourceTencentCloudImageRead(d *schema.ResourceData, meta interface{}) err defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} imageId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - image, has, errRet := cvmService.DescribeImageById(ctx, imageId, false) - if errRet != nil { - return errRet - } - if !has { - d.SetId("") + var respData *cvm.Image + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeImageById(ctx, imageId) + if e != nil { + return tccommon.RetryError(e) + } + if err := resourceTencentCloudImageReadRequestOnSuccess0(ctx, result); err != nil { + return err + } + respData = result return nil + }) + if err != nil { + log.Printf("[CRITAL]%s read image failed, reason:%+v", logId, err) + return err } - _ = d.Set("image_name", image.ImageName) - if image.ImageDescription != nil && *image.ImageDescription != "" { - _ = d.Set("image_description", image.ImageDescription) + if respData == nil { + d.SetId("") + log.Printf("[WARN]%s resource `image` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) + return nil } - - // Use the resource value when the instance_id in the resource is not empty. - // the instance ID is not returned in the query response body. - instanceId := "" - if v, ok := d.GetOk("instance_id"); ok { - instanceId = v.(string) + if respData.ImageName != nil { + _ = d.Set("image_name", respData.ImageName) } - snapShotSysDisk := make([]interface{}, 0, len(image.SnapshotSet)) - for _, v := range image.SnapshotSet { - snapShotSysDisk = append(snapShotSysDisk, v.SnapshotId) + if respData.ImageDescription != nil { + _ = d.Set("image_description", respData.ImageDescription) } - if instanceId != "" { - _ = d.Set("instance_id", helper.String(instanceId)) - } else { - _ = d.Set("snapshot_ids", snapShotSysDisk) + if err := resourceTencentCloudImageReadPostHandleResponse0(ctx, respData); err != nil { + return err } - client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - tagService := svctag.NewTagService(client) - - tags, err := tagService.DescribeResourceTags(ctx, "cvm", "image", client.Region, d.Id()) + tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + tagService := svctag.NewTagService(tcClient) + tags, err := tagService.DescribeResourceTags(ctx, "cvm", "image", tcClient.Region, d.Id()) if err != nil { return err } _ = d.Set("tags", tags) + return nil } func resourceTencentCloudImageUpdate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_image.update")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - instanceId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + imageId := d.Id() + + needChange := false + mutableArgs := []string{"image_name", "image_description"} + for _, v := range mutableArgs { + if d.HasChange(v) { + needChange = true + break + } } - if d.HasChange("image_name") || d.HasChange("image_description") { - imageName := d.Get("image_name").(string) - imageDesc := d.Get("image_description").(string) + if needChange { + request := cvm.NewModifyImageAttributeRequest() - if err := cvmService.ModifyImage(ctx, instanceId, imageName, imageDesc); nil != err { + request.ImageId = helper.String(imageId) + + if v, ok := d.GetOk("image_name"); ok { + request.ImageName = helper.String(v.(string)) + } + + if v, ok := d.GetOk("image_description"); ok { + request.ImageDescription = helper.String(v.(string)) + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyImageAttributeWithContext(ctx, request) + if e != nil { + return tccommon.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 update image failed, reason:%+v", logId, err) return err } } if d.HasChange("tags") { - oldInterface, newInterface := d.GetChange("tags") - replaceTags, deleteTags := svctag.DiffTags(oldInterface.(map[string]interface{}), newInterface.(map[string]interface{})) - tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region - resourceName := tccommon.BuildTagResourceName("cvm", "image", region, instanceId) - err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) - if err != nil { + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + tagService := svctag.NewTagService(tcClient) + oldTags, newTags := d.GetChange("tags") + replaceTags, deleteTags := svctag.DiffTags(oldTags.(map[string]interface{}), newTags.(map[string]interface{})) + resourceName := tccommon.BuildTagResourceName("cvm", "image", tcClient.Region, d.Id()) + if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil { return err } } @@ -285,37 +293,37 @@ func resourceTencentCloudImageUpdate(d *schema.ResourceData, meta interface{}) e func resourceTencentCloudImageDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_image.delete")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) imageId := d.Id() - if err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - e := cvmService.DeleteImage(ctx, imageId) + var ( + request = cvm.NewDeleteImagesRequest() + response = cvm.NewDeleteImagesResponse() + ) + + request.ImageIds = []*string{helper.String(imageId)} + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DeleteImagesWithContext(ctx, request) if e != nil { return tccommon.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 - }); nil != err { + }) + if err != nil { + log.Printf("[CRITAL]%s delete image failed, reason:%+v", logId, err) return err } - //check image - if err := resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, has, err := cvmService.DescribeImageById(ctx, imageId, true) - if err != nil { - return tccommon.RetryError(err) - } - if has { - return resource.RetryableError(fmt.Errorf("image exits error,image_id = %s", imageId)) - } - return nil - }); nil != err { + _ = response + if err := resourceTencentCloudImageDeletePostHandleResponse0(ctx, response); err != nil { return err } diff --git a/tencentcloud/services/cvm/resource_tc_image_extension.go b/tencentcloud/services/cvm/resource_tc_image_extension.go new file mode 100644 index 0000000000..413a13c8c6 --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_image_extension.go @@ -0,0 +1,140 @@ +package cvm + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" +) + +func resourceTencentCloudImageCreatePostFillRequest0(ctx context.Context, req *cvm.CreateImageRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + + if d.Get("force_poweroff").(bool) { + req.ForcePoweroff = helper.String(TRUE) + } else { + req.ForcePoweroff = helper.String(FALSE) + } + + if v, ok := d.GetOkExists("sysprep"); ok { + value := v.(bool) + if value { + req.Sysprep = helper.String(TRUE) + } else { + req.Sysprep = helper.String(FALSE) + } + } + + if len(req.SnapshotIds) > 0 && len(req.DataDiskIds) > 0 { + return fmt.Errorf("`%s` and `%s` Can't appear in the profile China at the same time,The parameter `%s` depends on the pre_parameter `%s`", + "snapshot_ids", "data_disk_ids", "data_disk_ids", "instance_id") + } + + if v := helper.GetTags(d, "tags"); len(v) > 0 { + tags := make([]*cvm.Tag, 0) + for tagKey, tagValue := range v { + tag := cvm.Tag{ + Key: helper.String(tagKey), + Value: helper.String(tagValue), + } + tags = append(tags, &tag) + } + tagSpecification := cvm.TagSpecification{ + ResourceType: helper.String("image"), + Tags: tags, + } + req.TagSpecification = append(req.TagSpecification, &tagSpecification) + } + + return nil +} + +func resourceTencentCloudImageCreatePostHandleResponse0(ctx context.Context, resp *cvm.CreateImageResponse) error { + meta := tccommon.ProviderMetaFromContext(ctx) + logId := ctx.Value(tccommon.LogIdKey) + + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + imageId := *resp.Response.ImageId + + // wait for status + image, errRet := cvmService.DescribeImageById(ctx, imageId) + if errRet != nil { + return errRet + } + if image == nil { + return fmt.Errorf("[CRITAL]%s creating cvm image failed, image doesn't exist", logId) + } + return nil +} + +func resourceTencentCloudImageReadRequestOnSuccess0(ctx context.Context, resp *cvm.Image) *resource.RetryError { + logId := ctx.Value(tccommon.LogIdKey) + + if resp != nil { + if *resp.ImageState == "CREATEFAILED" { + return resource.NonRetryableError(fmt.Errorf("[CRITAL]%s Create Image is failed", logId)) + } + if *resp.ImageState != "NORMAL" { + return resource.RetryableError(fmt.Errorf("iamge instance status is processing")) + } + } + return nil +} + +func resourceTencentCloudImageReadPostHandleResponse0(ctx context.Context, resp *cvm.Image) error { + d := tccommon.ResourceDataFromContext(ctx) + + // Use the resource value when the instance_id in the resource is not empty. + // the instance ID is not returned in the query response body. + instanceId := "" + if v, ok := d.GetOk("instance_id"); ok { + instanceId = v.(string) + } + + snapShotSysDisk := make([]interface{}, 0, len(resp.SnapshotSet)) + for _, v := range resp.SnapshotSet { + snapShotSysDisk = append(snapShotSysDisk, v.SnapshotId) + } + + if instanceId != "" { + _ = d.Set("instance_id", helper.String(instanceId)) + } else { + _ = d.Set("snapshot_ids", snapShotSysDisk) + } + + return nil +} + +func resourceTencentCloudImageDeletePostHandleResponse0(ctx context.Context, resp *cvm.DeleteImagesResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + logId := ctx.Value(tccommon.LogIdKey) + + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + imageId := d.Id() + + //check image + err := resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { + result, e := cvmService.DescribeImageById(ctx, imageId) + if e != nil { + return tccommon.RetryError(e) + } + if result != nil { + return resource.RetryableError(fmt.Errorf("image exits error,image_id = %s", imageId)) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s read image failed, reason:%+v", logId, err) + return err + } + return nil +} diff --git a/tencentcloud/services/cvm/resource_tc_image_test.go b/tencentcloud/services/cvm/resource_tc_image_test.go index 37f2aee1c7..a20f8d510d 100644 --- a/tencentcloud/services/cvm/resource_tc_image_test.go +++ b/tencentcloud/services/cvm/resource_tc_image_test.go @@ -211,14 +211,14 @@ func testAccCheckCvmImageDestroy(s *terraform.State) error { continue } - _, has, err := cvmService.DescribeImageById(ctx, rs.Primary.ID, true) - if err != nil || has { + image, err := cvmService.DescribeImageById(ctx, rs.Primary.ID) + if err != nil || image != nil { err = resource.Retry(3*tccommon.ReadRetryTimeout, func() *resource.RetryError { - _, has, err = cvmService.DescribeImageById(ctx, rs.Primary.ID, true) + image, err = cvmService.DescribeImageById(ctx, rs.Primary.ID) if nil != err { return tccommon.RetryError(err) } - if has { + if image != nil { return resource.RetryableError(fmt.Errorf("image still exists: %s", rs.Primary.ID)) } return nil @@ -227,7 +227,7 @@ func testAccCheckCvmImageDestroy(s *terraform.State) error { if err != nil { return err } - if has { + if image != nil { return fmt.Errorf("image still exists: %s", rs.Primary.ID) } } @@ -248,11 +248,11 @@ func testAccCheckCvmImageExists(n string) resource.TestCheckFunc { return fmt.Errorf("image id is not set") } cvmService := svccvm.NewCvmService(tcacctest.AccProvider.Meta().(tccommon.ProviderMeta).GetAPIV3Conn()) - _, has, err := cvmService.DescribeImageById(ctx, rs.Primary.ID, false) + image, err := cvmService.DescribeImageById(ctx, rs.Primary.ID) if err != nil { return err } - if !has { + if image == nil { return fmt.Errorf("image doesn't exist: %s", rs.Primary.ID) } return nil diff --git a/tencentcloud/services/cvm/resource_tc_instance.go b/tencentcloud/services/cvm/resource_tc_instance.go index b2e8ff3e2f..46b6cfde8c 100644 --- a/tencentcloud/services/cvm/resource_tc_instance.go +++ b/tencentcloud/services/cvm/resource_tc_instance.go @@ -1,27 +1,18 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - "encoding/base64" "fmt" "log" - "sort" - "strconv" - "strings" "time" - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - svccbs "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/cbs" - svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/vpc" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit" ) func ResourceTencentCloudInstance() *schema.Resource { @@ -30,214 +21,232 @@ func ResourceTencentCloudInstance() *schema.Resource { Read: resourceTencentCloudInstanceRead, Update: resourceTencentCloudInstanceUpdate, Delete: resourceTencentCloudInstanceDelete, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(900000 * time.Millisecond), + }, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(15 * time.Minute), - }, Schema: map[string]*schema.Schema{ "image_id": { Type: schema.TypeString, Required: true, Description: "The image to use for the instance. Changing `image_id` will cause the instance reset.", }, + "availability_zone": { Type: schema.TypeString, Required: true, ForceNew: true, Description: "The available zone for the CVM instance.", }, + "instance_count": { Type: schema.TypeInt, Optional: true, + Description: "The number of instances to be purchased. Value range:[1,100]; default value: 1.", Deprecated: "It has been deprecated from version 1.59.18. Use built-in `count` instead.", ValidateFunc: tccommon.ValidateIntegerInRange(1, 100), - Description: "The number of instances to be purchased. Value range:[1,100]; default value: 1.", }, + "instance_name": { Type: schema.TypeString, Optional: true, Default: "Terraform-CVM-Instance", - ValidateFunc: tccommon.ValidateStringLengthInRange(2, 128), Description: "The name of the instance. The max length of instance_name is 60, and default value is `Terraform-CVM-Instance`.", + ValidateFunc: tccommon.ValidateStringLengthInRange(2, 128), }, + "instance_type": { Type: schema.TypeString, Optional: true, Computed: true, - ValidateFunc: tccommon.ValidateInstanceType, Description: "The type of the instance.", + ValidateFunc: tccommon.ValidateInstanceType, }, + "hostname": { Type: schema.TypeString, Optional: true, Description: "The hostname of the instance. Windows instance: The name should be a combination of 2 to 15 characters comprised of letters (case insensitive), numbers, and hyphens (-). Period (.) is not supported, and the name cannot be a string of pure numbers. Other types (such as Linux) of instances: The name should be a combination of 2 to 60 characters, supporting multiple periods (.). The piece between two periods is composed of letters (case insensitive), numbers, and hyphens (-). Modifying will cause the instance reset.", }, + "project_id": { Type: schema.TypeInt, Optional: true, Default: 0, Description: "The project the instance belongs to, default to 0.", }, + "running_flag": { Type: schema.TypeBool, Optional: true, Default: true, Description: "Set instance to running or stop. Default value is true, the instance will shutdown when this flag is false.", }, + "stopped_mode": { - Type: schema.TypeString, - Optional: true, - Description: "Billing method of a pay-as-you-go instance after shutdown. Available values: `KEEP_CHARGING`,`STOP_CHARGING`. Default `KEEP_CHARGING`.", - ValidateFunc: tccommon.ValidateAllowedStringValue([]string{ - CVM_STOP_MODE_KEEP_CHARGING, - CVM_STOP_MODE_STOP_CHARGING, - }), + Type: schema.TypeString, + Optional: true, + Description: "Billing method of a pay-as-you-go instance after shutdown. Available values: `KEEP_CHARGING`,`STOP_CHARGING`. Default `KEEP_CHARGING`.", + ValidateFunc: tccommon.ValidateAllowedStringValue([]string{CVM_STOP_MODE_KEEP_CHARGING, CVM_STOP_MODE_STOP_CHARGING}), }, + "placement_group_id": { Type: schema.TypeString, Optional: true, ForceNew: true, Description: "The ID of a placement group.", }, - // payment + "instance_charge_type": { Type: schema.TypeString, Optional: true, - Default: CVM_CHARGE_TYPE_POSTPAID, + Default: "POSTPAID_BY_HOUR", + Description: "The charge type of instance. Valid values are `PREPAID`, `POSTPAID_BY_HOUR`, `SPOTPAID` and `CDHPAID`. The default is `POSTPAID_BY_HOUR`. Note: TencentCloud International only supports `POSTPAID_BY_HOUR` and `CDHPAID`. `PREPAID` instance may not allow to delete before expired. `SPOTPAID` instance must set `spot_instance_type` and `spot_max_price` at the same time. `CDHPAID` instance must set `cdh_instance_type` and `cdh_host_id`.", ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_CHARGE_TYPE), - Description: "The charge type of instance. Valid values are `PREPAID`, `POSTPAID_BY_HOUR`, `SPOTPAID`, `CDHPAID` and `CDCPAID`. The default is `POSTPAID_BY_HOUR`. Note: TencentCloud International only supports `POSTPAID_BY_HOUR` and `CDHPAID`. `PREPAID` instance may not allow to delete before expired. `SPOTPAID` instance must set `spot_instance_type` and `spot_max_price` at the same time. `CDHPAID` instance must set `cdh_instance_type` and `cdh_host_id`.", }, + "instance_charge_type_prepaid_period": { Type: schema.TypeInt, Optional: true, + Description: "The tenancy (time unit is month) of the prepaid instance, NOTE: it only works when instance_charge_type is set to `PREPAID`. Valid values are `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `24`, `36`.", ValidateFunc: tccommon.ValidateAllowedIntValue(CVM_PREPAID_PERIOD), - Description: "The tenancy (time unit is month) of the prepaid instance, NOTE: it only works when instance_charge_type is set to `PREPAID`. Valid values are `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `24`, `36`, `48`, `60`.", }, + "instance_charge_type_prepaid_renew_flag": { Type: schema.TypeString, Optional: true, Computed: true, - ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_PREPAID_RENEW_FLAG), Description: "Auto renewal flag. Valid values: `NOTIFY_AND_AUTO_RENEW`: notify upon expiration and renew automatically, `NOTIFY_AND_MANUAL_RENEW`: notify upon expiration but do not renew automatically, `DISABLE_NOTIFY_AND_MANUAL_RENEW`: neither notify upon expiration nor renew automatically. Default value: `NOTIFY_AND_MANUAL_RENEW`. If this parameter is specified as `NOTIFY_AND_AUTO_RENEW`, the instance will be automatically renewed on a monthly basis if the account balance is sufficient. NOTE: it only works when instance_charge_type is set to `PREPAID`.", + ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_PREPAID_RENEW_FLAG), }, + "spot_instance_type": { Type: schema.TypeString, Optional: true, - ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_SPOT_INSTANCE_TYPE), Description: "Type of spot instance, only support `ONE-TIME` now. Note: it only works when instance_charge_type is set to `SPOTPAID`.", + ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_SPOT_INSTANCE_TYPE), }, + "spot_max_price": { Type: schema.TypeString, Optional: true, ForceNew: true, - ValidateFunc: tccommon.ValidateStringNumber, Description: "Max price of a spot instance, is the format of decimal string, for example \"0.50\". Note: it only works when instance_charge_type is set to `SPOTPAID`.", + ValidateFunc: tccommon.ValidateStringNumber, }, + "cdh_instance_type": { Type: schema.TypeString, Optional: true, - ValidateFunc: tccommon.ValidateStringPrefix("CDH_"), Description: "Type of instance created on cdh, the value of this parameter is in the format of CDH_XCXG based on the number of CPU cores and memory capacity. Note: it only works when instance_charge_type is set to `CDHPAID`.", + ValidateFunc: tccommon.ValidateStringPrefix("CDH_"), }, + "cdh_host_id": { Type: schema.TypeString, Optional: true, ForceNew: true, Description: "Id of cdh instance. Note: it only works when instance_charge_type is set to `CDHPAID`.", }, - // network + "internet_charge_type": { - Type: schema.TypeString, - Optional: true, - Computed: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - stopMode := d.Get("stopped_mode").(string) - if stopMode != CVM_STOP_MODE_STOP_CHARGING || !d.HasChange("running_flag") { - return old == new - } - return old == "" || new == "" - }, - ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_INTERNET_CHARGE_TYPE), - Description: "Internet charge type of the instance, Valid values are `BANDWIDTH_PREPAID`, `TRAFFIC_POSTPAID_BY_HOUR`, `BANDWIDTH_POSTPAID_BY_HOUR` and `BANDWIDTH_PACKAGE`. If not set, internet charge type are consistent with the cvm charge type by default. This value takes NO Effect when changing and does not need to be set when `allocate_public_ip` is false.", + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Internet charge type of the instance, Valid values are `BANDWIDTH_PREPAID`, `TRAFFIC_POSTPAID_BY_HOUR`, `BANDWIDTH_POSTPAID_BY_HOUR` and `BANDWIDTH_PACKAGE`. If not set, internet charge type are consistent with the cvm charge type by default. This value takes NO Effect when changing and does not need to be set when `allocate_public_ip` is false.", + ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_INTERNET_CHARGE_TYPE), + DiffSuppressFunc: internetChargeType, }, + "bandwidth_package_id": { Type: schema.TypeString, Optional: true, Description: "bandwidth package id. if user is standard user, then the bandwidth_package_id is needed, or default has bandwidth_package_id.", }, + "internet_max_bandwidth_out": { Type: schema.TypeInt, Optional: true, Computed: true, Description: "Maximum outgoing bandwidth to the public network, measured in Mbps (Mega bits per second). This value does not need to be set when `allocate_public_ip` is false.", }, + "allocate_public_ip": { Type: schema.TypeBool, Optional: true, - Default: false, ForceNew: true, + Default: false, Description: "Associate a public IP address with an instance in a VPC or Classic. Boolean value, Default is false.", }, - // vpc + "vpc_id": { Type: schema.TypeString, Optional: true, Computed: true, Description: "The ID of a VPC network. If you want to create instances in a VPC network, this parameter must be set.", }, + "subnet_id": { Type: schema.TypeString, Optional: true, Computed: true, Description: "The ID of a VPC subnet. If you want to create instances in a VPC network, this parameter must be set.", }, + "private_ip": { Type: schema.TypeString, Optional: true, Computed: true, Description: "The private IP to be assigned to this instance, must be in the provided subnet and available.", }, - // security group + "security_groups": { Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Computed: true, ConflictsWith: []string{"orderly_security_groups"}, Description: "A list of security group IDs to associate with.", Deprecated: "It will be deprecated. Use `orderly_security_groups` instead.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, "orderly_security_groups": { Type: schema.TypeList, - Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, Computed: true, ConflictsWith: []string{"security_groups"}, Description: "A list of orderly security group IDs to associate with.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - // storage + "system_disk_type": { Type: schema.TypeString, Optional: true, - Default: CVM_DISK_TYPE_CLOUD_PREMIUM, - ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_DISK_TYPE), + Default: "CLOUD_PREMIUM", Description: "System disk type. For more information on limits of system disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: `LOCAL_BASIC`: local disk, `LOCAL_SSD`: local SSD disk, `CLOUD_BASIC`: cloud disk, `CLOUD_SSD`: cloud SSD disk, `CLOUD_PREMIUM`: Premium Cloud Storage, `CLOUD_BSSD`: Basic SSD, `CLOUD_HSSD`: Enhanced SSD, `CLOUD_TSSD`: Tremendous SSD. NOTE: If modified, the instance may force stop.", + ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_DISK_TYPE), }, + "system_disk_size": { Type: schema.TypeInt, Optional: true, Default: 50, Description: "Size of the system disk. unit is GB, Default is 50GB. If modified, the instance may force stop.", }, + "system_disk_id": { Type: schema.TypeString, Optional: true, Computed: true, Description: "System disk snapshot ID used to initialize the system disk. When system disk type is `LOCAL_BASIC` and `LOCAL_SSD`, disk id is not supported.", }, + "data_disks": { Type: schema.TypeList, Optional: true, @@ -253,9 +262,8 @@ func ResourceTencentCloudInstance() *schema.Resource { Description: "Data disk type. For more information about limits on different data disk types, see [Storage Overview](https://intl.cloud.tencent.com/document/product/213/4952). Valid values: LOCAL_BASIC: local disk, LOCAL_SSD: local SSD disk, LOCAL_NVME: local NVME disk, specified in the InstanceType, LOCAL_PRO: local HDD disk, specified in the InstanceType, CLOUD_BASIC: HDD cloud disk, CLOUD_PREMIUM: Premium Cloud Storage, CLOUD_SSD: SSD, CLOUD_HSSD: Enhanced SSD, CLOUD_TSSD: Tremendous SSD, CLOUD_BSSD: Balanced SSD.", }, "data_disk_size": { - Type: schema.TypeInt, - Required: true, - //ForceNew: true, + Type: schema.TypeInt, + Required: true, Description: "Size of the data disk, and unit is GB.", }, "data_disk_snapshot_id": { @@ -273,49 +281,51 @@ func ResourceTencentCloudInstance() *schema.Resource { "delete_with_instance": { Type: schema.TypeBool, Optional: true, - Default: true, ForceNew: true, + Default: true, Description: "Decides whether the disk is deleted with instance(only applied to `CLOUD_BASIC`, `CLOUD_SSD` and `CLOUD_PREMIUM` disk with `POSTPAID_BY_HOUR` instance), default is true.", }, "encrypt": { Type: schema.TypeBool, Optional: true, - Default: false, ForceNew: true, + Default: false, Description: "Decides whether the disk is encrypted. Default is `false`.", }, "throughput_performance": { Type: schema.TypeInt, Optional: true, - Default: 0, ForceNew: true, + Default: 0, Description: "Add extra performance to the data disk. Only works when disk type is `CLOUD_TSSD` or `CLOUD_HSSD`.", }, }, }, }, - // enhance services + "disable_security_service": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Disable enhance service for security, it is enabled by default. When this options is set, security agent won't be installed. Modifying will cause the instance reset.", }, + "disable_monitor_service": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Disable enhance service for monitor, it is enabled by default. When this options is set, monitor agent won't be installed. Modifying will cause the instance reset.", }, - // login + "key_name": { Type: schema.TypeString, Optional: true, Computed: true, - Deprecated: "Please use `key_ids` instead.", ConflictsWith: []string{"key_ids"}, Description: "The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.", + Deprecated: "Please use `key_ids` instead.", }, + "key_ids": { Type: schema.TypeSet, Optional: true, @@ -323,28 +333,27 @@ func ResourceTencentCloudInstance() *schema.Resource { ConflictsWith: []string{"key_name", "password"}, Description: "The key pair to use for the instance, it looks like `skey-16jig7tx`. Modifying will cause the instance reset.", Set: schema.HashString, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, + "password": { Type: schema.TypeString, Optional: true, Sensitive: true, Description: "Password for the instance. In order for the new password to take effect, the instance will be restarted after the password change. Modifying will cause the instance reset.", }, + "keep_image_login": { - Type: schema.TypeBool, - Optional: true, - Default: false, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - if new == "false" && old == "" || old == "false" && new == "" { - return true - } else { - return old == new - } - }, - ConflictsWith: []string{"key_name", "key_ids", "password"}, - Description: "Whether to keep image login or not, default is `false`. When the image type is private or shared or imported, this parameter can be set `true`. Modifying will cause the instance reset.", + Type: schema.TypeBool, + Optional: true, + Default: false, + ConflictsWith: []string{"key_name", "key_ids", "password"}, + Description: "Whether to keep image login or not, default is `false`. When the image type is private or shared or imported, this parameter can be set `true`. Modifying will cause the instance reset.", + DiffSuppressFunc: keepImageLogin, }, + "user_data": { Type: schema.TypeString, Optional: true, @@ -352,6 +361,7 @@ func ResourceTencentCloudInstance() *schema.Resource { ConflictsWith: []string{"user_data_raw"}, Description: "The user data to be injected into this instance. Must be base64 encoded and up to 16 KB.", }, + "user_data_raw": { Type: schema.TypeString, Optional: true, @@ -359,66 +369,76 @@ func ResourceTencentCloudInstance() *schema.Resource { ConflictsWith: []string{"user_data"}, Description: "The user data to be injected into this instance, in plain text. Conflicts with `user_data`. Up to 16 KB after base64 encoded.", }, + "tags": { Type: schema.TypeMap, Optional: true, Description: "A mapping of tags to assign to the resource. For tag limits, please refer to [Use Limits](https://intl.cloud.tencent.com/document/product/651/13354).", }, + "force_delete": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Indicate whether to force delete the instance. Default is `false`. If set true, the instance will be permanently deleted instead of being moved into the recycle bin. Note: only works for `PREPAID` instance.", }, + "disable_api_termination": { Type: schema.TypeBool, Optional: true, Default: false, Description: "Whether the termination protection is enabled. Default is `false`. If set true, which means that this instance can not be deleted by an API action.", }, - // role + "cam_role_name": { Type: schema.TypeString, - ForceNew: true, Optional: true, + ForceNew: true, Description: "CAM role name authorized to access.", }, - // Computed values. + "instance_status": { Type: schema.TypeString, Computed: true, Description: "Current status of the instance.", }, + "public_ip": { Type: schema.TypeString, Computed: true, Description: "Public IP of the instance.", }, + "uuid": { Type: schema.TypeString, Computed: true, Description: "Globally unique ID of the instance.", }, + "create_time": { Type: schema.TypeString, Computed: true, Description: "Create time of the instance.", }, + "expired_time": { Type: schema.TypeString, Computed: true, Description: "Expired time 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.", }, + "os_name": { Type: schema.TypeString, Computed: true, @@ -430,328 +450,153 @@ func ResourceTencentCloudInstance() *schema.Resource { func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_instance.create")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + var ( + instanceId string + ) + var ( + request = cvm.NewRunInstancesRequest() + response = cvm.NewRunInstancesResponse() + ) + + if v, ok := d.GetOk("image_id"); ok { + request.ImageId = helper.String(v.(string)) } - request := cvm.NewRunInstancesRequest() - request.ImageId = helper.String(d.Get("image_id").(string)) - request.Placement = &cvm.Placement{ - Zone: helper.String(d.Get("availability_zone").(string)), + placement := cvm.Placement{} + if v, ok := d.GetOk("availability_zone"); ok { + placement.Zone = helper.String(v.(string)) } - if v, ok := d.GetOk("project_id"); ok { - projectId := int64(v.(int)) - request.Placement.ProjectId = &projectId + if v, ok := d.GetOkExists("project_id"); ok { + placement.ProjectId = helper.IntInt64(v.(int)) } + request.Placement = &placement + if v, ok := d.GetOk("instance_name"); ok { request.InstanceName = helper.String(v.(string)) } - if v, ok := d.GetOk("instance_count"); ok { - request.InstanceCount = helper.Int64(int64(v.(int))) + + if v, ok := d.GetOkExists("instance_count"); ok { + request.InstanceCount = helper.IntInt64(v.(int)) } + if v, ok := d.GetOk("instance_type"); ok { request.InstanceType = helper.String(v.(string)) } + if v, ok := d.GetOk("hostname"); ok { request.HostName = helper.String(v.(string)) } + if v, ok := d.GetOk("cam_role_name"); ok { request.CamRoleName = helper.String(v.(string)) } - if v, ok := d.GetOk("instance_charge_type"); ok { - instanceChargeType := v.(string) - request.InstanceChargeType = &instanceChargeType - if instanceChargeType == CVM_CHARGE_TYPE_PREPAID || instanceChargeType == CVM_CHARGE_TYPE_UNDERWRITE { - request.InstanceChargePrepaid = &cvm.InstanceChargePrepaid{} - if period, ok := d.GetOk("instance_charge_type_prepaid_period"); ok { - periodInt64 := int64(period.(int)) - request.InstanceChargePrepaid.Period = &periodInt64 - } - if renewFlag, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { - request.InstanceChargePrepaid.RenewFlag = helper.String(renewFlag.(string)) - } - } - if instanceChargeType == CVM_CHARGE_TYPE_SPOTPAID { - spotInstanceType, sitOk := d.GetOk("spot_instance_type") - spotMaxPrice, smpOk := d.GetOk("spot_max_price") - if sitOk || smpOk { - request.InstanceMarketOptions = &cvm.InstanceMarketOptionsRequest{} - request.InstanceMarketOptions.MarketType = helper.String(CVM_MARKET_TYPE_SPOT) - request.InstanceMarketOptions.SpotOptions = &cvm.SpotMarketOptions{} - } - if sitOk { - request.InstanceMarketOptions.SpotOptions.SpotInstanceType = helper.String(strings.ToLower(spotInstanceType.(string))) - } - if smpOk { - request.InstanceMarketOptions.SpotOptions.MaxPrice = helper.String(spotMaxPrice.(string)) - } - } - if instanceChargeType == CVM_CHARGE_TYPE_CDHPAID { - if v, ok := d.GetOk("cdh_instance_type"); ok { - request.InstanceType = helper.String(v.(string)) - } else { - return fmt.Errorf("cdh_instance_type can not be empty when instance_charge_type is %s", instanceChargeType) - } - if v, ok := d.GetOk("cdh_host_id"); ok { - request.Placement.HostIds = append(request.Placement.HostIds, helper.String(v.(string))) - } else { - return fmt.Errorf("cdh_host_id can not be empty when instance_charge_type is %s", instanceChargeType) - } - } - } - if v, ok := d.GetOk("placement_group_id"); ok { - request.DisasterRecoverGroupIds = []*string{helper.String(v.(string))} - } - - // network - request.InternetAccessible = &cvm.InternetAccessible{} + internetAccessible := cvm.InternetAccessible{} if v, ok := d.GetOk("internet_charge_type"); ok { - request.InternetAccessible.InternetChargeType = helper.String(v.(string)) + internetAccessible.InternetChargeType = helper.String(v.(string)) } - if v, ok := d.GetOk("internet_max_bandwidth_out"); ok { - maxBandwidthOut := int64(v.(int)) - request.InternetAccessible.InternetMaxBandwidthOut = &maxBandwidthOut + if v, ok := d.GetOkExists("internet_max_bandwidth_out"); ok { + internetAccessible.InternetMaxBandwidthOut = helper.IntInt64(v.(int)) } if v, ok := d.GetOk("bandwidth_package_id"); ok { - request.InternetAccessible.BandwidthPackageId = helper.String(v.(string)) + internetAccessible.BandwidthPackageId = helper.String(v.(string)) } if v, ok := d.GetOkExists("allocate_public_ip"); ok { - allocatePublicIp := v.(bool) - request.InternetAccessible.PublicIpAssigned = &allocatePublicIp - } - - // vpc - if v, ok := d.GetOk("vpc_id"); ok { - request.VirtualPrivateCloud = &cvm.VirtualPrivateCloud{} - request.VirtualPrivateCloud.VpcId = helper.String(v.(string)) - - if v, ok = d.GetOk("subnet_id"); ok { - request.VirtualPrivateCloud.SubnetId = helper.String(v.(string)) - } - - if v, ok = d.GetOk("private_ip"); ok { - request.VirtualPrivateCloud.PrivateIpAddresses = []*string{helper.String(v.(string))} - } + internetAccessible.PublicIpAssigned = helper.Bool(v.(bool)) } + request.InternetAccessible = &internetAccessible if v, ok := d.GetOk("security_groups"); ok { - securityGroups := v.(*schema.Set).List() - request.SecurityGroupIds = make([]*string, 0, len(securityGroups)) - for _, securityGroup := range securityGroups { - request.SecurityGroupIds = append(request.SecurityGroupIds, helper.String(securityGroup.(string))) - } - } - - if v, ok := d.GetOk("orderly_security_groups"); ok { - securityGroups := v.([]interface{}) - request.SecurityGroupIds = make([]*string, 0, len(securityGroups)) - for _, securityGroup := range securityGroups { - request.SecurityGroupIds = append(request.SecurityGroupIds, helper.String(securityGroup.(string))) + securityGroupIdsSet := v.(*schema.Set).List() + for i := range securityGroupIdsSet { + securityGroupIds := securityGroupIdsSet[i].(string) + request.SecurityGroupIds = append(request.SecurityGroupIds, helper.String(securityGroupIds)) } } - // storage - request.SystemDisk = &cvm.SystemDisk{} + systemDisk := cvm.SystemDisk{} if v, ok := d.GetOk("system_disk_type"); ok { - request.SystemDisk.DiskType = helper.String(v.(string)) + systemDisk.DiskType = helper.String(v.(string)) } - if v, ok := d.GetOk("system_disk_size"); ok { - diskSize := int64(v.(int)) - request.SystemDisk.DiskSize = &diskSize + if v, ok := d.GetOkExists("system_disk_size"); ok { + systemDisk.DiskSize = helper.IntInt64(v.(int)) } if v, ok := d.GetOk("system_disk_id"); ok { - request.SystemDisk.DiskId = helper.String(v.(string)) - } - if v, ok := d.GetOk("data_disks"); ok { - dataDisks := v.([]interface{}) - request.DataDisks = make([]*cvm.DataDisk, 0, len(dataDisks)) - for _, d := range dataDisks { - value := d.(map[string]interface{}) - diskType := value["data_disk_type"].(string) - diskSize := int64(value["data_disk_size"].(int)) - throughputPerformance := int64(value["throughput_performance"].(int)) - dataDisk := cvm.DataDisk{ - DiskType: &diskType, - DiskSize: &diskSize, - ThroughputPerformance: &throughputPerformance, - } - if v, ok := value["data_disk_snapshot_id"]; ok && v != nil { - snapshotId := v.(string) - if snapshotId != "" { - dataDisk.SnapshotId = helper.String(snapshotId) - } - } - if value["data_disk_id"] != "" { - dataDisk.DiskId = helper.String(value["data_disk_id"].(string)) - } - if deleteWithInstance, ok := value["delete_with_instance"]; ok { - deleteWithInstanceBool := deleteWithInstance.(bool) - dataDisk.DeleteWithInstance = &deleteWithInstanceBool - } - - if encrypt, ok := value["encrypt"]; ok { - encryptBool := encrypt.(bool) - dataDisk.Encrypt = &encryptBool - } - request.DataDisks = append(request.DataDisks, &dataDisk) - } + systemDisk.DiskId = helper.String(v.(string)) } + request.SystemDisk = &systemDisk - // enhanced service - request.EnhancedService = &cvm.EnhancedService{} + enhancedService := cvm.EnhancedService{} + runSecurityServiceEnabled := cvm.RunSecurityServiceEnabled{} if v, ok := d.GetOkExists("disable_security_service"); ok { - securityService := !(v.(bool)) - request.EnhancedService.SecurityService = &cvm.RunSecurityServiceEnabled{ - Enabled: &securityService, - } + runSecurityServiceEnabled.Enabled = helper.Bool(v.(bool)) } + enhancedService.SecurityService = &runSecurityServiceEnabled + runMonitorServiceEnabled := cvm.RunMonitorServiceEnabled{} if v, ok := d.GetOkExists("disable_monitor_service"); ok { - monitorService := !(v.(bool)) - request.EnhancedService.MonitorService = &cvm.RunMonitorServiceEnabled{ - Enabled: &monitorService, - } + runMonitorServiceEnabled.Enabled = helper.Bool(v.(bool)) } + enhancedService.MonitorService = &runMonitorServiceEnabled + request.EnhancedService = &enhancedService - // login - request.LoginSettings = &cvm.LoginSettings{} - keyIds := d.Get("key_ids").(*schema.Set).List() - if len(keyIds) > 0 { - request.LoginSettings.KeyIds = helper.InterfacesStringsPoint(keyIds) - } else if v, ok := d.GetOk("key_name"); ok { - request.LoginSettings.KeyIds = []*string{helper.String(v.(string))} - } + loginSettings := cvm.LoginSettings{} if v, ok := d.GetOk("password"); ok { - request.LoginSettings.Password = helper.String(v.(string)) - } - v := d.Get("keep_image_login").(bool) - if v { - request.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN) - } else { - request.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN_NOT) + loginSettings.Password = helper.String(v.(string)) } + request.LoginSettings = &loginSettings if v, ok := d.GetOk("user_data"); ok { request.UserData = helper.String(v.(string)) } - if v, ok := d.GetOk("user_data_raw"); ok { - userData := base64.StdEncoding.EncodeToString([]byte(v.(string))) - request.UserData = &userData - } if v, ok := d.GetOkExists("disable_api_termination"); ok { request.DisableApiTermination = helper.Bool(v.(bool)) } - if v := helper.GetTags(d, "tags"); len(v) > 0 { - tags := make([]*cvm.Tag, 0) - for tagKey, tagValue := range v { - tag := cvm.Tag{ - Key: helper.String(tagKey), - Value: helper.String(tagValue), - } - tags = append(tags, &tag) - } - tagSpecification := cvm.TagSpecification{ - ResourceType: helper.String("instance"), - Tags: tags, - } - request.TagSpecification = append(request.TagSpecification, &tagSpecification) + if err := resourceTencentCloudInstanceCreatePostFillRequest0(ctx, request); err != nil { + return err } - instanceId := "" - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - ratelimit.Check("create") - response, err := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().RunInstances(request) - if err != nil { - log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", - logId, request.GetAction(), request.ToJsonString(), err.Error()) - e, ok := err.(*sdkErrors.TencentCloudSDKError) - if ok && tccommon.IsContains(CVM_RETRYABLE_ERROR, e.Code) { - return resource.RetryableError(fmt.Errorf("cvm create error: %s, retrying", e.Error())) - } - return resource.NonRetryableError(err) - } - log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", - logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) - if len(response.Response.InstanceIdSet) < 1 { - err = fmt.Errorf("instance id is nil") - return resource.NonRetryableError(err) + if err := resourceTencentCloudInstanceCreatePreRequest0(ctx, request); err != nil { + return err } - instanceId = *response.Response.InstanceIdSet[0] - - return nil - }) - if err != nil { - return err - } - d.SetId(instanceId) - err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance != nil && *instance.InstanceState == CVM_STATUS_LAUNCH_FAILED { - //LatestOperationCodeMode - return resource.NonRetryableError(fmt.Errorf("cvm instance %s launch failed, this resource will not be stored to tfstate and will auto removed\n.", *instance.InstanceId)) - } - if instance != nil && *instance.InstanceState == CVM_STATUS_RUNNING { - return nil + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().RunInstancesWithContext(ctx, request) + if e != nil { + if err := resourceTencentCloudInstanceCreateRequestOnError0(ctx, request, e); err != nil { + return err + } + return tccommon.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 resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + response = result + return nil }) - if err != nil { + log.Printf("[CRITAL]%s create instance failed, reason:%+v", logId, err) return err } - // Wait for the tags attached to the vm since tags attachment it's async while vm creation. - if tags := helper.GetTags(d, "tags"); len(tags) > 0 { - tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - tagService := svctag.NewTagService(tcClient) - err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - actualTags, e := tagService.DescribeResourceTags(ctx, "cvm", "instance", tcClient.Region, instanceId) - if e != nil { - return resource.RetryableError(e) - } - for tagKey, tagValue := range tags { - if v, ok := actualTags[tagKey]; !ok || v != tagValue { - return resource.RetryableError(fmt.Errorf("tag(%s, %s) modification is not completed", tagKey, tagValue)) - } - } - return nil - }) - if err != nil { - return err - } + if len(response.Response.InstanceIdSet) < 1 { + return fmt.Errorf("resource `tencentcloud_instance` create failed.") } - if !(d.Get("running_flag").(bool)) { - stoppedMode := d.Get("stopped_mode").(string) - err = cvmService.StopInstance(ctx, instanceId, stoppedMode) - if err != nil { - return err - } + instanceId = *response.Response.InstanceIdSet[0] - err = resource.Retry(2*tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance != nil && *instance.InstanceState == CVM_STATUS_STOPPED { - return nil - } - return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) - }) - if err != nil { - return err - } + if err := resourceTencentCloudInstanceCreatePostHandleResponse0(ctx, response); err != nil { + return err } + d.SetId(instanceId) + return resourceTencentCloudInstanceRead(d, meta) } @@ -759,1009 +604,561 @@ func resourceTencentCloudInstanceRead(d *schema.ResourceData, meta interface{}) defer tccommon.LogElapsed("resource.tencentcloud_instance.read")() defer tccommon.InconsistentCheck(d, meta)() - var ( - logId = tccommon.GetLogId(tccommon.ContextNil) - ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - client = meta.(tccommon.ProviderMeta).GetAPIV3Conn() - cvmService = CvmService{client: client} - cbsService = svccbs.NewCbsService(client) - instanceId = d.Id() - ) + logId := tccommon.GetLogId(tccommon.ContextNil) - forceDelete := false - if v, ok := d.GetOkExists("force_delete"); ok { - forceDelete = v.(bool) - _ = d.Set("force_delete", forceDelete) - } + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) - var instance *cvm.Instance - var errRet error - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet = cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} - if instance != nil && instance.LatestOperationState != nil && *instance.LatestOperationState == "OPERATING" { - return resource.RetryableError(fmt.Errorf("waiting for instance %s operation", *instance.InstanceId)) - } + instanceId := d.Id() + var respData *cvm.Instance + reqErr := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeInstanceById(ctx, instanceId) + if e != nil { + return tccommon.RetryError(e) + } + if err := resourceTencentCloudInstanceReadRequestOnSuccess0(ctx, result); err != nil { + return err + } + respData = result return nil }) - - if err != nil { - return err + if reqErr != nil { + log.Printf("[CRITAL]%s read instance failed, reason:%+v", logId, reqErr) + return reqErr } - if instance == nil || *instance.InstanceState == CVM_STATUS_LAUNCH_FAILED { + if respData == nil { d.SetId("") - log.Printf("[CRITAL]instance %s not exist or launch failed", instanceId) + log.Printf("[WARN]%s resource `instance` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } + if err := resourceTencentCloudInstanceReadPreHandleResponse0(ctx, respData); err != nil { + return err + } - var cvmImages []string - var response *cvm.DescribeImagesResponse - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - request := cvm.NewDescribeImagesRequest() - response, errRet = client.UseCvmClient().DescribeImages(request) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) + if respData.Placement != nil { + if respData.Placement.Zone != nil { + _ = d.Set("availability_zone", respData.Placement.Zone) } - if *response.Response.TotalCount > 0 { - for i := range response.Response.ImageSet { - image := response.Response.ImageSet[i] - cvmImages = append(cvmImages, *image.ImageId) - } + + if respData.Placement.ProjectId != nil { + _ = d.Set("project_id", respData.Placement.ProjectId) } - return nil - }) - if err != nil { - return err } - if d.Get("image_id").(string) == "" || instance.ImageId == nil || !tccommon.IsContains(cvmImages, *instance.ImageId) { - _ = d.Set("image_id", instance.ImageId) + if respData.InstanceName != nil { + _ = d.Set("instance_name", respData.InstanceName) } - _ = d.Set("availability_zone", instance.Placement.Zone) - _ = d.Set("instance_name", instance.InstanceName) - _ = d.Set("instance_type", instance.InstanceType) - _ = d.Set("project_id", instance.Placement.ProjectId) - _ = d.Set("instance_charge_type", instance.InstanceChargeType) - _ = d.Set("instance_charge_type_prepaid_renew_flag", instance.RenewFlag) - _ = d.Set("internet_charge_type", instance.InternetAccessible.InternetChargeType) - _ = d.Set("internet_max_bandwidth_out", instance.InternetAccessible.InternetMaxBandwidthOut) - _ = d.Set("vpc_id", instance.VirtualPrivateCloud.VpcId) - _ = d.Set("subnet_id", instance.VirtualPrivateCloud.SubnetId) - _ = d.Set("security_groups", instance.SecurityGroupIds) - _ = d.Set("orderly_security_groups", instance.SecurityGroupIds) - _ = d.Set("system_disk_type", instance.SystemDisk.DiskType) - _ = d.Set("system_disk_size", instance.SystemDisk.DiskSize) - _ = d.Set("system_disk_id", instance.SystemDisk.DiskId) - _ = d.Set("instance_status", instance.InstanceState) - _ = d.Set("create_time", instance.CreatedTime) - _ = d.Set("expired_time", instance.ExpiredTime) - _ = d.Set("cam_role_name", instance.CamRoleName) - _ = d.Set("disable_api_termination", instance.DisableApiTermination) - _ = d.Set("cpu", instance.CPU) - _ = d.Set("memory", instance.Memory) - _ = d.Set("os_name", instance.OsName) - - if instance.Uuid != nil { - _ = d.Set("uuid", instance.Uuid) + if respData.InstanceType != nil { + _ = d.Set("instance_type", respData.InstanceType) } - if *instance.InstanceChargeType == CVM_CHARGE_TYPE_CDHPAID { - _ = d.Set("cdh_instance_type", instance.InstanceType) + if respData.InstanceChargeType != nil { + _ = d.Set("instance_charge_type", respData.InstanceChargeType) } - if _, ok := d.GetOkExists("allocate_public_ip"); !ok { - _ = d.Set("allocate_public_ip", len(instance.PublicIpAddresses) > 0) + if respData.RenewFlag != nil { + _ = d.Set("instance_charge_type_prepaid_renew_flag", respData.RenewFlag) } - tagService := svctag.NewTagService(client) + if respData.InternetAccessible != nil { + if respData.InternetAccessible.InternetChargeType != nil { + _ = d.Set("internet_charge_type", respData.InternetAccessible.InternetChargeType) + } + + if respData.InternetAccessible.InternetMaxBandwidthOut != nil { + _ = d.Set("internet_max_bandwidth_out", respData.InternetAccessible.InternetMaxBandwidthOut) + } - tags, err := tagService.DescribeResourceTags(ctx, "cvm", "instance", client.Region, d.Id()) - if err != nil { - return err } - // as attachment add tencentcloud:autoscaling:auto-scaling-group-id tag automatically - // we should remove this tag, otherwise it will cause terraform state change - delete(tags, "tencentcloud:autoscaling:auto-scaling-group-id") - _ = d.Set("tags", tags) - - //set data_disks - var hasDataDisks, isCombineDataDisks bool - dataDiskList := make([]map[string]interface{}, 0, len(instance.DataDisks)) - diskSizeMap := map[string]*uint64{} - diskOrderMap := make(map[string]int) - - if _, ok := d.GetOk("data_disks"); ok { - hasDataDisks = true - } - if len(instance.DataDisks) > 0 { - var diskIds []*string - for i := range instance.DataDisks { - id := instance.DataDisks[i].DiskId - size := instance.DataDisks[i].DiskSize - if id == nil { - continue - } - if strings.HasPrefix(*id, "disk-") { - diskIds = append(diskIds, id) - } else { - diskSizeMap[*id] = helper.Int64Uint64(*size) - } + + if respData.VirtualPrivateCloud != nil { + if respData.VirtualPrivateCloud.VpcId != nil { + _ = d.Set("vpc_id", respData.VirtualPrivateCloud.VpcId) } - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - disks, err := cbsService.DescribeDiskList(ctx, diskIds) - if err != nil { - return resource.NonRetryableError(err) - } - for i := range disks { - disk := disks[i] - if *disk.DiskState == "EXPANDING" { - return resource.RetryableError(fmt.Errorf("data_disk[%d] is expending", i)) - } - diskSizeMap[*disk.DiskId] = disk.DiskSize - if hasDataDisks { - items := strings.Split(*disk.DiskName, "_") - diskOrder := items[len(items)-1] - diskOrderInt, err := strconv.Atoi(diskOrder) - if err != nil { - isCombineDataDisks = true - continue - } - diskOrderMap[*disk.DiskId] = diskOrderInt - } - } - return nil - }) - if err != nil { - return err + + if respData.VirtualPrivateCloud.SubnetId != nil { + _ = d.Set("subnet_id", respData.VirtualPrivateCloud.SubnetId) } + } - for _, disk := range instance.DataDisks { - dataDisk := make(map[string]interface{}, 5) - dataDisk["data_disk_id"] = disk.DiskId - if disk.DiskId == nil { - dataDisk["data_disk_size"] = disk.DiskSize - } else if size, ok := diskSizeMap[*disk.DiskId]; ok { - dataDisk["data_disk_size"] = size - } - dataDisk["data_disk_type"] = disk.DiskType - dataDisk["data_disk_snapshot_id"] = disk.SnapshotId - dataDisk["delete_with_instance"] = disk.DeleteWithInstance - dataDisk["encrypt"] = disk.Encrypt - dataDisk["throughput_performance"] = disk.ThroughputPerformance - dataDiskList = append(dataDiskList, dataDisk) - } - if hasDataDisks && !isCombineDataDisks { - sort.SliceStable(dataDiskList, func(idx1, idx2 int) bool { - dataDiskIdIdx1 := *dataDiskList[idx1]["data_disk_id"].(*string) - dataDiskIdIdx2 := *dataDiskList[idx2]["data_disk_id"].(*string) - return diskOrderMap[dataDiskIdIdx1] < diskOrderMap[dataDiskIdIdx2] - }) + + if respData.SecurityGroupIds != nil { + _ = d.Set("security_groups", respData.SecurityGroupIds) } - _ = d.Set("data_disks", dataDiskList) - if len(instance.PrivateIpAddresses) > 0 { - _ = d.Set("private_ip", instance.PrivateIpAddresses[0]) + if respData.SecurityGroupIds != nil { + _ = d.Set("orderly_security_groups", respData.SecurityGroupIds) } - if len(instance.PublicIpAddresses) > 0 { - _ = d.Set("public_ip", instance.PublicIpAddresses[0]) + + if respData.SystemDisk != nil { + if respData.SystemDisk.DiskType != nil { + _ = d.Set("system_disk_type", respData.SystemDisk.DiskType) + } + + if respData.SystemDisk.DiskSize != nil { + _ = d.Set("system_disk_size", respData.SystemDisk.DiskSize) + } + + if respData.SystemDisk.DiskId != nil { + _ = d.Set("system_disk_id", respData.SystemDisk.DiskId) + } + } - if len(instance.LoginSettings.KeyIds) > 0 { - _ = d.Set("key_name", instance.LoginSettings.KeyIds[0]) - _ = d.Set("key_ids", instance.LoginSettings.KeyIds) - } else { - _ = d.Set("key_name", "") - _ = d.Set("key_ids", []*string{}) + + if respData.InstanceState != nil { + _ = d.Set("instance_status", respData.InstanceState) } - if instance.LoginSettings.KeepImageLogin != nil { - _ = d.Set("keep_image_login", *instance.LoginSettings.KeepImageLogin == CVM_IMAGE_LOGIN) + + if respData.CreatedTime != nil { + _ = d.Set("create_time", respData.CreatedTime) } - if *instance.InstanceState == CVM_STATUS_STOPPED { - _ = d.Set("running_flag", false) - } else { - _ = d.Set("running_flag", true) + if respData.ExpiredTime != nil { + _ = d.Set("expired_time", respData.ExpiredTime) } - return nil -} + if respData.CamRoleName != nil { + _ = d.Set("cam_role_name", respData.CamRoleName) + } -func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}) (err error) { - defer tccommon.LogElapsed("resource.tencentcloud_instance.update")() + if respData.DisableApiTermination != nil { + _ = d.Set("disable_api_termination", respData.DisableApiTermination) + } - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - instanceId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + if respData.CPU != nil { + _ = d.Set("cpu", respData.CPU) } - d.Partial(true) + if respData.Memory != nil { + _ = d.Set("memory", respData.Memory) + } - // Get the latest instance info from actual resource. - instanceInfo, err := cvmService.DescribeInstanceById(ctx, instanceId) - if err != nil { - return err + if respData.OsName != nil { + _ = d.Set("os_name", respData.OsName) } - var ( - periodSet = false - renewFlagSet = false - expectChargeType = CVM_CHARGE_TYPE_POSTPAID - currentChargeType = *instanceInfo.InstanceChargeType - ) + if respData.Uuid != nil { + _ = d.Set("uuid", respData.Uuid) + } - chargeType, chargeOk := d.GetOk("instance_charge_type") - if chargeOk { - expectChargeType = chargeType.(string) + if err := resourceTencentCloudInstanceReadPostHandleResponse0(ctx, respData); err != nil { + return err } - if d.HasChange("instance_charge_type") && expectChargeType != currentChargeType { - var ( - period = -1 - renewFlag string - ) + return nil +} - if v, ok := d.GetOk("instance_charge_type_prepaid_period"); ok { - period = v.(int) - } - if v, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { - renewFlag = v.(string) - } - // change charge type - err := cvmService.ModifyInstanceChargeType(ctx, instanceId, expectChargeType, period, renewFlag) - if err != nil { - return err - } - // query cvm status - err = waitForOperationFinished(d, meta, 5*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err +func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_instance.update")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + immutableArgs := []string{"instance_count", "stopped_mode", "spot_instance_type", "internet_charge_type", "bandwidth_package_id", "system_disk_id", "force_delete"} + for _, v := range immutableArgs { + if d.HasChange(v) { + return fmt.Errorf("argument `%s` cannot be changed", v) } - periodSet = true - renewFlagSet = true } + instanceId := d.Id() - // When instance is prepaid but period was empty and set to 1, skip this case. - op, np := d.GetChange("instance_charge_type_prepaid_period") - if _, ok := op.(int); !ok && np.(int) == 1 { - periodSet = true + if err := resourceTencentCloudInstanceUpdateOnStart(ctx); err != nil { + return err } - if d.HasChange("instance_charge_type_prepaid_period") && !periodSet { - chargeType := d.Get("instance_charge_type").(string) - period := d.Get("instance_charge_type_prepaid_period").(int) - renewFlag := "" - if v, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { - renewFlag = v.(string) - } - err := cvmService.ModifyInstanceChargeType(ctx, instanceId, chargeType, period, renewFlag) - if err != nil { - return err + needChange := false + mutableArgs := []string{"instance_name"} + for _, v := range mutableArgs { + if d.HasChange(v) { + needChange = true + break } - // query cvm status - err = waitForOperationFinished(d, meta, 5*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } - renewFlagSet = true } - if d.HasChange("instance_charge_type_prepaid_renew_flag") && !renewFlagSet { - //renew api - err := cvmService.ModifyRenewParam(ctx, instanceId, d.Get("instance_charge_type_prepaid_renew_flag").(string)) - if err != nil { - return err - } + if needChange { + request := cvm.NewModifyInstancesAttributeRequest() - //check success - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } - - time.Sleep(tccommon.ReadRetryTimeout) + request.InstanceIds = []*string{helper.String(instanceId)} - } + if v, ok := d.GetOk("instance_name"); ok { + request.InstanceName = helper.String(v.(string)) + } - if d.HasChange("instance_name") { - err := cvmService.ModifyInstanceName(ctx, instanceId, d.Get("instance_name").(string)) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyInstancesAttributeWithContext(ctx, request) + if e != nil { + return tccommon.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 update instance failed, reason:%+v", logId, err) return err } - } - if d.HasChange("disable_api_termination") { - err := cvmService.ModifyDisableApiTermination(ctx, instanceId, d.Get("disable_api_termination").(bool)) - if err != nil { - return err + needChange1 := false + mutableArgs1 := []string{"disable_api_termination"} + for _, v := range mutableArgs1 { + if d.HasChange(v) { + needChange1 = true + break } } - if d.HasChange("security_groups") { - securityGroups := d.Get("security_groups").(*schema.Set).List() - securityGroupIds := make([]*string, 0, len(securityGroups)) - for _, securityGroup := range securityGroups { - securityGroupIds = append(securityGroupIds, helper.String(securityGroup.(string))) - } - err := cvmService.ModifySecurityGroups(ctx, instanceId, securityGroupIds) - if err != nil { - return err - } + if needChange1 { + request1 := cvm.NewModifyInstancesAttributeRequest() - } + request1.InstanceIds = []*string{helper.String(instanceId)} - if d.HasChange("orderly_security_groups") { - orderlySecurityGroups := d.Get("orderly_security_groups").([]interface{}) - orderlySecurityGroupIds := make([]*string, 0, len(orderlySecurityGroups)) - for _, securityGroup := range orderlySecurityGroups { - orderlySecurityGroupIds = append(orderlySecurityGroupIds, helper.String(securityGroup.(string))) + if v, ok := d.GetOkExists("disable_api_termination"); ok { + request1.DisableApiTermination = helper.Bool(v.(bool)) } - err := cvmService.ModifySecurityGroups(ctx, instanceId, orderlySecurityGroupIds) + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyInstancesAttributeWithContext(ctx, request1) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request1.GetAction(), request1.ToJsonString(), result.ToJsonString()) + } + return nil + }) if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) return err } - } - if d.HasChange("project_id") { - projectId := d.Get("project_id").(int) - err := cvmService.ModifyProjectId(ctx, instanceId, int64(projectId)) - if err != nil { - return err + needChange2 := false + mutableArgs2 := []string{"security_groups"} + for _, v := range mutableArgs2 { + if d.HasChange(v) { + needChange2 = true + break } - } - // Reset Instance - // Keep Login Info - if d.HasChange("image_id") || - d.HasChange("hostname") || - d.HasChange("disable_security_service") || - d.HasChange("disable_monitor_service") || - d.HasChange("keep_image_login") { + if needChange2 { + request2 := cvm.NewModifyInstancesAttributeRequest() - request := cvm.NewResetInstanceRequest() - request.InstanceId = helper.String(d.Id()) + request2.InstanceIds = []*string{helper.String(instanceId)} - if v, ok := d.GetOk("image_id"); ok { - request.ImageId = helper.String(v.(string)) - } - if v, ok := d.GetOk("hostname"); ok { - request.HostName = helper.String(v.(string)) - } - - // enhanced service - request.EnhancedService = &cvm.EnhancedService{} - if d.HasChange("disable_security_service") { - v := d.Get("disable_security_service") - securityService := v.(bool) - request.EnhancedService.SecurityService = &cvm.RunSecurityServiceEnabled{ - Enabled: &securityService, + if v, ok := d.GetOk("security_groups"); ok { + securityGroupsSet := v.(*schema.Set).List() + for i := range securityGroupsSet { + securityGroups := securityGroupsSet[i].(string) + request2.SecurityGroups = append(request2.SecurityGroups, helper.String(securityGroups)) } } - if d.HasChange("disable_monitor_service") { - v := d.Get("disable_monitor_service") - monitorService := !(v.(bool)) - request.EnhancedService.MonitorService = &cvm.RunMonitorServiceEnabled{ - Enabled: &monitorService, + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyInstancesAttributeWithContext(ctx, request2) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request2.GetAction(), request2.ToJsonString(), result.ToJsonString()) } - } - - // Modify or keep login info when instance reset - request.LoginSettings = &cvm.LoginSettings{} - - if v, ok := d.GetOk("password"); ok { - request.LoginSettings.Password = helper.String(v.(string)) - } - - if v, ok := d.GetOk("key_ids"); ok { - request.LoginSettings.KeyIds = helper.InterfacesStringsPoint(v.(*schema.Set).List()) - } else if v, ok := d.GetOk("key_name"); ok { - request.LoginSettings.KeyIds = []*string{helper.String(v.(string))} - } - - if v := d.Get("keep_image_login").(bool); v { - request.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN) - } else { - request.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN_NOT) - } - - if err := cvmService.ResetInstance(ctx, request); err != nil { + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) return err } + } - // Modify Login Info Directly - } else { - if d.HasChange("password") { - err := cvmService.ModifyPassword(ctx, instanceId, d.Get("password").(string)) - if err != nil { - return err - } - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } + needChange3 := false + mutableArgs3 := []string{"orderly_security_groups"} + for _, v := range mutableArgs3 { + if d.HasChange(v) { + needChange3 = true + break } + } - if d.HasChange("key_name") { - o, n := d.GetChange("key_name") - oldKeyId := o.(string) - keyId := n.(string) - - if oldKeyId != "" { - err := cvmService.UnbindKeyPair(ctx, []*string{&oldKeyId}, []*string{&instanceId}) - if err != nil { - return err - } - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } - } + if needChange3 { + request3 := cvm.NewModifyInstancesAttributeRequest() + + request3.InstanceIds = []*string{helper.String(instanceId)} - if keyId != "" { - err = cvmService.BindKeyPair(ctx, []*string{&keyId}, instanceId) - if err != nil { - return err - } - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } + if v, ok := d.GetOk("orderly_security_groups"); ok { + securityGroupsSet := v.(*schema.Set).List() + for i := range securityGroupsSet { + securityGroups := securityGroupsSet[i].(string) + request3.SecurityGroups = append(request3.SecurityGroups, helper.String(securityGroups)) } } - // support remove old `key_name` to `key_ids`, so do not follow "else" - if d.HasChange("key_ids") { - o, n := d.GetChange("key_ids") - ov := o.(*schema.Set) - - nv := n.(*schema.Set) - - adds := nv.Difference(ov) - removes := ov.Difference(nv) - adds.Remove("") - removes.Remove("") - - if removes.Len() > 0 { - err := cvmService.UnbindKeyPair(ctx, helper.InterfacesStringsPoint(removes.List()), []*string{&instanceId}) - if err != nil { - return err - } - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } - } - if adds.Len() > 0 { - err = cvmService.BindKeyPair(ctx, helper.InterfacesStringsPoint(adds.List()), instanceId) - if err != nil { - return err - } - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyInstancesAttributeWithContext(ctx, request3) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request3.GetAction(), request3.ToJsonString(), result.ToJsonString()) } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) + return err } } - if d.HasChange("data_disks") { - o, n := d.GetChange("data_disks") - ov := o.([]interface{}) - nv := n.([]interface{}) - - if len(ov) != len(nv) { - return fmt.Errorf("error: data disk count has changed (%d -> %d) but doesn't support add or remove for now", len(ov), len(nv)) + needChange4 := false + mutableArgs4 := []string{"project_id"} + for _, v := range mutableArgs4 { + if d.HasChange(v) { + needChange4 = true + break } + } - cbsService := svccbs.NewCbsService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + if needChange4 { + request4 := cvm.NewModifyInstancesProjectRequest() - for i := range nv { - sizeKey := fmt.Sprintf("data_disks.%d.data_disk_size", i) - idKey := fmt.Sprintf("data_disks.%d.data_disk_id", i) - if !d.HasChange(sizeKey) { - continue - } - size := d.Get(sizeKey).(int) - diskId := d.Get(idKey).(string) + request4.InstanceIds = []*string{helper.String(instanceId)} - err := cbsService.ResizeDisk(ctx, diskId, size) + if v, ok := d.GetOkExists("project_id"); ok { + request4.ProjectId = helper.IntInt64(v.(int)) + } - if err != nil { - return fmt.Errorf("an error occurred when modifying %s, reason: %s", sizeKey, err.Error()) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyInstancesProjectWithContext(ctx, request4) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request4.GetAction(), request4.ToJsonString(), result.ToJsonString()) } - + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) + return err } } - var flag bool - if d.HasChange("running_flag") { - flag = d.Get("running_flag").(bool) - if err := switchInstance(&cvmService, ctx, d, flag); err != nil { - return err + needChange5 := false + mutableArgs5 := []string{"system_disk_size", "system_disk_type"} + for _, v := range mutableArgs5 { + if d.HasChange(v) { + needChange5 = true + break } - } - if d.HasChange("system_disk_size") || d.HasChange("system_disk_type") { + if needChange5 { + request5 := cvm.NewResizeInstanceDisksRequest() - size := d.Get("system_disk_size").(int) - diskType := d.Get("system_disk_type").(string) - //diskId := d.Get("system_disk_id").(string) - req := cvm.NewResizeInstanceDisksRequest() - req.InstanceId = &instanceId - req.ForceStop = helper.Bool(true) - req.SystemDisk = &cvm.SystemDisk{ - DiskSize: helper.IntInt64(size), - DiskType: &diskType, - } + response5 := cvm.NewResizeInstanceDisksResponse() - err := cvmService.ResizeInstanceDisks(ctx, req) - if err != nil { - return fmt.Errorf("an error occurred when modifying system_disk, reason: %s", err.Error()) + request5.InstanceId = helper.String(instanceId) + + forceStop := true + request5.ForceStop = &forceStop + + systemDisk := cvm.SystemDisk{} + if v, ok := d.GetOkExists("system_disk_size"); ok { + systemDisk.DiskSize = helper.IntInt64(v.(int)) + } + if v, ok := d.GetOk("system_disk_type"); ok { + systemDisk.DiskType = helper.String(v.(string)) } + request5.SystemDisk = &systemDisk - err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, err := cvmService.DescribeInstanceById(ctx, instanceId) - if err != nil { - return resource.NonRetryableError(err) - } - if instance != nil && instance.LatestOperationState != nil { - if *instance.InstanceState == "FAILED" { - return resource.NonRetryableError(fmt.Errorf("instance operation failed")) - } - if *instance.InstanceState == "OPERATING" { - return resource.RetryableError(fmt.Errorf("instance operating")) - } - } - if instance != nil && instance.SystemDisk != nil { - //wait until disk result as expected - if *instance.SystemDisk.DiskType != diskType || int(*instance.SystemDisk.DiskSize) != size { - return resource.RetryableError(fmt.Errorf("waiting for expanding success")) - } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ResizeInstanceDisksWithContext(ctx, request5) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request5.GetAction(), request5.ToJsonString(), result.ToJsonString()) } return nil }) - if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) return err } - - } - - if d.HasChange("instance_type") { - err := cvmService.ModifyInstanceType(ctx, instanceId, d.Get("instance_type").(string)) - if err != nil { + if err := resourceTencentCloudInstanceUpdatePreHandleResponse5(ctx, response5); err != nil { return err } - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err - } } - if d.HasChange("cdh_instance_type") { - err := cvmService.ModifyInstanceType(ctx, instanceId, d.Get("cdh_instance_type").(string)) - if err != nil { - return err - } - - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { - return err + needChange6 := false + mutableArgs6 := []string{"instance_type"} + for _, v := range mutableArgs6 { + if d.HasChange(v) { + needChange6 = true + break } } - if d.HasChange("vpc_id") || d.HasChange("subnet_id") || d.HasChange("private_ip") { - vpcId := d.Get("vpc_id").(string) - subnetId := d.Get("subnet_id").(string) - privateIp := d.Get("private_ip").(string) - err := cvmService.ModifyVpc(ctx, instanceId, vpcId, subnetId, privateIp) - if err != nil { - return err - } - } + if needChange6 { + request6 := cvm.NewResetInstancesTypeRequest() - if d.HasChange("tags") { - oldInterface, newInterface := d.GetChange("tags") - replaceTags, deleteTags := svctag.DiffTags(oldInterface.(map[string]interface{}), newInterface.(map[string]interface{})) - tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region - resourceName := tccommon.BuildTagResourceName("cvm", "instance", region, instanceId) - err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) - if err != nil { - return err - } - //except instance ,system disk and data disk will be tagged - //keep logical consistence with the console - //tag system disk - if systemDiskId, ok := d.GetOk("system_disk_id"); ok { - if systemDiskId.(string) != "" { - resourceName = tccommon.BuildTagResourceName("cvm", "volume", region, systemDiskId.(string)) - if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil { - return err - } - } - } - //tag disk ids - if dataDisks, ok := d.GetOk("data_disks"); ok { - dataDiskList := dataDisks.([]interface{}) - for _, dataDisk := range dataDiskList { - disk := dataDisk.(map[string]interface{}) - dataDiskId := disk["data_disk_id"].(string) - resourceName = tccommon.BuildTagResourceName("cvm", "volume", region, dataDiskId) - if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil { - return err - } - } - } + response6 := cvm.NewResetInstancesTypeResponse() - } + request6.InstanceIds = []*string{helper.String(instanceId)} - if d.HasChange("internet_max_bandwidth_out") { - chargeType := d.Get("internet_charge_type").(string) - bandWidthOut := int64(d.Get("internet_max_bandwidth_out").(int)) - if chargeType != "TRAFFIC_POSTPAID_BY_HOUR" && chargeType != "BANDWIDTH_POSTPAID_BY_HOUR" && chargeType != "BANDWIDTH_PACKAGE" { - return fmt.Errorf("charge type should be one of `TRAFFIC_POSTPAID_BY_HOUR BANDWIDTH_POSTPAID_BY_HOUR BANDWIDTH_PACKAGE` when adjusting internet_max_bandwidth_out") + if v, ok := d.GetOk("instance_type"); ok { + request6.InstanceType = helper.String(v.(string)) } - err := cvmService.ModifyInternetMaxBandwidthOut(ctx, instanceId, chargeType, bandWidthOut) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ResetInstancesTypeWithContext(ctx, request6) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request6.GetAction(), request6.ToJsonString(), result.ToJsonString()) + } + return nil + }) if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) return err } - - err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) - if err != nil { + if err := resourceTencentCloudInstanceUpdatePreHandleResponse6(ctx, response6); err != nil { return err } } - d.Partial(false) - - return resourceTencentCloudInstanceRead(d, meta) -} - -func resourceTencentCloudInstanceDelete(d *schema.ResourceData, meta interface{}) error { - defer tccommon.LogElapsed("resource.tencentcloud_instance.delete")() + needChange7 := false + mutableArgs7 := []string{"cdh_instance_type"} + for _, v := range mutableArgs7 { + if d.HasChange(v) { + needChange7 = true + break + } + } - logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + if needChange7 { + request7 := cvm.NewResetInstancesTypeRequest() - instanceId := d.Id() - //check is force delete or not - forceDelete := d.Get("force_delete").(bool) - instanceChargeType := d.Get("instance_charge_type").(string) + response7 := cvm.NewResetInstancesTypeResponse() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } + request7.InstanceIds = []*string{helper.String(instanceId)} - instance, err := cvmService.DescribeInstanceById(ctx, instanceId) - if err != nil { - return err - } - - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := cvmService.DeleteInstance(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet) + if v, ok := d.GetOk("cdh_instance_type"); ok { + request7.InstanceType = helper.String(v.(string)) } - return nil - }) - if err != nil { - return err - } - // prepaid need delete again - if instanceChargeType == CVM_CHARGE_TYPE_PREPAID { - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := cvmService.DeleteInstance(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ResetInstancesTypeWithContext(ctx, request7) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request7.GetAction(), request7.ToJsonString(), result.ToJsonString()) } return nil }) if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) return err } - } - - //check recycling - notExist := false - - //check exist - err = resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance == nil { - notExist = true - return nil - } - if *instance.InstanceState == CVM_STATUS_SHUTDOWN && *instance.LatestOperationState != CVM_LATEST_OPERATION_STATE_OPERATING { - //in recycling - return nil - } - return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) - }) - if err != nil { - return err - } - - vpcService := vpc.NewVpcService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - - if notExist { - err := waitIpRelease(ctx, vpcService, instance) - if err != nil { + if err := resourceTencentCloudInstanceUpdatePreHandleResponse7(ctx, response7); err != nil { return err } - return nil - } - if !forceDelete { - return nil } - // exist in recycle, delete again - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := cvmService.DeleteInstance(ctx, instanceId) - //when state is terminating, do not delete but check exist - if errRet != nil { - //check InvalidInstanceState.Terminating - ee, ok := errRet.(*sdkErrors.TencentCloudSDKError) - if !ok { - return tccommon.RetryError(errRet) - } - if ee.Code == "InvalidInstanceState.Terminating" { - return nil - } - return tccommon.RetryError(errRet, "OperationDenied.InstanceOperationInProgress") + needChange8 := false + mutableArgs8 := []string{"vpc_id", "subnet_id"} + for _, v := range mutableArgs8 { + if d.HasChange(v) { + needChange8 = true + break } - return nil - }) - if err != nil { - return err } - //describe and check not exist - err = resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance == nil { - return nil - } - return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) - }) - if err != nil { - return err - } - if v, ok := d.GetOk("data_disks"); ok { - dataDisks := v.([]interface{}) - for _, d := range dataDisks { - value := d.(map[string]interface{}) - diskId := value["data_disk_id"].(string) - deleteWithInstance := value["delete_with_instance"].(bool) - if deleteWithInstance { - cbsService := svccbs.NewCbsService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - err := resource.Retry(tccommon.ReadRetryTimeout*2, func() *resource.RetryError { - diskInfo, e := cbsService.DescribeDiskById(ctx, diskId) - if e != nil { - return tccommon.RetryError(e, tccommon.InternalError) - } - if *diskInfo.DiskState != svccbs.CBS_STORAGE_STATUS_UNATTACHED { - return resource.RetryableError(fmt.Errorf("cbs storage status is %s", *diskInfo.DiskState)) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s delete cbs failed, reason:%s\n ", logId, err.Error()) - return err - } - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - e := cbsService.DeleteDiskById(ctx, diskId) - if e != nil { - return tccommon.RetryError(e, tccommon.InternalError) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s delete cbs failed, reason:%s\n ", logId, err.Error()) - return err - } - err = resource.Retry(tccommon.ReadRetryTimeout*2, func() *resource.RetryError { - diskInfo, e := cbsService.DescribeDiskById(ctx, diskId) - if e != nil { - return tccommon.RetryError(e, tccommon.InternalError) - } - if *diskInfo.DiskState == svccbs.CBS_STORAGE_STATUS_TORECYCLE { - return resource.RetryableError(fmt.Errorf("cbs storage status is %s", *diskInfo.DiskState)) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s read cbs status failed, reason:%s\n ", logId, err.Error()) - return err - } - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - e := cbsService.DeleteDiskById(ctx, diskId) - if e != nil { - return tccommon.RetryError(e, tccommon.InternalError) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s delete cbs failed, reason:%s\n ", logId, err.Error()) - return err - } - err = resource.Retry(tccommon.ReadRetryTimeout*2, func() *resource.RetryError { - diskInfo, e := cbsService.DescribeDiskById(ctx, diskId) - if e != nil { - return tccommon.RetryError(e, tccommon.InternalError) - } - if diskInfo != nil { - return resource.RetryableError(fmt.Errorf("cbs storage status is %s", *diskInfo.DiskState)) - } - return nil - }) - if err != nil { - log.Printf("[CRITAL]%s read cbs status failed, reason:%s\n ", logId, err.Error()) - return err - } - } - } - } + if needChange8 { + request8 := cvm.NewModifyInstancesVpcAttributeRequest() - err = waitIpRelease(ctx, vpcService, instance) - if err != nil { - return err - } - return nil -} + request8.InstanceIds = []*string{helper.String(instanceId)} -func switchInstance(cvmService *CvmService, ctx context.Context, d *schema.ResourceData, flag bool) (err error) { - instanceId := d.Id() - if flag { - err = cvmService.StartInstance(ctx, instanceId) - if err != nil { - return err + virtualPrivateCloud := cvm.VirtualPrivateCloud{} + if v, ok := d.GetOk("vpc_id"); ok { + virtualPrivateCloud.VpcId = helper.String(v.(string)) } - err = resource.Retry(2*tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance != nil && *instance.InstanceState == CVM_STATUS_RUNNING { - return nil - } - return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) - }) - if err != nil { - return err + if v, ok := d.GetOk("subnet_id"); ok { + virtualPrivateCloud.SubnetId = helper.String(v.(string)) } - } else { - stoppedMode := d.Get("stopped_mode").(string) - skipStopApi := false - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - // when retry polling instance status, stop instance should skipped - if !skipStopApi { - err := cvmService.StopInstance(ctx, instanceId, stoppedMode) - if err != nil { - return resource.NonRetryableError(err) - } - } - instance, err := cvmService.DescribeInstanceById(ctx, instanceId) - if err != nil { - return resource.NonRetryableError(err) - } - if instance == nil { - return resource.NonRetryableError(fmt.Errorf("instance %s not found", instanceId)) - } + request8.VirtualPrivateCloud = &virtualPrivateCloud - if instance.LatestOperationState != nil { - operationState := *instance.LatestOperationState - if operationState == "OPERATING" { - skipStopApi = true - return resource.RetryableError(fmt.Errorf("instance %s stop operating, retrying", instanceId)) - } - if operationState == "FAILED" { - skipStopApi = false - return resource.RetryableError(fmt.Errorf("instance %s stop failed, retrying", instanceId)) - } - } - return nil - }) - if err != nil { + if err := resourceTencentCloudInstanceUpdatePostFillRequest8(ctx, request8); err != nil { return err } - err = resource.Retry(2*tccommon.ReadRetryTimeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance != nil && *instance.InstanceState == CVM_STATUS_STOPPED { - return nil + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyInstancesVpcAttributeWithContext(ctx, request8) + if e != nil { + return tccommon.RetryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request8.GetAction(), request8.ToJsonString(), result.ToJsonString()) } - return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + return nil }) if err != nil { + log.Printf("[CRITAL]%s update instance failed, reason:%+v", logId, err) return err } } - return nil + + if err := resourceTencentCloudInstanceUpdateOnExit(ctx); err != nil { + return err + } + + return resourceTencentCloudInstanceRead(d, meta) } -func waitForOperationFinished(d *schema.ResourceData, meta interface{}, timeout time.Duration, state string, immediately bool) error { +func resourceTencentCloudInstanceDelete(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_instance.delete")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - cvmService := CvmService{client} + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + instanceId := d.Id() - // We cannot catch LatestOperationState change immediately after modification returns, we must wait for LatestOperationState update to expected. - if !immediately { - time.Sleep(time.Second * 10) + + var ( + request = cvm.NewTerminateInstancesRequest() + response = cvm.NewTerminateInstancesResponse() + ) + + request.InstanceIds = []*string{helper.String(instanceId)} + + if err := resourceTencentCloudInstanceDeletePostFillRequest0(ctx, request); err != nil { + return err } - err := resource.Retry(timeout, func() *resource.RetryError { - instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if instance == nil { - return resource.NonRetryableError(fmt.Errorf("%s not exists", instanceId)) - } - if instance.LatestOperationState == nil { - return resource.RetryableError(fmt.Errorf("wait for operation update")) - } - if *instance.LatestOperationState == state { - return resource.RetryableError(fmt.Errorf("waiting for instance %s operation", instanceId)) - } - if *instance.LatestOperationState == CVM_LATEST_OPERATION_STATE_FAILED { - return resource.NonRetryableError(fmt.Errorf("failed operation")) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().TerminateInstancesWithContext(ctx, request) + if e != nil { + return tccommon.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 delete instance failed, reason:%+v", logId, err) return err } - return nil -} - -func waitIpRelease(ctx context.Context, vpcService vpc.VpcService, instance *cvm.Instance) error { - // wait ip release - if len(instance.PrivateIpAddresses) > 0 { - params := make(map[string]interface{}) - params["VpcId"] = instance.VirtualPrivateCloud.VpcId - params["SubnetId"] = instance.VirtualPrivateCloud.SubnetId - params["IpAddresses"] = instance.PrivateIpAddresses - err := resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { - usedIpAddress, errRet := vpcService.DescribeVpcUsedIpAddressByFilter(ctx, params) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - if len(usedIpAddress) > 0 { - return resource.RetryableError(fmt.Errorf("wait cvm private ip release...")) - } - return nil - }) - if err != nil { - return err - } + if err := resourceTencentCloudInstanceDeletePreHandleResponse0(ctx, response); err != nil { + return err } + + _ = response return nil } diff --git a/tencentcloud/services/cvm/resource_tc_instance_extension.go b/tencentcloud/services/cvm/resource_tc_instance_extension.go new file mode 100644 index 0000000000..d4e1d503a7 --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_instance_extension.go @@ -0,0 +1,1183 @@ +package cvm + +import ( + "context" + "encoding/base64" + "fmt" + "log" + "sort" + "strconv" + "strings" + "time" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/vpc" + + svccbs "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/cbs" + + svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" + + sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" +) + +func internetChargeType(k, oldValue, newValue string, d *schema.ResourceData) bool { + stopMode := d.Get("stopped_mode").(string) + if stopMode != CVM_STOP_MODE_STOP_CHARGING || !d.HasChange("running_flag") { + return oldValue == newValue + } + return oldValue == "" || newValue == "" +} + +func keepImageLogin(k, oldValue, newValue string, d *schema.ResourceData) bool { + if newValue == "false" && oldValue == "" || oldValue == "false" && newValue == "" { + return true + } else { + return oldValue == newValue + } +} + +func resourceTencentCloudInstanceCreatePostFillRequest0(ctx context.Context, req *cvm.RunInstancesRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + + if v, ok := d.GetOk("instance_charge_type"); ok { + instanceChargeType := v.(string) + req.InstanceChargeType = &instanceChargeType + if instanceChargeType == CVM_CHARGE_TYPE_PREPAID || instanceChargeType == CVM_CHARGE_TYPE_UNDERWRITE { + req.InstanceChargePrepaid = &cvm.InstanceChargePrepaid{} + if period, ok := d.GetOk("instance_charge_type_prepaid_period"); ok { + periodInt64 := int64(period.(int)) + req.InstanceChargePrepaid.Period = &periodInt64 + } + if renewFlag, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { + req.InstanceChargePrepaid.RenewFlag = helper.String(renewFlag.(string)) + } + } + if instanceChargeType == CVM_CHARGE_TYPE_SPOTPAID { + spotInstanceType, sitOk := d.GetOk("spot_instance_type") + spotMaxPrice, smpOk := d.GetOk("spot_max_price") + if sitOk || smpOk { + req.InstanceMarketOptions = &cvm.InstanceMarketOptionsRequest{} + req.InstanceMarketOptions.MarketType = helper.String(CVM_MARKET_TYPE_SPOT) + req.InstanceMarketOptions.SpotOptions = &cvm.SpotMarketOptions{} + } + if sitOk { + req.InstanceMarketOptions.SpotOptions.SpotInstanceType = helper.String(strings.ToLower(spotInstanceType.(string))) + } + if smpOk { + req.InstanceMarketOptions.SpotOptions.MaxPrice = helper.String(spotMaxPrice.(string)) + } + } + if instanceChargeType == CVM_CHARGE_TYPE_CDHPAID { + if v, ok := d.GetOk("cdh_instance_type"); ok { + req.InstanceType = helper.String(v.(string)) + } else { + return fmt.Errorf("cdh_instance_type can not be empty when instance_charge_type is %s", instanceChargeType) + } + if v, ok := d.GetOk("cdh_host_id"); ok { + req.Placement.HostIds = append(req.Placement.HostIds, helper.String(v.(string))) + } else { + return fmt.Errorf("cdh_host_id can not be empty when instance_charge_type is %s", instanceChargeType) + } + } + } + + if v, ok := d.GetOk("placement_group_id"); ok { + req.DisasterRecoverGroupIds = []*string{helper.String(v.(string))} + } + + if v, ok := d.GetOk("orderly_security_groups"); ok { + securityGroups := v.([]interface{}) + req.SecurityGroupIds = make([]*string, 0, len(securityGroups)) + for _, securityGroup := range securityGroups { + req.SecurityGroupIds = append(req.SecurityGroupIds, helper.String(securityGroup.(string))) + } + } + + // storage + if v, ok := d.GetOk("data_disks"); ok { + dataDisks := v.([]interface{}) + req.DataDisks = make([]*cvm.DataDisk, 0, len(dataDisks)) + for _, d := range dataDisks { + value := d.(map[string]interface{}) + diskType := value["data_disk_type"].(string) + diskSize := int64(value["data_disk_size"].(int)) + throughputPerformance := int64(value["throughput_performance"].(int)) + dataDisk := cvm.DataDisk{ + DiskType: &diskType, + DiskSize: &diskSize, + ThroughputPerformance: &throughputPerformance, + } + if v, ok := value["data_disk_snapshot_id"]; ok && v != nil { + snapshotId := v.(string) + if snapshotId != "" { + dataDisk.SnapshotId = helper.String(snapshotId) + } + } + if value["data_disk_id"] != "" { + dataDisk.DiskId = helper.String(value["data_disk_id"].(string)) + } + if deleteWithInstance, ok := value["delete_with_instance"]; ok { + deleteWithInstanceBool := deleteWithInstance.(bool) + dataDisk.DeleteWithInstance = &deleteWithInstanceBool + } + + if encrypt, ok := value["encrypt"]; ok { + encryptBool := encrypt.(bool) + dataDisk.Encrypt = &encryptBool + } + req.DataDisks = append(req.DataDisks, &dataDisk) + } + } + + // vpc + if v, ok := d.GetOk("vpc_id"); ok { + req.VirtualPrivateCloud = &cvm.VirtualPrivateCloud{} + req.VirtualPrivateCloud.VpcId = helper.String(v.(string)) + + if v, ok = d.GetOk("subnet_id"); ok { + req.VirtualPrivateCloud.SubnetId = helper.String(v.(string)) + } + + if v, ok = d.GetOk("private_ip"); ok { + req.VirtualPrivateCloud.PrivateIpAddresses = []*string{helper.String(v.(string))} + } + } + + // login + keyIds := d.Get("key_ids").(*schema.Set).List() + if len(keyIds) > 0 { + req.LoginSettings.KeyIds = helper.InterfacesStringsPoint(keyIds) + } else if v, ok := d.GetOk("key_name"); ok { + req.LoginSettings.KeyIds = []*string{helper.String(v.(string))} + } + v := d.Get("keep_image_login").(bool) + if v { + req.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN) + } else { + req.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN_NOT) + } + + if v, ok := d.GetOk("user_data_raw"); ok { + userData := base64.StdEncoding.EncodeToString([]byte(v.(string))) + req.UserData = &userData + } + + if v := helper.GetTags(d, "tags"); len(v) > 0 { + tags := make([]*cvm.Tag, 0) + for tagKey, tagValue := range v { + tag := cvm.Tag{ + Key: helper.String(tagKey), + Value: helper.String(tagValue), + } + tags = append(tags, &tag) + } + tagSpecification := cvm.TagSpecification{ + ResourceType: helper.String("instance"), + Tags: tags, + } + req.TagSpecification = append(req.TagSpecification, &tagSpecification) + } + + return nil +} + +func resourceTencentCloudInstanceCreatePreRequest0(ctx context.Context, req *cvm.RunInstancesRequest) *resource.RetryError { + ratelimit.Check("create") + return nil +} + +func resourceTencentCloudInstanceCreateRequestOnError0(ctx context.Context, req *cvm.RunInstancesRequest, e error) *resource.RetryError { + logId := ctx.Value(tccommon.LogIdKey) + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", + logId, req.GetAction(), req.ToJsonString(), e.Error()) + + err, ok := e.(*sdkErrors.TencentCloudSDKError) + if ok && tccommon.IsContains(CVM_RETRYABLE_ERROR, err.Code) { + return resource.RetryableError(fmt.Errorf("cvm create error: %s, retrying", err.Error())) + } + return resource.NonRetryableError(e) +} + +func resourceTencentCloudInstanceCreatePostHandleResponse0(ctx context.Context, resp *cvm.RunInstancesResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + instanceId := *resp.Response.InstanceIdSet[0] + + err := resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance != nil && *instance.InstanceState == CVM_STATUS_LAUNCH_FAILED { + //LatestOperationCodeMode + return resource.NonRetryableError(fmt.Errorf("cvm instance %s launch failed, this resource will not be stored to tfstate and will auto removed\n.", *instance.InstanceId)) + } + if instance != nil && *instance.InstanceState == CVM_STATUS_RUNNING { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + + if err != nil { + return err + } + + // Wait for the tags attached to the vm since tags attachment it's async while vm creation. + if tags := helper.GetTags(d, "tags"); len(tags) > 0 { + tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + tagService := svctag.NewTagService(tcClient) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + actualTags, e := tagService.DescribeResourceTags(ctx, "cvm", "instance", tcClient.Region, instanceId) + if e != nil { + return resource.RetryableError(e) + } + for tagKey, tagValue := range tags { + if v, ok := actualTags[tagKey]; !ok || v != tagValue { + return resource.RetryableError(fmt.Errorf("tag(%s, %s) modification is not completed", tagKey, tagValue)) + } + } + return nil + }) + if err != nil { + return err + } + } + + if !(d.Get("running_flag").(bool)) { + stoppedMode := d.Get("stopped_mode").(string) + err = cvmService.StopInstance(ctx, instanceId, stoppedMode) + if err != nil { + return err + } + + err = resource.Retry(2*tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance != nil && *instance.InstanceState == CVM_STATUS_STOPPED { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + if err != nil { + return err + } + } + + return nil +} + +func resourceTencentCloudInstanceReadRequestOnSuccess0(ctx context.Context, resp *cvm.Instance) *resource.RetryError { + if resp != nil && resp.LatestOperationState != nil && *resp.LatestOperationState == "OPERATING" { + return resource.RetryableError(fmt.Errorf("waiting for instance %s operation", *resp.InstanceId)) + } + return nil +} + +func resourceTencentCloudInstanceReadPreHandleResponse0(ctx context.Context, resp *cvm.Instance) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + instanceId := d.Id() + + if *resp.InstanceState == CVM_STATUS_LAUNCH_FAILED { + d.SetId("") + log.Printf("[CRITAL]instance %s not exist or launch failed", instanceId) + return nil + } + + var errRet error + var cvmImages []string + var response *cvm.DescribeImagesResponse + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + request := cvm.NewDescribeImagesRequest() + response, errRet = client.UseCvmClient().DescribeImages(request) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if *response.Response.TotalCount > 0 { + for i := range response.Response.ImageSet { + image := response.Response.ImageSet[i] + cvmImages = append(cvmImages, *image.ImageId) + } + } + return nil + }) + if err != nil { + return err + } + + if d.Get("image_id").(string) == "" || resp.ImageId == nil || !tccommon.IsContains(cvmImages, *resp.ImageId) { + _ = d.Set("image_id", resp.ImageId) + } + + return nil +} + +func resourceTencentCloudInstanceReadPostHandleResponse0(ctx context.Context, resp *cvm.Instance) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + cbsService := svccbs.NewCbsService(client) + + instance := resp + + if *instance.InstanceChargeType == CVM_CHARGE_TYPE_CDHPAID { + _ = d.Set("cdh_instance_type", instance.InstanceType) + } + + if _, ok := d.GetOkExists("allocate_public_ip"); !ok { + _ = d.Set("allocate_public_ip", len(instance.PublicIpAddresses) > 0) + } + + tagService := svctag.NewTagService(client) + tags, err := tagService.DescribeResourceTags(ctx, "cvm", "instance", client.Region, d.Id()) + if err != nil { + return err + } + // as attachment add tencentcloud:autoscaling:auto-scaling-group-id tag automatically + // we should remove this tag, otherwise it will cause terraform state change + delete(tags, "tencentcloud:autoscaling:auto-scaling-group-id") + _ = d.Set("tags", tags) + + //set data_disks + var hasDataDisks, isCombineDataDisks bool + dataDiskList := make([]map[string]interface{}, 0, len(instance.DataDisks)) + diskSizeMap := map[string]*uint64{} + diskOrderMap := make(map[string]int) + + if _, ok := d.GetOk("data_disks"); ok { + hasDataDisks = true + } + if len(instance.DataDisks) > 0 { + var diskIds []*string + for i := range instance.DataDisks { + id := instance.DataDisks[i].DiskId + size := instance.DataDisks[i].DiskSize + if id == nil { + continue + } + if strings.HasPrefix(*id, "disk-") { + diskIds = append(diskIds, id) + } else { + diskSizeMap[*id] = helper.Int64Uint64(*size) + } + } + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + disks, err := cbsService.DescribeDiskList(ctx, diskIds) + if err != nil { + return resource.NonRetryableError(err) + } + for i := range disks { + disk := disks[i] + if *disk.DiskState == "EXPANDING" { + return resource.RetryableError(fmt.Errorf("data_disk[%d] is expending", i)) + } + diskSizeMap[*disk.DiskId] = disk.DiskSize + if hasDataDisks { + items := strings.Split(*disk.DiskName, "_") + diskOrder := items[len(items)-1] + diskOrderInt, err := strconv.Atoi(diskOrder) + if err != nil { + isCombineDataDisks = true + continue + } + diskOrderMap[*disk.DiskId] = diskOrderInt + } + } + return nil + }) + if err != nil { + return err + } + } + for _, disk := range instance.DataDisks { + dataDisk := make(map[string]interface{}, 5) + dataDisk["data_disk_id"] = disk.DiskId + if disk.DiskId == nil { + dataDisk["data_disk_size"] = disk.DiskSize + } else if size, ok := diskSizeMap[*disk.DiskId]; ok { + dataDisk["data_disk_size"] = size + } + dataDisk["data_disk_type"] = disk.DiskType + dataDisk["data_disk_snapshot_id"] = disk.SnapshotId + dataDisk["delete_with_instance"] = disk.DeleteWithInstance + dataDisk["encrypt"] = disk.Encrypt + dataDisk["throughput_performance"] = disk.ThroughputPerformance + dataDiskList = append(dataDiskList, dataDisk) + } + if hasDataDisks && !isCombineDataDisks { + sort.SliceStable(dataDiskList, func(idx1, idx2 int) bool { + dataDiskIdIdx1 := *dataDiskList[idx1]["data_disk_id"].(*string) + dataDiskIdIdx2 := *dataDiskList[idx2]["data_disk_id"].(*string) + return diskOrderMap[dataDiskIdIdx1] < diskOrderMap[dataDiskIdIdx2] + }) + } + _ = d.Set("data_disks", dataDiskList) + + if len(instance.PrivateIpAddresses) > 0 { + _ = d.Set("private_ip", instance.PrivateIpAddresses[0]) + } + if len(instance.PublicIpAddresses) > 0 { + _ = d.Set("public_ip", instance.PublicIpAddresses[0]) + } + if len(instance.LoginSettings.KeyIds) > 0 { + _ = d.Set("key_name", instance.LoginSettings.KeyIds[0]) + _ = d.Set("key_ids", instance.LoginSettings.KeyIds) + } else { + _ = d.Set("key_name", "") + _ = d.Set("key_ids", []*string{}) + } + if instance.LoginSettings.KeepImageLogin != nil { + _ = d.Set("keep_image_login", *instance.LoginSettings.KeepImageLogin == CVM_IMAGE_LOGIN) + } + + if *instance.InstanceState == CVM_STATUS_STOPPED { + _ = d.Set("running_flag", false) + } else { + _ = d.Set("running_flag", true) + } + + forceDelete := false + if v, ok := d.GetOkExists("force_delete"); ok { + forceDelete = v.(bool) + _ = d.Set("force_delete", forceDelete) + } + + return nil +} + +func resourceTencentCloudInstanceUpdateOnStart(ctx context.Context) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + instanceId := d.Id() + + d.Partial(true) + + // Get the latest instance info from actual resource. + instanceInfo, err := cvmService.DescribeInstanceById(ctx, instanceId) + if err != nil { + return err + } + + var ( + periodSet = false + renewFlagSet = false + expectChargeType = CVM_CHARGE_TYPE_POSTPAID + currentChargeType = *instanceInfo.InstanceChargeType + ) + + chargeType, chargeOk := d.GetOk("instance_charge_type") + if chargeOk { + expectChargeType = chargeType.(string) + } + + if d.HasChange("instance_charge_type") && expectChargeType != currentChargeType { + var ( + period = -1 + renewFlag string + ) + + if v, ok := d.GetOk("instance_charge_type_prepaid_period"); ok { + period = v.(int) + } + if v, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { + renewFlag = v.(string) + } + // change charge type + err := cvmService.ModifyInstanceChargeType(ctx, instanceId, expectChargeType, period, renewFlag) + if err != nil { + return err + } + // query cvm status + err = waitForOperationFinished(d, meta, 5*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + periodSet = true + renewFlagSet = true + } + + // When instance is prepaid but period was empty and set to 1, skip this case. + op, np := d.GetChange("instance_charge_type_prepaid_period") + if _, ok := op.(int); !ok && np.(int) == 1 { + periodSet = true + } + if d.HasChange("instance_charge_type_prepaid_period") && !periodSet { + chargeType := d.Get("instance_charge_type").(string) + period := d.Get("instance_charge_type_prepaid_period").(int) + renewFlag := "" + + if v, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { + renewFlag = v.(string) + } + err := cvmService.ModifyInstanceChargeType(ctx, instanceId, chargeType, period, renewFlag) + if err != nil { + return err + } + // query cvm status + err = waitForOperationFinished(d, meta, 5*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + renewFlagSet = true + } + + if d.HasChange("instance_charge_type_prepaid_renew_flag") && !renewFlagSet { + //renew api + err := cvmService.ModifyRenewParam(ctx, instanceId, d.Get("instance_charge_type_prepaid_renew_flag").(string)) + if err != nil { + return err + } + + //check success + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + + time.Sleep(tccommon.ReadRetryTimeout) + } + + // Reset Instance + // Keep Login Info + if d.HasChange("image_id") || + d.HasChange("hostname") || + d.HasChange("disable_security_service") || + d.HasChange("disable_monitor_service") || + d.HasChange("keep_image_login") { + + request := cvm.NewResetInstanceRequest() + request.InstanceId = helper.String(d.Id()) + + if v, ok := d.GetOk("image_id"); ok { + request.ImageId = helper.String(v.(string)) + } + if v, ok := d.GetOk("hostname"); ok { + request.HostName = helper.String(v.(string)) + } + + // enhanced service + request.EnhancedService = &cvm.EnhancedService{} + if d.HasChange("disable_security_service") { + v := d.Get("disable_security_service") + securityService := v.(bool) + request.EnhancedService.SecurityService = &cvm.RunSecurityServiceEnabled{ + Enabled: &securityService, + } + } + + if d.HasChange("disable_monitor_service") { + v := d.Get("disable_monitor_service") + monitorService := !(v.(bool)) + request.EnhancedService.MonitorService = &cvm.RunMonitorServiceEnabled{ + Enabled: &monitorService, + } + } + + // Modify or keep login info when instance reset + request.LoginSettings = &cvm.LoginSettings{} + + if v, ok := d.GetOk("password"); ok { + request.LoginSettings.Password = helper.String(v.(string)) + } + + if v, ok := d.GetOk("key_ids"); ok { + request.LoginSettings.KeyIds = helper.InterfacesStringsPoint(v.(*schema.Set).List()) + } else if v, ok := d.GetOk("key_name"); ok { + request.LoginSettings.KeyIds = []*string{helper.String(v.(string))} + } + + if v := d.Get("keep_image_login").(bool); v { + request.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN) + } else { + request.LoginSettings.KeepImageLogin = helper.String(CVM_IMAGE_LOGIN_NOT) + } + + if err := cvmService.ResetInstance(ctx, request); err != nil { + return err + } + + // Modify Login Info Directly + } else { + if d.HasChange("password") { + err := cvmService.ModifyPassword(ctx, instanceId, d.Get("password").(string)) + if err != nil { + return err + } + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + } + + if d.HasChange("key_name") { + o, n := d.GetChange("key_name") + oldKeyId := o.(string) + keyId := n.(string) + + if oldKeyId != "" { + err := cvmService.UnbindKeyPair(ctx, []*string{&oldKeyId}, []*string{&instanceId}) + if err != nil { + return err + } + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + } + + if keyId != "" { + err = cvmService.BindKeyPair(ctx, []*string{&keyId}, instanceId) + if err != nil { + return err + } + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + } + } + + // support remove old `key_name` to `key_ids`, so do not follow "else" + if d.HasChange("key_ids") { + o, n := d.GetChange("key_ids") + ov := o.(*schema.Set) + + nv := n.(*schema.Set) + + adds := nv.Difference(ov) + removes := ov.Difference(nv) + adds.Remove("") + removes.Remove("") + + if removes.Len() > 0 { + err := cvmService.UnbindKeyPair(ctx, helper.InterfacesStringsPoint(removes.List()), []*string{&instanceId}) + if err != nil { + return err + } + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + } + if adds.Len() > 0 { + err = cvmService.BindKeyPair(ctx, helper.InterfacesStringsPoint(adds.List()), instanceId) + if err != nil { + return err + } + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + } + } + } + + if d.HasChange("data_disks") { + o, n := d.GetChange("data_disks") + ov := o.([]interface{}) + nv := n.([]interface{}) + + if len(ov) != len(nv) { + return fmt.Errorf("error: data disk count has changed (%d -> %d) but doesn't support add or remove for now", len(ov), len(nv)) + } + + cbsService := svccbs.NewCbsService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + + for i := range nv { + sizeKey := fmt.Sprintf("data_disks.%d.data_disk_size", i) + idKey := fmt.Sprintf("data_disks.%d.data_disk_id", i) + if !d.HasChange(sizeKey) { + continue + } + size := d.Get(sizeKey).(int) + diskId := d.Get(idKey).(string) + + err := cbsService.ResizeDisk(ctx, diskId, size) + + if err != nil { + return fmt.Errorf("an error occurred when modifying %s, reason: %s", sizeKey, err.Error()) + } + + } + } + + var flag bool + if d.HasChange("running_flag") { + flag = d.Get("running_flag").(bool) + if err := switchInstance(&cvmService, ctx, d, flag); err != nil { + return err + } + + } + + return nil +} + +func waitForOperationFinished(d *schema.ResourceData, meta interface{}, timeout time.Duration, state string, immediately bool) error { + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + cvmService := CvmService{client} + instanceId := d.Id() + // We cannot catch LatestOperationState change immediately after modification returns, we must wait for LatestOperationState update to expected. + if !immediately { + time.Sleep(time.Second * 10) + } + + err := resource.Retry(timeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance == nil { + return resource.NonRetryableError(fmt.Errorf("%s not exists", instanceId)) + } + if instance.LatestOperationState == nil { + return resource.RetryableError(fmt.Errorf("wait for operation update")) + } + if *instance.LatestOperationState == state { + return resource.RetryableError(fmt.Errorf("waiting for instance %s operation", instanceId)) + } + if *instance.LatestOperationState == CVM_LATEST_OPERATION_STATE_FAILED { + return resource.NonRetryableError(fmt.Errorf("failed operation")) + } + return nil + }) + if err != nil { + return err + } + return nil +} + +func switchInstance(cvmService *CvmService, ctx context.Context, d *schema.ResourceData, flag bool) (err error) { + instanceId := d.Id() + if flag { + err = cvmService.StartInstance(ctx, instanceId) + if err != nil { + return err + } + err = resource.Retry(2*tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance != nil && *instance.InstanceState == CVM_STATUS_RUNNING { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + if err != nil { + return err + } + } else { + stoppedMode := d.Get("stopped_mode").(string) + skipStopApi := false + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + // when retry polling instance status, stop instance should skipped + if !skipStopApi { + err := cvmService.StopInstance(ctx, instanceId, stoppedMode) + if err != nil { + return resource.NonRetryableError(err) + } + } + instance, err := cvmService.DescribeInstanceById(ctx, instanceId) + if err != nil { + return resource.NonRetryableError(err) + } + if instance == nil { + return resource.NonRetryableError(fmt.Errorf("instance %s not found", instanceId)) + } + + if instance.LatestOperationState != nil { + operationState := *instance.LatestOperationState + if operationState == "OPERATING" { + skipStopApi = true + return resource.RetryableError(fmt.Errorf("instance %s stop operating, retrying", instanceId)) + } + if operationState == "FAILED" { + skipStopApi = false + return resource.RetryableError(fmt.Errorf("instance %s stop failed, retrying", instanceId)) + } + } + return nil + }) + if err != nil { + return err + } + err = resource.Retry(2*tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance != nil && *instance.InstanceState == CVM_STATUS_STOPPED { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + if err != nil { + return err + } + } + return nil +} + +func resourceTencentCloudInstanceUpdatePreHandleResponse5(ctx context.Context, resp *cvm.ResizeInstanceDisksResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + instanceId := d.Id() + size := d.Get("system_disk_size").(int) + diskType := d.Get("system_disk_type").(string) + + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, err := cvmService.DescribeInstanceById(ctx, instanceId) + if err != nil { + return resource.NonRetryableError(err) + } + if instance != nil && instance.LatestOperationState != nil { + if *instance.InstanceState == "FAILED" { + return resource.NonRetryableError(fmt.Errorf("instance operation failed")) + } + if *instance.InstanceState == "OPERATING" { + return resource.RetryableError(fmt.Errorf("instance operating")) + } + } + if instance != nil && instance.SystemDisk != nil { + //wait until disk result as expected + if *instance.SystemDisk.DiskType != diskType || int(*instance.SystemDisk.DiskSize) != size { + return resource.RetryableError(fmt.Errorf("waiting for expanding success")) + } + } + return nil + }) + if err != nil { + return err + } + + return nil +} + +func resourceTencentCloudInstanceUpdatePreHandleResponse6(ctx context.Context, resp *cvm.ResetInstancesTypeResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + + err := waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + + return nil +} + +func resourceTencentCloudInstanceUpdatePreHandleResponse7(ctx context.Context, resp *cvm.ResetInstancesTypeResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + + err := waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + + return nil +} + +func resourceTencentCloudInstanceUpdatePostFillRequest8(ctx context.Context, req *cvm.ModifyInstancesVpcAttributeRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + + privateIp := d.Get("private_ip").(string) + if privateIp != "" { + req.VirtualPrivateCloud.PrivateIpAddresses = []*string{&privateIp} + } + return nil +} + +func resourceTencentCloudInstanceUpdateOnExit(ctx context.Context) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + instanceId := d.Id() + + if d.HasChange("tags") { + oldInterface, newInterface := d.GetChange("tags") + replaceTags, deleteTags := svctag.DiffTags(oldInterface.(map[string]interface{}), newInterface.(map[string]interface{})) + tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region + resourceName := tccommon.BuildTagResourceName("cvm", "instance", region, instanceId) + err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) + if err != nil { + return err + } + //except instance ,system disk and data disk will be tagged + //keep logical consistence with the console + //tag system disk + if systemDiskId, ok := d.GetOk("system_disk_id"); ok { + if systemDiskId.(string) != "" { + resourceName = tccommon.BuildTagResourceName("cvm", "volume", region, systemDiskId.(string)) + if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil { + return err + } + } + } + //tag disk ids + if dataDisks, ok := d.GetOk("data_disks"); ok { + dataDiskList := dataDisks.([]interface{}) + for _, dataDisk := range dataDiskList { + disk := dataDisk.(map[string]interface{}) + dataDiskId := disk["data_disk_id"].(string) + resourceName = tccommon.BuildTagResourceName("cvm", "volume", region, dataDiskId) + if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil { + return err + } + } + } + + } + + if d.HasChange("internet_max_bandwidth_out") { + chargeType := d.Get("internet_charge_type").(string) + bandWidthOut := int64(d.Get("internet_max_bandwidth_out").(int)) + if chargeType != "TRAFFIC_POSTPAID_BY_HOUR" && chargeType != "BANDWIDTH_POSTPAID_BY_HOUR" && chargeType != "BANDWIDTH_PACKAGE" { + return fmt.Errorf("charge type should be one of `TRAFFIC_POSTPAID_BY_HOUR BANDWIDTH_POSTPAID_BY_HOUR BANDWIDTH_PACKAGE` when adjusting internet_max_bandwidth_out") + } + + err := cvmService.ModifyInternetMaxBandwidthOut(ctx, instanceId, chargeType, bandWidthOut) + if err != nil { + return err + } + + err = waitForOperationFinished(d, meta, 2*tccommon.ReadRetryTimeout, CVM_LATEST_OPERATION_STATE_OPERATING, false) + if err != nil { + return err + } + + } + + d.Partial(false) + + return nil +} + +func resourceTencentCloudInstanceDeletePostFillRequest0(ctx context.Context, req *cvm.TerminateInstancesRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + instanceId := d.Id() + + _, err := cvmService.DescribeInstanceById(ctx, instanceId) + if err != nil { + return err + } + + return nil +} + +func resourceTencentCloudInstanceDeletePreHandleResponse0(ctx context.Context, resp *cvm.TerminateInstancesResponse) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + logId := ctx.Value(tccommon.LogIdKey) + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + instanceId := d.Id() + + //check is force delete or not + forceDelete := d.Get("force_delete").(bool) + + //check recycling + notExist := false + + var instance *cvm.Instance + //check exist + err := resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance == nil { + notExist = true + return nil + } + if *instance.InstanceState == CVM_STATUS_SHUTDOWN && *instance.LatestOperationState != CVM_LATEST_OPERATION_STATE_OPERATING { + //in recycling + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + if err != nil { + return err + } + + vpcService := vpc.NewVpcService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + + if notExist { + err := waitIpRelease(ctx, vpcService, instance) + if err != nil { + return err + } + return nil + } + + if !forceDelete { + return nil + } + + // exist in recycle, delete again + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + errRet := cvmService.DeleteInstance(ctx, instanceId) + //when state is terminating, do not delete but check exist + if errRet != nil { + //check InvalidInstanceState.Terminating + ee, ok := errRet.(*sdkErrors.TencentCloudSDKError) + if !ok { + return tccommon.RetryError(errRet) + } + if ee.Code == "InvalidInstanceState.Terminating" { + return nil + } + return tccommon.RetryError(errRet, "OperationDenied.InstanceOperationInProgress") + } + return nil + }) + if err != nil { + return err + } + + //describe and check not exist + err = resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if instance == nil { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + if err != nil { + return err + } + if v, ok := d.GetOk("data_disks"); ok { + dataDisks := v.([]interface{}) + for _, d := range dataDisks { + value := d.(map[string]interface{}) + diskId := value["data_disk_id"].(string) + deleteWithInstance := value["delete_with_instance"].(bool) + if deleteWithInstance { + cbsService := svccbs.NewCbsService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + err := resource.Retry(tccommon.ReadRetryTimeout*2, func() *resource.RetryError { + diskInfo, e := cbsService.DescribeDiskById(ctx, diskId) + if e != nil { + return tccommon.RetryError(e, tccommon.InternalError) + } + if *diskInfo.DiskState != svccbs.CBS_STORAGE_STATUS_UNATTACHED { + return resource.RetryableError(fmt.Errorf("cbs storage status is %s", *diskInfo.DiskState)) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s delete cbs failed, reason:%s\n ", logId, err.Error()) + return err + } + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + e := cbsService.DeleteDiskById(ctx, diskId) + if e != nil { + return tccommon.RetryError(e, tccommon.InternalError) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s delete cbs failed, reason:%s\n ", logId, err.Error()) + return err + } + err = resource.Retry(tccommon.ReadRetryTimeout*2, func() *resource.RetryError { + diskInfo, e := cbsService.DescribeDiskById(ctx, diskId) + if e != nil { + return tccommon.RetryError(e, tccommon.InternalError) + } + if *diskInfo.DiskState == svccbs.CBS_STORAGE_STATUS_TORECYCLE { + return resource.RetryableError(fmt.Errorf("cbs storage status is %s", *diskInfo.DiskState)) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s read cbs status failed, reason:%s\n ", logId, err.Error()) + return err + } + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + e := cbsService.DeleteDiskById(ctx, diskId) + if e != nil { + return tccommon.RetryError(e, tccommon.InternalError) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s delete cbs failed, reason:%s\n ", logId, err.Error()) + return err + } + err = resource.Retry(tccommon.ReadRetryTimeout*2, func() *resource.RetryError { + diskInfo, e := cbsService.DescribeDiskById(ctx, diskId) + if e != nil { + return tccommon.RetryError(e, tccommon.InternalError) + } + if diskInfo != nil { + return resource.RetryableError(fmt.Errorf("cbs storage status is %s", *diskInfo.DiskState)) + } + return nil + }) + if err != nil { + log.Printf("[CRITAL]%s read cbs status failed, reason:%s\n ", logId, err.Error()) + return err + } + } + } + } + + err = waitIpRelease(ctx, vpcService, instance) + if err != nil { + return err + } + + return nil +} + +func waitIpRelease(ctx context.Context, vpcService vpc.VpcService, instance *cvm.Instance) error { + // wait ip release + if instance != nil && len(instance.PrivateIpAddresses) > 0 { + params := make(map[string]interface{}) + params["VpcId"] = instance.VirtualPrivateCloud.VpcId + params["SubnetId"] = instance.VirtualPrivateCloud.SubnetId + params["IpAddresses"] = instance.PrivateIpAddresses + err := resource.Retry(5*tccommon.ReadRetryTimeout, func() *resource.RetryError { + usedIpAddress, errRet := vpcService.DescribeVpcUsedIpAddressByFilter(ctx, params) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + if len(usedIpAddress) > 0 { + return resource.RetryableError(fmt.Errorf("wait cvm private ip release...")) + } + + return nil + }) + if err != nil { + return err + } + } + return nil +} diff --git a/tencentcloud/services/cvm/resource_tc_instance_test.go b/tencentcloud/services/cvm/resource_tc_instance_test.go index 88293dd10f..4c629c37f0 100644 --- a/tencentcloud/services/cvm/resource_tc_instance_test.go +++ b/tencentcloud/services/cvm/resource_tc_instance_test.go @@ -1595,7 +1595,7 @@ data "tencentcloud_instance_types" "default" { filter { name = "instance-family" - values = ["S1"] + values = ["S5"] } cpu_core_count = 2 memory_size = 2 @@ -1623,7 +1623,7 @@ data "tencentcloud_instance_types" "default" { filter { name = "instance-family" - values = ["S1"] + values = ["S5"] } cpu_core_count = 2 memory_size = 2 @@ -1893,7 +1893,7 @@ const testAccTencentCloudInstancePostPaid = ` data "tencentcloud_instance_types" "default" { filter { name = "instance-family" - values = ["S1"] + values = ["S5"] } cpu_core_count = 2 @@ -1917,7 +1917,7 @@ const testAccTencentCloudInstanceBasicToPrepaid = ` data "tencentcloud_instance_types" "default" { filter { name = "instance-family" - values = ["S1"] + values = ["S5"] } cpu_core_count = 2 diff --git a/tencentcloud/services/cvm/resource_tc_key_pair.go b/tencentcloud/services/cvm/resource_tc_key_pair.go index c768504a77..a421adbc86 100644 --- a/tencentcloud/services/cvm/resource_tc_key_pair.go +++ b/tencentcloud/services/cvm/resource_tc_key_pair.go @@ -1,20 +1,18 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" "fmt" "log" - "strings" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" - svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" - - "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + svctag "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/services/tag" ) func ResourceTencentCloudKeyPair() *schema.Resource { @@ -26,142 +24,67 @@ func ResourceTencentCloudKeyPair() *schema.Resource { Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - Schema: map[string]*schema.Schema{ "key_name": { Type: schema.TypeString, Required: true, - ValidateFunc: tccommon.ValidateKeyPairName, Description: "The key pair's name. It is the only in one TencentCloud account.", + ValidateFunc: tccommon.ValidateKeyPairName, }, + "public_key": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - StateFunc: func(v interface{}) string { - switch value := v.(type) { - case string: - publicKey := value - split := strings.Split(value, " ") - if len(split) > 2 { - publicKey = strings.Join(split[0:2], " ") - } - return strings.TrimSpace(publicKey) - default: - return "" - } - }, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, Description: "You can import an existing public key and using TencentCloud key pair to manage it.", + StateFunc: publicKeyStateFunc, }, + "project_id": { Type: schema.TypeInt, Optional: true, - Default: 0, ForceNew: true, + Default: 0, Description: "Specifys to which project the key pair belongs.", }, + "tags": { Type: schema.TypeMap, Optional: true, - Description: "Tags of the key pair.", + Description: "Tag description list.", }, }, } } -func cvmCreateKeyPair(ctx context.Context, d *schema.ResourceData, meta interface{}) (keyId string, err error) { - logId := tccommon.GetLogId(ctx) - request := cvm.NewCreateKeyPairRequest() - response := cvm.NewCreateKeyPairResponse() - request.KeyName = helper.String(d.Get("key_name").(string)) - request.ProjectId = helper.IntInt64(d.Get("project_id").(int)) - - innerErr := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateKeyPair(request) - if e != nil { - return tccommon.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 innerErr != nil { - log.Printf("[CRITAL]%s create cvm keyPair by import failed, reason:%+v", logId, err) - err = innerErr - return - } - if response == nil || response.Response == nil || response.Response.KeyPair == nil { - err = fmt.Errorf("Response is nil") - return - } - - keyId = *response.Response.KeyPair.KeyId - return -} - -func cvmCreateKeyPairByImportPublicKey(ctx context.Context, d *schema.ResourceData, meta interface{}) (keyId string, err error) { - logId := tccommon.GetLogId(ctx) - request := cvm.NewImportKeyPairRequest() - response := cvm.NewImportKeyPairResponse() - request.KeyName = helper.String(d.Get("key_name").(string)) - request.ProjectId = helper.IntInt64(d.Get("project_id").(int)) - request.PublicKey = helper.String(d.Get("public_key").(string)) - - innerErr := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ImportKeyPair(request) - if e != nil { - return tccommon.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 innerErr != nil { - log.Printf("[CRITAL]%s create cvm keyPair by import failed, reason:%+v", logId, err) - err = innerErr - return - } - if response == nil || response.Response == nil { - err = fmt.Errorf("Response is nil") - return - } - - keyId = *response.Response.KeyId - return -} - func resourceTencentCloudKeyPairCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_key_pair.create")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + var ( keyId string - err error ) + d.SetId(keyId) - if _, ok := d.GetOk("public_key"); ok { - keyId, err = cvmCreateKeyPairByImportPublicKey(ctx, d, meta) - } else { - keyId, err = cvmCreateKeyPair(ctx, d, meta) - } - if err != nil { + if err := resourceTencentCloudKeyPairCreateOnExit(ctx); err != nil { return err } - d.SetId(keyId) if tags := helper.GetTags(d, "tags"); len(tags) > 0 { - tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - tagService := svctag.NewTagService(tcClient) - resourceName := tccommon.BuildTagResourceName("cvm", "keypair", tcClient.Region, keyId) + tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) + region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region + resourceName := fmt.Sprintf("qcs::cvm:%s:uin/:keypair/%s", region, d.Id()) if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil { return err } } + _ = ctx return resourceTencentCloudKeyPairRead(d, meta) } @@ -170,44 +93,38 @@ func resourceTencentCloudKeyPairRead(d *schema.ResourceData, meta interface{}) e defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} keyId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - var keyPair *cvm.KeyPair - var errRet error - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - keyPair, errRet = cvmService.DescribeKeyPairById(ctx, keyId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - return nil - }) + + respData, err := service.DescribeKeyPairById(ctx, keyId) if err != nil { return err } - if keyPair == nil { + + if respData == nil { d.SetId("") + log.Printf("[WARN]%s resource `key_pair` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } + if respData.KeyName != nil { + _ = d.Set("key_name", respData.KeyName) + } - _ = d.Set("key_name", keyPair.KeyName) - _ = d.Set("project_id", keyPair.ProjectId) - if keyPair.PublicKey != nil { - publicKey := *keyPair.PublicKey - split := strings.Split(publicKey, " ") - if len(split) > 2 { - publicKey = strings.Join(split[0:2], " ") - } - _ = d.Set("public_key", publicKey) + if respData.ProjectId != nil { + _ = d.Set("project_id", respData.ProjectId) } - client := meta.(tccommon.ProviderMeta).GetAPIV3Conn() - tagService := svctag.NewTagService(client) + if err := resourceTencentCloudKeyPairReadPostHandleResponse0(ctx, respData); err != nil { + return err + } - tags, err := tagService.DescribeResourceTags(ctx, "cvm", "keypair", client.Region, d.Id()) + tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + tagService := svctag.NewTagService(tcClient) + tags, err := tagService.DescribeResourceTags(ctx, "cvm", "keypair", tcClient.Region, d.Id()) if err != nil { return err } @@ -218,31 +135,55 @@ func resourceTencentCloudKeyPairRead(d *schema.ResourceData, meta interface{}) e func resourceTencentCloudKeyPairUpdate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_key_pair.update")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) keyId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + + needChange := false + mutableArgs := []string{"key_name"} + for _, v := range mutableArgs { + if d.HasChange(v) { + needChange = true + break + } } - if d.HasChange("key_name") { - keyName := d.Get("key_name").(string) - err := cvmService.ModifyKeyPairName(ctx, keyId, keyName) + if needChange { + request := cvm.NewModifyKeyPairAttributeRequest() + + request.KeyId = helper.String(keyId) + + if v, ok := d.GetOk("key_name"); ok { + request.KeyName = helper.String(v.(string)) + } + + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyKeyPairAttributeWithContext(ctx, request) + if e != nil { + return tccommon.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 update key pair failed, reason:%+v", logId, err) return err } } if d.HasChange("tags") { - oldInterface, newInterface := d.GetChange("tags") - replaceTags, deleteTags := svctag.DiffTags(oldInterface.(map[string]interface{}), newInterface.(map[string]interface{})) - tagService := svctag.NewTagService(meta.(tccommon.ProviderMeta).GetAPIV3Conn()) - region := meta.(tccommon.ProviderMeta).GetAPIV3Conn().Region - resourceName := tccommon.BuildTagResourceName("cvm", "keypair", region, keyId) - err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) - if err != nil { + ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + tcClient := meta.(tccommon.ProviderMeta).GetAPIV3Conn() + tagService := svctag.NewTagService(tcClient) + oldTags, newTags := d.GetChange("tags") + replaceTags, deleteTags := svctag.DiffTags(oldTags.(map[string]interface{}), newTags.(map[string]interface{})) + resourceName := tccommon.BuildTagResourceName("cvm", "keypair", tcClient.Region, d.Id()) + if err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags); err != nil { return err } } @@ -252,60 +193,42 @@ func resourceTencentCloudKeyPairUpdate(d *schema.ResourceData, meta interface{}) func resourceTencentCloudKeyPairDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_key_pair.delete")() + defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) keyId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - var keyPair *cvm.KeyPair - var errRet error - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - keyPair, errRet = cvmService.DescribeKeyPairById(ctx, keyId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - return nil - }) - if err != nil { + var ( + request = cvm.NewDeleteKeyPairsRequest() + response = cvm.NewDeleteKeyPairsResponse() + ) + + request.KeyIds = []*string{helper.String(keyId)} + + if err := resourceTencentCloudKeyPairDeletePostFillRequest0(ctx, request); err != nil { return err } - if keyPair == nil { - d.SetId("") - return nil - } - if len(keyPair.AssociatedInstanceIds) > 0 { - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := cvmService.UnbindKeyPair(ctx, []*string{&keyId}, keyPair.AssociatedInstanceIds) - if errRet != nil { - if sdkErr, ok := errRet.(*errors.TencentCloudSDKError); ok { - if sdkErr.Code == CVM_NOT_FOUND_ERROR { - return nil - } - } - return tccommon.RetryError(errRet) + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DeleteKeyPairsWithContext(ctx, request) + if e != nil { + if err := resourceTencentCloudKeyPairDeleteRequestOnError0(ctx, e); err != nil { + return err } - return nil - }) - if err != nil { - return err - } - } - - err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - errRet := cvmService.DeleteKeyPair(ctx, keyId) - if errRet != nil { - return tccommon.RetryError(errRet, KYE_PAIR_INVALID_ERROR, KEY_PAIR_NOT_SUPPORT_ERROR) + return tccommon.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 delete key pair failed, reason:%+v", logId, err) return err } + _ = response return nil } diff --git a/tencentcloud/services/cvm/resource_tc_key_pair_extension.go b/tencentcloud/services/cvm/resource_tc_key_pair_extension.go new file mode 100644 index 0000000000..86dd46c4f9 --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_key_pair_extension.go @@ -0,0 +1,179 @@ +package cvm + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + + cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" +) + +func resourceTencentCloudKeyPairReadPostHandleResponse0(ctx context.Context, resp *cvm.KeyPair) error { + d := tccommon.ResourceDataFromContext(ctx) + + if resp.PublicKey != nil { + publicKey := *resp.PublicKey + split := strings.Split(publicKey, " ") + if len(split) > 2 { + publicKey = strings.Join(split[0:2], " ") + } + _ = d.Set("public_key", publicKey) + } + return nil +} + +func resourceTencentCloudKeyPairDeletePostFillRequest0(ctx context.Context, req *cvm.DeleteKeyPairsRequest) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + cvmService := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + keyId := d.Id() + + var keyPair *cvm.KeyPair + var errRet error + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + keyPair, errRet = cvmService.DescribeKeyPairById(ctx, keyId) + if errRet != nil { + return tccommon.RetryError(errRet, tccommon.InternalError) + } + return nil + }) + if err != nil { + return err + } + if keyPair == nil { + d.SetId("") + return nil + } + + if len(keyPair.AssociatedInstanceIds) > 0 { + err = resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + errRet := cvmService.UnbindKeyPair(ctx, []*string{&keyId}, keyPair.AssociatedInstanceIds) + if errRet != nil { + if sdkErr, ok := errRet.(*errors.TencentCloudSDKError); ok { + if sdkErr.Code == CVM_NOT_FOUND_ERROR { + return nil + } + } + return tccommon.RetryError(errRet) + } + return nil + }) + if err != nil { + return err + } + } + + return nil +} + +func publicKeyStateFunc(v interface{}) string { + switch value := v.(type) { + case string: + publicKey := value + split := strings.Split(value, " ") + if len(split) > 2 { + publicKey = strings.Join(split[0:2], " ") + } + return strings.TrimSpace(publicKey) + default: + return "" + } +} + +func resourceTencentCloudKeyPairDeleteRequestOnError0(ctx context.Context, e error) *resource.RetryError { + return tccommon.RetryError(e, KYE_PAIR_INVALID_ERROR, KEY_PAIR_NOT_SUPPORT_ERROR) +} + +func resourceTencentCloudKeyPairCreateOnExit(ctx context.Context) error { + d := tccommon.ResourceDataFromContext(ctx) + meta := tccommon.ProviderMetaFromContext(ctx) + + var ( + keyId string + err error + ) + if _, ok := d.GetOk("public_key"); ok { + keyId, err = cvmCreateKeyPairByImportPublicKey(ctx, d, meta) + } else { + keyId, err = cvmCreateKeyPair(ctx, d, meta) + } + if err != nil { + return err + } + d.SetId(keyId) + return nil +} + +func cvmCreateKeyPair(ctx context.Context, d *schema.ResourceData, meta interface{}) (keyId string, err error) { + logId := tccommon.GetLogId(ctx) + request := cvm.NewCreateKeyPairRequest() + response := cvm.NewCreateKeyPairResponse() + request.KeyName = helper.String(d.Get("key_name").(string)) + request.ProjectId = helper.IntInt64(d.Get("project_id").(int)) + + innerErr := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateKeyPair(request) + if e != nil { + return tccommon.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 innerErr != nil { + log.Printf("[CRITAL]%s create cvm keyPair by import failed, reason:%+v", logId, err) + err = innerErr + return + } + if response == nil || response.Response == nil || response.Response.KeyPair == nil { + err = fmt.Errorf("Response is nil") + return + } + + keyId = *response.Response.KeyPair.KeyId + return +} + +func cvmCreateKeyPairByImportPublicKey(ctx context.Context, d *schema.ResourceData, meta interface{}) (keyId string, err error) { + logId := tccommon.GetLogId(ctx) + request := cvm.NewImportKeyPairRequest() + response := cvm.NewImportKeyPairResponse() + request.KeyName = helper.String(d.Get("key_name").(string)) + request.ProjectId = helper.IntInt64(d.Get("project_id").(int)) + request.PublicKey = helper.String(d.Get("public_key").(string)) + + innerErr := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ImportKeyPair(request) + if e != nil { + return tccommon.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 innerErr != nil { + log.Printf("[CRITAL]%s create cvm keyPair by import failed, reason:%+v", logId, err) + err = innerErr + return + } + if response == nil || response.Response == nil { + err = fmt.Errorf("Response is nil") + return + } + + keyId = *response.Response.KeyId + return +} diff --git a/tencentcloud/services/cvm/resource_tc_placement_group.go b/tencentcloud/services/cvm/resource_tc_placement_group.go index 25fac68fbf..f30ba5235d 100644 --- a/tencentcloud/services/cvm/resource_tc_placement_group.go +++ b/tencentcloud/services/cvm/resource_tc_placement_group.go @@ -1,13 +1,16 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "log" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) func ResourceTencentCloudPlacementGroup() *schema.Resource { @@ -19,33 +22,34 @@ func ResourceTencentCloudPlacementGroup() *schema.Resource { Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, Required: true, - ValidateFunc: tccommon.ValidateStringLengthInRange(1, 60), Description: "Name of the placement group, 1-60 characters in length.", + ValidateFunc: tccommon.ValidateStringLengthInRange(1, 60), }, + "type": { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_PLACEMENT_GROUP_TYPE), Description: "Type of the placement group. Valid values: `HOST`, `SW` and `RACK`.", + ValidateFunc: tccommon.ValidateAllowedStringValue(CVM_PLACEMENT_GROUP_TYPE), }, - // computed "cvm_quota_total": { Type: schema.TypeInt, Computed: true, Description: "Maximum number of hosts in the placement group.", }, + "current_num": { Type: schema.TypeInt, Computed: true, Description: "Number of hosts in the placement group.", }, + "create_time": { Type: schema.TypeString, Computed: true, @@ -57,27 +61,46 @@ func ResourceTencentCloudPlacementGroup() *schema.Resource { func resourceTencentCloudPlacementGroupCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_placement_group.create")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + var ( + disasterRecoverGroupId string + ) + var ( + request = cvm.NewCreateDisasterRecoverGroupRequest() + response = cvm.NewCreateDisasterRecoverGroupResponse() + ) + + if v, ok := d.GetOk("name"); ok { + request.Name = helper.String(v.(string)) + } + + if v, ok := d.GetOk("type"); ok { + request.Type = helper.String(v.(string)) } - placementName := d.Get("name").(string) - placementType := d.Get("type").(string) - var id string - var errRet error + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - id, errRet = cvmService.CreatePlacementGroup(ctx, placementName, placementType) - if errRet != nil { - return tccommon.RetryError(errRet) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().CreateDisasterRecoverGroupWithContext(ctx, request) + if e != nil { + return tccommon.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 placement group failed, reason:%+v", logId, err) return err } - d.SetId(id) + + disasterRecoverGroupId = *response.Response.DisasterRecoverGroupId + + d.SetId(disasterRecoverGroupId) return resourceTencentCloudPlacementGroupRead(d, meta) } @@ -87,57 +110,85 @@ func resourceTencentCloudPlacementGroupRead(d *schema.ResourceData, meta interfa defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - placementId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - var placement *cvm.DisasterRecoverGroup - var errRet error - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - placement, errRet = cvmService.DescribePlacementGroupById(ctx, placementId) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - return nil - }) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + disasterRecoverGroupId := d.Id() + + respData, err := service.DescribePlacementGroupById(ctx, disasterRecoverGroupId) if err != nil { return err } - if placement == nil { + + if respData == nil { d.SetId("") + log.Printf("[WARN]%s resource `placement_group` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } + if respData.Name != nil { + _ = d.Set("name", respData.Name) + } + + if respData.Type != nil { + _ = d.Set("type", respData.Type) + } + + if respData.CvmQuotaTotal != nil { + _ = d.Set("cvm_quota_total", respData.CvmQuotaTotal) + } - _ = d.Set("name", placement.Name) - _ = d.Set("type", placement.Type) - _ = d.Set("cvm_quota_total", placement.CvmQuotaTotal) - _ = d.Set("current_num", placement.CurrentNum) - _ = d.Set("create_time", placement.CreateTime) + if respData.CurrentNum != nil { + _ = d.Set("current_num", respData.CurrentNum) + } + + if respData.CreateTime != nil { + _ = d.Set("create_time", respData.CreateTime) + } return nil } func resourceTencentCloudPlacementGroupUpdate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_placement_group.update")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - placementId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + disasterRecoverGroupId := d.Id() + + needChange := false + mutableArgs := []string{"name"} + for _, v := range mutableArgs { + if d.HasChange(v) { + needChange = true + break + } } - if d.HasChange("name") { - placementName := d.Get("name").(string) + + if needChange { + request := cvm.NewModifyDisasterRecoverGroupAttributeRequest() + + request.DisasterRecoverGroupId = helper.String(disasterRecoverGroupId) + + if v, ok := d.GetOk("name"); ok { + request.Name = helper.String(v.(string)) + } + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - err := cvmService.ModifyPlacementGroup(ctx, placementId, placementName) - if err != nil { - return tccommon.RetryError(err) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().ModifyDisasterRecoverGroupAttributeWithContext(ctx, request) + if e != nil { + return tccommon.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 update placement group failed, reason:%+v", logId, err) return err } } @@ -147,23 +198,35 @@ func resourceTencentCloudPlacementGroupUpdate(d *schema.ResourceData, meta inter func resourceTencentCloudPlacementGroupDelete(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_placement_group.delete")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + disasterRecoverGroupId := d.Id() + + var ( + request = cvm.NewDeleteDisasterRecoverGroupsRequest() + response = cvm.NewDeleteDisasterRecoverGroupsResponse() + ) + + request.DisasterRecoverGroupIds = []*string{helper.String(disasterRecoverGroupId)} - placementId := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - err := cvmService.DeletePlacementGroup(ctx, placementId) - if err != nil { - return tccommon.RetryError(err) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().DeleteDisasterRecoverGroupsWithContext(ctx, request) + if e != nil { + return tccommon.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 delete placement group failed, reason:%+v", logId, err) return err } + _ = response return nil } diff --git a/tencentcloud/services/cvm/resource_tc_placement_group_extension.go b/tencentcloud/services/cvm/resource_tc_placement_group_extension.go new file mode 100644 index 0000000000..b417cc5d9f --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_placement_group_extension.go @@ -0,0 +1 @@ +package cvm diff --git a/tencentcloud/services/cvm/resource_tc_reserved_instance.go b/tencentcloud/services/cvm/resource_tc_reserved_instance.go index 9b18443082..e3a9917f90 100644 --- a/tencentcloud/services/cvm/resource_tc_reserved_instance.go +++ b/tencentcloud/services/cvm/resource_tc_reserved_instance.go @@ -1,14 +1,16 @@ +// Code generated by iacg; DO NOT EDIT. package cvm import ( "context" - "fmt" - - tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "log" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" ) func ResourceTencentCloudReservedInstance() *schema.Resource { @@ -20,38 +22,38 @@ func ResourceTencentCloudReservedInstance() *schema.Resource { Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, - Schema: map[string]*schema.Schema{ "config_id": { Type: schema.TypeString, Required: true, Description: "Configuration ID of the reserved instance.", }, + "instance_count": { Type: schema.TypeInt, Required: true, - ValidateFunc: tccommon.ValidateIntegerMin(1), Description: "Number of reserved instances to be purchased.", + ValidateFunc: tccommon.ValidateIntegerMin(1), }, + "reserved_instance_name": { - Type: schema.TypeString, - Optional: true, - Description: `Reserved Instance display name. - - If you do not specify an instance display name, 'Unnamed' is displayed by default. - - Up to 60 characters (including pattern strings) are supported.`, + Type: schema.TypeString, + Optional: true, + Description: "Reserved Instance display name.\n\t\t\t\t- If you do not specify an instance display name, 'Unnamed' is displayed by default.\n\t\t\t\t- Up to 60 characters (including pattern strings) are supported.", }, - // computed "start_time": { Type: schema.TypeString, Computed: true, Description: "Start time of the RI.", }, + "end_time": { Type: schema.TypeString, Computed: true, Description: "Expiry time of the RI.", }, + "status": { Type: schema.TypeString, Computed: true, @@ -63,31 +65,50 @@ func ResourceTencentCloudReservedInstance() *schema.Resource { func resourceTencentCloudReservedInstanceCreate(d *schema.ResourceData, meta interface{}) error { defer tccommon.LogElapsed("resource.tencentcloud_reserved_instance.create")() + defer tccommon.InconsistentCheck(d, meta)() + logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - configId := d.Get("config_id").(string) - count := d.Get("instance_count").(int) - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + var ( + reservedInstanceId string + ) + var ( + request = cvm.NewPurchaseReservedInstancesOfferingRequest() + response = cvm.NewPurchaseReservedInstancesOfferingResponse() + ) + + if v, ok := d.GetOk("config_id"); ok { + request.ReservedInstancesOfferingId = helper.String(v.(string)) + } + + if v, ok := d.GetOkExists("instance_count"); ok { + request.InstanceCount = helper.IntInt64(v.(int)) } - extendParams := make(map[string]interface{}) + if v, ok := d.GetOk("reserved_instance_name"); ok { - extendParams["reserved_instance_name"] = v.(string) + request.ReservedInstanceName = helper.String(v.(string)) } - var instanceId string - var errRet error + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { - instanceId, errRet = cvmService.CreateReservedInstance(ctx, configId, int64(count), extendParams) - if errRet != nil { - return tccommon.RetryError(errRet) + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseCvmClient().PurchaseReservedInstancesOfferingWithContext(ctx, request) + if e != nil { + return tccommon.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 reserved instance failed, reason:%+v", logId, err) return err } - d.SetId(instanceId) + + reservedInstanceId = *response.Response.ReservedInstanceId + + d.SetId(reservedInstanceId) return resourceTencentCloudReservedInstanceRead(d, meta) } @@ -97,46 +118,74 @@ func resourceTencentCloudReservedInstanceRead(d *schema.ResourceData, meta inter defer tccommon.InconsistentCheck(d, meta)() logId := tccommon.GetLogId(tccommon.ContextNil) - ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId) - id := d.Id() - cvmService := CvmService{ - client: meta.(tccommon.ProviderMeta).GetAPIV3Conn(), - } - filter := map[string]string{ - "reserved-instances-id": id, - } - var instances []*cvm.ReservedInstances - var errRet error - err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { - instances, errRet = cvmService.DescribeReservedInstanceByFilter(ctx, filter) - if errRet != nil { - return tccommon.RetryError(errRet, tccommon.InternalError) - } - return nil - }) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := CvmService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + reservedInstanceId := d.Id() + + respData, err := service.DescribeReservedInstanceById(ctx, reservedInstanceId) if err != nil { return err } - if len(instances) < 1 { + + if respData == nil { d.SetId("") + log.Printf("[WARN]%s resource `reserved_instance` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) return nil } - instance := instances[0] + if respData.InstanceCount != nil { + _ = d.Set("instance_count", respData.InstanceCount) + } + + if respData.StartTime != nil { + _ = d.Set("start_time", respData.StartTime) + } - _ = d.Set("instance_count", instance.InstanceCount) - _ = d.Set("start_time", instance.StartTime) - _ = d.Set("end_time", instance.EndTime) - _ = d.Set("status", instance.State) - _ = d.Set("reserved_instance_name", instance.ReservedInstanceName) + if respData.EndTime != nil { + _ = d.Set("end_time", respData.EndTime) + } + + if respData.State != nil { + _ = d.Set("status", respData.State) + } + + if respData.ReservedInstanceName != nil { + _ = d.Set("reserved_instance_name", respData.ReservedInstanceName) + } return nil } func resourceTencentCloudReservedInstanceUpdate(d *schema.ResourceData, meta interface{}) error { - return fmt.Errorf("reserved instance not allowed to modify") + defer tccommon.LogElapsed("resource.tencentcloud_reserved_instance.update")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + reservedInstanceId := d.Id() + + if err := resourceTencentCloudReservedInstanceUpdateOnStart(ctx); err != nil { + return err + } + + _ = reservedInstanceId + return resourceTencentCloudReservedInstanceRead(d, meta) } func resourceTencentCloudReservedInstanceDelete(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("resource.tencentcloud_reserved_instance.delete")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(tccommon.ContextNil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + reservedInstanceId := d.Id() + + _ = reservedInstanceId + _ = ctx return nil } diff --git a/tencentcloud/services/cvm/resource_tc_reserved_instance_extension.go b/tencentcloud/services/cvm/resource_tc_reserved_instance_extension.go new file mode 100644 index 0000000000..d8b9df735f --- /dev/null +++ b/tencentcloud/services/cvm/resource_tc_reserved_instance_extension.go @@ -0,0 +1,10 @@ +package cvm + +import ( + "context" + "fmt" +) + +func resourceTencentCloudReservedInstanceUpdateOnStart(ctx context.Context) error { + return fmt.Errorf("reserved instance not allowed to modify") +} diff --git a/tencentcloud/services/cvm/resource_tc_reserved_instance_test.go b/tencentcloud/services/cvm/resource_tc_reserved_instance_test.go index cd10e3a45a..c5a281f64d 100644 --- a/tencentcloud/services/cvm/resource_tc_reserved_instance_test.go +++ b/tencentcloud/services/cvm/resource_tc_reserved_instance_test.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) -func TestAccTencentCloudReservedInstance(t *testing.T) { +func TestAccTencentCloudNeedFixReservedInstance(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ PreCheck: func() { tcacctest.AccPreCheck(t) }, diff --git a/tencentcloud/services/cvm/tencentcloud_sweeper_test.go b/tencentcloud/services/cvm/resource_test.go similarity index 100% rename from tencentcloud/services/cvm/tencentcloud_sweeper_test.go rename to tencentcloud/services/cvm/resource_test.go diff --git a/tencentcloud/services/cvm/service_tencentcloud_cvm.go b/tencentcloud/services/cvm/service_tencentcloud_cvm.go index 071d5d8f1f..15b1170ded 100644 --- a/tencentcloud/services/cvm/service_tencentcloud_cvm.go +++ b/tencentcloud/services/cvm/service_tencentcloud_cvm.go @@ -64,28 +64,32 @@ func (me *CvmService) DescribeInstanceSetByIds(ctx context.Context, instanceSetI return } -func (me *CvmService) DescribeInstanceById(ctx context.Context, instanceId string) (instance *cvm.Instance, errRet error) { +func (me *CvmService) DescribeInstanceById(ctx context.Context, instanceId string) (ret *cvm.Instance, errRet error) { logId := tccommon.GetLogId(ctx) + request := cvm.NewDescribeInstancesRequest() - request.InstanceIds = []*string{&instanceId} + request.InstanceIds = []*string{helper.String(instanceId)} + + 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 iacExtInfo connectivity.IacExtInfo - iacExtInfo.InstanceId = instanceId ratelimit.Check(request.GetAction()) - response, err := me.client.UseCvmClient(iacExtInfo).DescribeInstances(request) + + 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()) + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) if len(response.Response.InstanceSet) < 1 { return } - instance = response.Response.InstanceSet[0] + + ret = response.Response.InstanceSet[0] return } @@ -572,25 +576,32 @@ func (me *CvmService) DescribeInstancesSellTypeByFilter(ctx context.Context, fil return } -func (me *CvmService) DescribeKeyPairById(ctx context.Context, keyId string) (keyPair *cvm.KeyPair, errRet error) { +func (me *CvmService) DescribeKeyPairById(ctx context.Context, keyId string) (ret *cvm.KeyPair, errRet error) { logId := tccommon.GetLogId(ctx) + request := cvm.NewDescribeKeyPairsRequest() - request.KeyIds = []*string{&keyId} + request.KeyIds = []*string{helper.String(keyId)} + + 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()) + } + }() ratelimit.Check(request.GetAction()) + response, err := me.client.UseCvmClient().DescribeKeyPairs(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()) + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) - if len(response.Response.KeyPairSet) > 0 { - keyPair = response.Response.KeyPairSet[0] + if len(response.Response.KeyPairSet) < 1 { + return } + + ret = response.Response.KeyPairSet[0] return } @@ -745,26 +756,32 @@ func (me *CvmService) CreatePlacementGroup(ctx context.Context, placementName, p return } -func (me *CvmService) DescribePlacementGroupById(ctx context.Context, placementId string) (placementGroup *cvm.DisasterRecoverGroup, errRet error) { +func (me *CvmService) DescribePlacementGroupById(ctx context.Context, disasterRecoverGroupId string) (ret *cvm.DisasterRecoverGroup, errRet error) { logId := tccommon.GetLogId(ctx) + request := cvm.NewDescribeDisasterRecoverGroupsRequest() - request.DisasterRecoverGroupIds = []*string{&placementId} + request.DisasterRecoverGroupIds = []*string{helper.String(disasterRecoverGroupId)} + + 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()) + } + }() ratelimit.Check(request.GetAction()) + response, err := me.client.UseCvmClient().DescribeDisasterRecoverGroups(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()) + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) if len(response.Response.DisasterRecoverGroupSet) < 1 { return } - placementGroup = response.Response.DisasterRecoverGroupSet[0] + + ret = response.Response.DisasterRecoverGroupSet[0] return } @@ -1073,52 +1090,32 @@ func (me *CvmService) DeleteImage(ctx context.Context, imageId string) error { return nil } -func (me *CvmService) DescribeImageById(ctx context.Context, keyId string, isDelete bool) (image *cvm.Image, has bool, errRet error) { +func (me *CvmService) DescribeImageById(ctx context.Context, imageId string) (ret *cvm.Image, errRet error) { logId := tccommon.GetLogId(ctx) + request := cvm.NewDescribeImagesRequest() - request.ImageIds = []*string{&keyId} + request.ImageIds = []*string{helper.String(imageId)} - var imgRsp *cvm.DescribeImagesResponse - err := resource.Retry(20*tccommon.ReadRetryTimeout, func() *resource.RetryError { - ratelimit.Check(request.GetAction()) - response, err := me.client.UseCvmClient().DescribeImages(request) - if err != nil { - return resource.RetryableError(err) + 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()) } - if response != nil && response.Response != nil { - if len(response.Response.ImageSet) == 0 && !isDelete { - return resource.RetryableError(fmt.Errorf("iamge instance status is processing")) - } - if len(response.Response.ImageSet) > 0 { - if *response.Response.ImageSet[0].ImageState == "CREATEFAILED" { - return resource.NonRetryableError(fmt.Errorf("[CRITAL]%s Create Image is failed", logId)) - } - if *response.Response.ImageSet[0].ImageState != "NORMAL" { - return resource.RetryableError(fmt.Errorf("iamge instance status is processing")) - } - } + }() - imgRsp = response - return nil - } - return resource.NonRetryableError(fmt.Errorf("response is null")) - }) + ratelimit.Check(request.GetAction()) + response, err := me.client.UseCvmClient().DescribeImages(request) if err != nil { - log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]", - 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 imgRsp == nil { + if len(response.Response.ImageSet) < 1 { return } - if len(imgRsp.Response.ImageSet) > 0 && len(imgRsp.Response.ImageSet[0].SnapshotSet) != 0 { - has = true - image = imgRsp.Response.ImageSet[0] - } + ret = response.Response.ImageSet[0] return } @@ -1242,11 +1239,11 @@ func (me *CvmService) ResizeInstanceDisks(ctx context.Context, request *cvm.Resi return } -func (me *CvmService) DescribeCvmHpcClusterById(ctx context.Context, hpcClusterId string) (hpcCluster *cvm.HpcClusterInfo, errRet error) { +func (me *CvmService) DescribeCvmHpcClusterById(ctx context.Context, hpcClusterId string) (ret *cvm.HpcClusterInfo, errRet error) { logId := tccommon.GetLogId(ctx) request := cvm.NewDescribeHpcClustersRequest() - request.HpcClusterIds = []*string{&hpcClusterId} + request.HpcClusterIds = []*string{helper.String(hpcClusterId)} defer func() { if errRet != nil { @@ -1260,7 +1257,7 @@ func (me *CvmService) DescribeCvmHpcClusterById(ctx context.Context, hpcClusterI offset uint64 = 0 limit uint64 = 20 ) - instances := make([]*cvm.HpcClusterInfo, 0) + var instances []*cvm.HpcClusterInfo for { request.Offset = &offset request.Limit = &limit @@ -1285,7 +1282,8 @@ func (me *CvmService) DescribeCvmHpcClusterById(ctx context.Context, hpcClusterI if len(instances) < 1 { return } - hpcCluster = instances[0] + + ret = instances[0] return } @@ -1313,11 +1311,11 @@ func (me *CvmService) DeleteCvmHpcClusterById(ctx context.Context, hpcClusterId return } -func (me *CvmService) DescribeCvmLaunchTemplateById(ctx context.Context, launchTemplateId string) (launchTemplate *cvm.LaunchTemplateInfo, errRet error) { +func (me *CvmService) DescribeCvmLaunchTemplateById(ctx context.Context, launchTemplateId string) (ret *cvm.LaunchTemplateInfo, errRet error) { logId := tccommon.GetLogId(ctx) request := cvm.NewDescribeLaunchTemplatesRequest() - request.LaunchTemplateIds = []*string{&launchTemplateId} + request.LaunchTemplateIds = []*string{helper.String(launchTemplateId)} defer func() { if errRet != nil { @@ -1338,7 +1336,7 @@ func (me *CvmService) DescribeCvmLaunchTemplateById(ctx context.Context, launchT return } - launchTemplate = response.Response.LaunchTemplateSet[0] + ret = response.Response.LaunchTemplateSet[0] return } @@ -1513,7 +1511,7 @@ func (me *CvmService) ModifyLaunchTemplateDefaultVersion(ctx context.Context, la return nil } -func (me *CvmService) DescribeCvmChcHostsByFilter(ctx context.Context, param map[string]interface{}) (chcHosts []*cvm.ChcHost, errRet error) { +func (me *CvmService) DescribeCvmChcHostsByFilter(ctx context.Context, param map[string]interface{}) (ret []*cvm.ChcHost, errRet error) { var ( logId = tccommon.GetLogId(ctx) request = cvm.NewDescribeChcHostsRequest() @@ -1526,10 +1524,10 @@ func (me *CvmService) DescribeCvmChcHostsByFilter(ctx context.Context, param map }() for k, v := range param { - if k == "chc_ids" { - request.ChcIds = helper.Strings(v.([]string)) + if k == "ChcIds" { + request.ChcIds = v.([]*string) } - if k == "filters" { + if k == "Filters" { request.Filters = v.([]*cvm.Filter) } } @@ -1538,7 +1536,7 @@ func (me *CvmService) DescribeCvmChcHostsByFilter(ctx context.Context, param map var ( offset int64 = 0 - limit int64 = 20 + limit int64 = 100 ) for { request.Offset = &offset @@ -1553,7 +1551,7 @@ func (me *CvmService) DescribeCvmChcHostsByFilter(ctx context.Context, param map if response == nil || len(response.Response.ChcHostSet) < 1 { break } - chcHosts = append(chcHosts, response.Response.ChcHostSet...) + ret = append(ret, response.Response.ChcHostSet...) if len(response.Response.ChcHostSet) < int(limit) { break } @@ -1564,7 +1562,7 @@ func (me *CvmService) DescribeCvmChcHostsByFilter(ctx context.Context, param map return } -func (me *CvmService) DescribeCvmChcDeniedActionsByFilter(ctx context.Context, param map[string]interface{}) (chcDeniedActions []*cvm.ChcHostDeniedActions, errRet error) { +func (me *CvmService) DescribeCvmChcDeniedActionsByFilter(ctx context.Context, param map[string]interface{}) (ret []*cvm.ChcHostDeniedActions, errRet error) { var ( logId = tccommon.GetLogId(ctx) request = cvm.NewDescribeChcDeniedActionsRequest() @@ -1577,8 +1575,8 @@ func (me *CvmService) DescribeCvmChcDeniedActionsByFilter(ctx context.Context, p }() for k, v := range param { - if k == "chc_ids" { - request.ChcIds = helper.Strings(v.([]string)) + if k == "ChcIds" { + request.ChcIds = v.([]*string) } } @@ -1591,11 +1589,11 @@ func (me *CvmService) DescribeCvmChcDeniedActionsByFilter(ctx context.Context, p } 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.ChcHostDeniedActionSet) < 1 { + if len(response.Response.ChcHostDeniedActionSet) < 1 { return } - chcDeniedActions = append(chcDeniedActions, response.Response.ChcHostDeniedActionSet...) + ret = response.Response.ChcHostDeniedActionSet return } @@ -1682,7 +1680,7 @@ func (me *CvmService) CvmSyncImagesStateRefreshFunc(imageId string, failStates [ } } -func (me *CvmService) DescribeCvmImageQuotaByFilter(ctx context.Context, param map[string]interface{}) (imageQuota int64, errRet error) { +func (me *CvmService) DescribeCvmImageQuotaByFilter(ctx context.Context, param map[string]interface{}) (ret *cvm.DescribeImageQuotaResponseParams, errRet error) { var ( logId = tccommon.GetLogId(ctx) request = cvm.NewDescribeImageQuotaRequest() @@ -1704,15 +1702,14 @@ func (me *CvmService) DescribeCvmImageQuotaByFilter(ctx context.Context, param m log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) if response == nil || response.Response == nil { - errRet = fmt.Errorf("Response is null") return } - imageQuota = *response.Response.ImageNumQuota + ret = response.Response return } -func (me *CvmService) DescribeCvmImageSharePermissionByFilter(ctx context.Context, param map[string]interface{}) (imageSharePermission []*cvm.SharePermission, errRet error) { +func (me *CvmService) DescribeCvmImageSharePermissionByFilter(ctx context.Context, param map[string]interface{}) (ret []*cvm.SharePermission, errRet error) { var ( logId = tccommon.GetLogId(ctx) request = cvm.NewDescribeImageSharePermissionRequest() @@ -1739,11 +1736,11 @@ func (me *CvmService) DescribeCvmImageSharePermissionByFilter(ctx context.Contex } log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) - if response == nil || response.Response == nil { - errRet = fmt.Errorf("Response is null") + if len(response.Response.SharePermissionSet) < 1 { + return } - imageSharePermission = response.Response.SharePermissionSet + ret = response.Response.SharePermissionSet return } @@ -1776,3 +1773,311 @@ func (me *CvmService) ModifyImageSharePermission(ctx context.Context, imageId, p } return } + +func (me *CvmService) DescribeCvmDisasterRecoverGroupQuotaByFilter(ctx context.Context, param map[string]interface{}) (ret *cvm.DescribeDisasterRecoverGroupQuotaResponseParams, errRet error) { + var ( + logId = tccommon.GetLogId(ctx) + request = cvm.NewDescribeDisasterRecoverGroupQuotaRequest() + ) + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseCvmClient().DescribeDisasterRecoverGroupQuota(request) + if err != nil { + 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 || response.Response == nil { + return + } + + ret = response.Response + return +} + +func (me *CvmService) DescribeCvmImportImageOsByFilter(ctx context.Context, param map[string]interface{}) (ret *cvm.DescribeImportImageOsResponseParams, errRet error) { + var ( + logId = tccommon.GetLogId(ctx) + request = cvm.NewDescribeImportImageOsRequest() + ) + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseCvmClient().DescribeImportImageOs(request) + if err != nil { + 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 || response.Response == nil { + return + } + + ret = response.Response + return +} + +func (me *CvmService) DescribeCvmChcConfigById(ctx context.Context, chcId string) (ret *cvm.ChcHost, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cvm.NewDescribeChcHostsRequest() + request.ChcIds = []*string{helper.String(chcId)} + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + var ( + offset int64 = 0 + limit int64 = 20 + ) + var instances []*cvm.ChcHost + for { + request.Offset = &offset + request.Limit = &limit + response, err := me.client.UseCvmClient().DescribeChcHosts(request) + if err != nil { + 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.ChcHostSet) < 1 { + break + } + instances = append(instances, response.Response.ChcHostSet...) + if len(response.Response.ChcHostSet) < int(limit) { + break + } + + offset += limit + } + + if len(instances) < 1 { + return + } + + ret = instances[0] + return +} + +func (me *CvmService) DescribeCvmImageSharePermissionById(ctx context.Context, imageId string) (ret *cvm.DescribeImageSharePermissionResponseParams, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cvm.NewDescribeImageSharePermissionRequest() + request.ImageId = &imageId + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseCvmClient().DescribeImageSharePermission(request) + if err != nil { + errRet = err + return + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + ret = response.Response + return +} + +func (me *CvmService) DescribeCvmLaunchTemplateById1(ctx context.Context, launchTemplateId string) (ret *cvm.LaunchTemplateVersionInfo, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cvm.NewDescribeLaunchTemplateVersionsRequest() + request.LaunchTemplateId = helper.String(launchTemplateId) + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseCvmClient().DescribeLaunchTemplateVersions(request) + if err != nil { + 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 len(response.Response.LaunchTemplateVersionSet) < 1 { + return + } + + ret = response.Response.LaunchTemplateVersionSet[0] + return +} + +func (me *CvmService) DescribeReservedInstanceById(ctx context.Context, reservedInstanceId string) (ret *cvm.ReservedInstances, errRet error) { + logId := tccommon.GetLogId(ctx) + + request := cvm.NewDescribeReservedInstancesRequest() + filter := &cvm.Filter{ + Name: helper.String("reserved-instances-id"), + Values: []*string{helper.String(reservedInstanceId)}, + } + request.Filters = append(request.Filters, filter) + + 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()) + } + }() + + ratelimit.Check(request.GetAction()) + + var ( + offset int64 = 0 + limit int64 = 20 + ) + var instances []*cvm.ReservedInstances + for { + request.Offset = &offset + request.Limit = &limit + response, err := me.client.UseCvmClient().DescribeReservedInstances(request) + if err != nil { + 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.ReservedInstancesSet) < 1 { + break + } + instances = append(instances, response.Response.ReservedInstancesSet...) + if len(response.Response.ReservedInstancesSet) < int(limit) { + break + } + + offset += limit + } + + if len(instances) < 1 { + return + } + + ret = instances[0] + return +} + +func (me *CvmService) DescribeReservedInstanceConfigsByFilter(ctx context.Context, param map[string]interface{}) (ret []*cvm.ReservedInstancesOffering, errRet error) { + var ( + logId = tccommon.GetLogId(ctx) + request = cvm.NewDescribeReservedInstancesOfferingsRequest() + ) + + 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()) + } + }() + + for k, v := range param { + if k == "Filters" { + request.Filters = v.([]*cvm.Filter) + } + } + + ratelimit.Check(request.GetAction()) + + var ( + offset int64 = 0 + limit int64 = 100 + ) + for { + request.Offset = &offset + request.Limit = &limit + response, err := me.client.UseCvmClient().DescribeReservedInstancesOfferings(request) + if err != nil { + 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.ReservedInstancesOfferingsSet) < 1 { + break + } + ret = append(ret, response.Response.ReservedInstancesOfferingsSet...) + if len(response.Response.ReservedInstancesOfferingsSet) < int(limit) { + break + } + + offset += limit + } + + return +} + +func (me *CvmService) DescribeReservedInstancesByFilter(ctx context.Context, param map[string]interface{}) (ret []*cvm.ReservedInstances, errRet error) { + var ( + logId = tccommon.GetLogId(ctx) + request = cvm.NewDescribeReservedInstancesRequest() + ) + + 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()) + } + }() + + for k, v := range param { + if k == "Filters" { + request.Filters = v.([]*cvm.Filter) + } + } + + ratelimit.Check(request.GetAction()) + + var ( + offset int64 = 0 + limit int64 = 100 + ) + for { + request.Offset = &offset + request.Limit = &limit + response, err := me.client.UseCvmClient().DescribeReservedInstances(request) + if err != nil { + 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.ReservedInstancesSet) < 1 { + break + } + ret = append(ret, response.Response.ReservedInstancesSet...) + if len(response.Response.ReservedInstancesSet) < int(limit) { + break + } + + offset += limit + } + + return +} diff --git a/website/docs/r/image.html.markdown b/website/docs/r/image.html.markdown index 5c413cb968..d9d7b594b7 100644 --- a/website/docs/r/image.html.markdown +++ b/website/docs/r/image.html.markdown @@ -33,7 +33,7 @@ The following arguments are supported: * `instance_id` - (Optional, String, ForceNew) Cloud server instance ID. * `snapshot_ids` - (Optional, Set: [`String`], ForceNew) Cloud disk snapshot ID list; creating a mirror based on a snapshot must include a system disk snapshot. It cannot be passed in simultaneously with InstanceId. * `sysprep` - (Optional, Bool) Sysprep function under Windows. When creating a Windows image, you can select true or false to enable or disable the Syspre function. -* `tags` - (Optional, Map) Tags of the image. +* `tags` - (Optional, Map) Tag description list. ## Attributes Reference diff --git a/website/docs/r/instance.html.markdown b/website/docs/r/instance.html.markdown index 799a5ca57a..21a3e4907e 100644 --- a/website/docs/r/instance.html.markdown +++ b/website/docs/r/instance.html.markdown @@ -120,9 +120,9 @@ The following arguments are supported: * `disable_security_service` - (Optional, Bool) Disable enhance service for security, it is enabled by default. When this options is set, security agent won't be installed. Modifying will cause the instance reset. * `force_delete` - (Optional, Bool) Indicate whether to force delete the instance. Default is `false`. If set true, the instance will be permanently deleted instead of being moved into the recycle bin. Note: only works for `PREPAID` instance. * `hostname` - (Optional, String) The hostname of the instance. Windows instance: The name should be a combination of 2 to 15 characters comprised of letters (case insensitive), numbers, and hyphens (-). Period (.) is not supported, and the name cannot be a string of pure numbers. Other types (such as Linux) of instances: The name should be a combination of 2 to 60 characters, supporting multiple periods (.). The piece between two periods is composed of letters (case insensitive), numbers, and hyphens (-). Modifying will cause the instance reset. -* `instance_charge_type_prepaid_period` - (Optional, Int) The tenancy (time unit is month) of the prepaid instance, NOTE: it only works when instance_charge_type is set to `PREPAID`. Valid values are `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `24`, `36`, `48`, `60`. +* `instance_charge_type_prepaid_period` - (Optional, Int) The tenancy (time unit is month) of the prepaid instance, NOTE: it only works when instance_charge_type is set to `PREPAID`. Valid values are `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `24`, `36`. * `instance_charge_type_prepaid_renew_flag` - (Optional, String) Auto renewal flag. Valid values: `NOTIFY_AND_AUTO_RENEW`: notify upon expiration and renew automatically, `NOTIFY_AND_MANUAL_RENEW`: notify upon expiration but do not renew automatically, `DISABLE_NOTIFY_AND_MANUAL_RENEW`: neither notify upon expiration nor renew automatically. Default value: `NOTIFY_AND_MANUAL_RENEW`. If this parameter is specified as `NOTIFY_AND_AUTO_RENEW`, the instance will be automatically renewed on a monthly basis if the account balance is sufficient. NOTE: it only works when instance_charge_type is set to `PREPAID`. -* `instance_charge_type` - (Optional, String) The charge type of instance. Valid values are `PREPAID`, `POSTPAID_BY_HOUR`, `SPOTPAID`, `CDHPAID` and `CDCPAID`. The default is `POSTPAID_BY_HOUR`. Note: TencentCloud International only supports `POSTPAID_BY_HOUR` and `CDHPAID`. `PREPAID` instance may not allow to delete before expired. `SPOTPAID` instance must set `spot_instance_type` and `spot_max_price` at the same time. `CDHPAID` instance must set `cdh_instance_type` and `cdh_host_id`. +* `instance_charge_type` - (Optional, String) The charge type of instance. Valid values are `PREPAID`, `POSTPAID_BY_HOUR`, `SPOTPAID` and `CDHPAID`. The default is `POSTPAID_BY_HOUR`. Note: TencentCloud International only supports `POSTPAID_BY_HOUR` and `CDHPAID`. `PREPAID` instance may not allow to delete before expired. `SPOTPAID` instance must set `spot_instance_type` and `spot_max_price` at the same time. `CDHPAID` instance must set `cdh_instance_type` and `cdh_host_id`. * `instance_count` - (Optional, Int, **Deprecated**) It has been deprecated from version 1.59.18. Use built-in `count` instead. The number of instances to be purchased. Value range:[1,100]; default value: 1. * `instance_name` - (Optional, String) The name of the instance. The max length of instance_name is 60, and default value is `Terraform-CVM-Instance`. * `instance_type` - (Optional, String) The type of the instance. diff --git a/website/docs/r/key_pair.html.markdown b/website/docs/r/key_pair.html.markdown index 664d0214fa..26e0e274d3 100644 --- a/website/docs/r/key_pair.html.markdown +++ b/website/docs/r/key_pair.html.markdown @@ -31,7 +31,7 @@ The following arguments are supported: * `key_name` - (Required, String) The key pair's name. It is the only in one TencentCloud account. * `project_id` - (Optional, Int, ForceNew) Specifys to which project the key pair belongs. * `public_key` - (Optional, String, ForceNew) You can import an existing public key and using TencentCloud key pair to manage it. -* `tags` - (Optional, Map) Tags of the key pair. +* `tags` - (Optional, Map) Tag description list. ## Attributes Reference