diff --git a/tencentcloud/resource_tc_instance.go b/tencentcloud/resource_tc_instance.go index 26cafee65c..d75b5c6b58 100644 --- a/tencentcloud/resource_tc_instance.go +++ b/tencentcloud/resource_tc_instance.go @@ -229,7 +229,6 @@ func resourceTencentCloudInstance() *schema.Resource { "instance_charge_type": { Type: schema.TypeString, Optional: true, - ForceNew: true, Default: CVM_CHARGE_TYPE_POSTPAID, ValidateFunc: validateAllowedStringValue(CVM_CHARGE_TYPE), 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`.", @@ -968,12 +967,53 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{} d.Partial(true) - unsupportedUpdateFields := []string{ - "instance_charge_type_prepaid_period", + if d.HasChange("instance_charge_type") { + old, chargeType := d.GetChange("instance_charge_type") + if old.(string) != CVM_CHARGE_TYPE_POSTPAID || chargeType.(string) != CVM_CHARGE_TYPE_PREPAID { + return fmt.Errorf("Only support change chargeType from POSTPAID_BY_HOUR to PREPAID.") + } + var ( + period int + renewFlag string + ) + if v, ok := d.GetOk("instance_charge_type_prepaid_period"); ok { + period = v.(int) + } else { + return fmt.Errorf("instance charge type prepaid period can not"+ + " be empty when charge type is %s", chargeType) + } + if v, ok := d.GetOk("instance_charge_type_prepaid_renew_flag"); ok { + renewFlag = v.(string) + } + // change charge type + err := cvmService.ModifyInstanceChargeType(ctx, instanceId, chargeType.(string), period, renewFlag) + if err != nil { + return err + } + // query cvm status + err = resource.Retry(5*readRetryTimeout, func() *resource.RetryError { + instance, errRet := cvmService.DescribeInstanceById(ctx, instanceId) + if errRet != nil { + return retryError(errRet, InternalError) + } + if instance != nil && (*instance.InstanceState == CVM_STATUS_RUNNING || + *instance.InstanceState == CVM_STATUS_LAUNCH_FAILED) { + return nil + } + return resource.RetryableError(fmt.Errorf("cvm instance status is %s, retry...", *instance.InstanceState)) + }) + if err != nil { + return err + } } - for _, field := range unsupportedUpdateFields { - if d.HasChange(field) { - return fmt.Errorf("tencentcloud_cvm_instance update on %s is not support yet", field) + + if d.HasChange("instance_charge_type_prepaid_period") { + chargeType := d.Get("instance_charge_type").(string) + if chargeType != CVM_CHARGE_TYPE_PREPAID { + return fmt.Errorf("tencentcloud_cvm_instance update on instance_charge_type_prepaid_period or instance_charge_type_prepaid_renew_flag is only supported with charge type PREPAID") + } + if !d.HasChange("instance_charge_type") { + return fmt.Errorf("tencentcloud_cvm_instance update on instance_charge_type_prepaid_period is only with charge type change to PREPAID") } } diff --git a/tencentcloud/service_tencentcloud_cvm.go b/tencentcloud/service_tencentcloud_cvm.go index 2972d1551e..9b19379506 100644 --- a/tencentcloud/service_tencentcloud_cvm.go +++ b/tencentcloud/service_tencentcloud_cvm.go @@ -1027,3 +1027,30 @@ func (me *CvmService) ModifyRenewParam(ctx context.Context, instanceId string, r return nil } + +func (me *CvmService) ModifyInstanceChargeType(ctx context.Context, instanceId string, chargeType string, period int, + renewFlag string) error { + logId := getLogId(ctx) + request := cvm.NewModifyInstancesChargeTypeRequest() + request.InstanceIds = []*string{&instanceId} + request.InstanceChargeType = &chargeType + request.InstanceChargePrepaid = &cvm.InstanceChargePrepaid{} + if period != -1 { + request.InstanceChargePrepaid.Period = helper.IntInt64(period) + } + if renewFlag != "" { + request.InstanceChargePrepaid.RenewFlag = &renewFlag + } + + ratelimit.Check(request.GetAction()) + response, err := me.client.UseCvmClient().ModifyInstancesChargeType(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 err + } + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", + logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + return nil +} diff --git a/website/docs/r/instance.html.markdown b/website/docs/r/instance.html.markdown index 280e71421d..ab90af155c 100644 --- a/website/docs/r/instance.html.markdown +++ b/website/docs/r/instance.html.markdown @@ -153,7 +153,7 @@ The following arguments are supported: * `hostname` - (Optional) 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) 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) 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, ForceNew) 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_charge_type` - (Optional) 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, **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) The name of the instance. The max length of instance_name is 60, and default value is `Terraform-CVM-Instance`. * `instance_type` - (Optional) The type of the instance.