@@ -541,9 +541,6 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{}
541541 if period , ok := d .GetOk ("instance_charge_type_prepaid_period" ); ok {
542542 periodInt64 := int64 (period .(int ))
543543 request .InstanceChargePrepaid .Period = & periodInt64
544- } else {
545- return fmt .Errorf ("instance charge type prepaid period can not be empty when charge type is %s" ,
546- instanceChargeType )
547544 }
548545 if renewFlag , ok := d .GetOk ("instance_charge_type_prepaid_renew_flag" ); ok {
549546 request .InstanceChargePrepaid .RenewFlag = helper .String (renewFlag .(string ))
@@ -1006,12 +1003,19 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
10061003
10071004 d .Partial (true )
10081005
1006+ // Get the latest instance info from actual resource.
1007+ instanceInfo , err := cvmService .DescribeInstanceById (ctx , instanceId )
1008+ if err != nil {
1009+ return err
1010+ }
1011+
10091012 var (
1010- periodSet = false
1011- renewFlagSet = false
1013+ periodSet = false
1014+ renewFlagSet = false
1015+ alreadyPrepaid = * instanceInfo .InstanceChargeType == CVM_CHARGE_TYPE_PREPAID
10121016 )
10131017
1014- if d .HasChange ("instance_charge_type" ) {
1018+ if d .HasChange ("instance_charge_type" ) && ! alreadyPrepaid {
10151019 old , chargeType := d .GetChange ("instance_charge_type" )
10161020 if old .(string ) != CVM_CHARGE_TYPE_POSTPAID || chargeType .(string ) != CVM_CHARGE_TYPE_PREPAID {
10171021 return fmt .Errorf ("Only support change chargeType from POSTPAID_BY_HOUR to PREPAID." )
@@ -1022,9 +1026,6 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
10221026 )
10231027 if v , ok := d .GetOk ("instance_charge_type_prepaid_period" ); ok {
10241028 period = v .(int )
1025- } else {
1026- return fmt .Errorf ("instance charge type prepaid period can not" +
1027- " be empty when charge type is %s" , chargeType )
10281029 }
10291030 if v , ok := d .GetOk ("instance_charge_type_prepaid_renew_flag" ); ok {
10301031 renewFlag = v .(string )
@@ -1035,70 +1036,48 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
10351036 return err
10361037 }
10371038 // query cvm status
1038- err = resource .Retry (5 * readRetryTimeout , func () * resource.RetryError {
1039- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1040- if errRet != nil {
1041- return retryError (errRet , InternalError )
1042- }
1043- if instance != nil && instance .LatestOperationState != nil {
1044- if * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING {
1045- return resource .RetryableError (fmt .Errorf ("cvm instance status is %s, retry..." , * instance .LatestOperationState ))
1046- }
1047- if * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_FAILED {
1048- return resource .NonRetryableError (fmt .Errorf ("failed operation when modify instance charge type" ))
1049- }
1050- }
1051- return nil
1052- })
1039+ err = waitForOperationFinished (d , meta , 5 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
10531040 if err != nil {
10541041 return err
10551042 }
10561043 periodSet = true
10571044 renewFlagSet = true
10581045 }
10591046
1047+ // When instance is prepaid but period was empty and set to 1, skip this case.
1048+ op , np := d .GetChange ("instance_charge_type_prepaid_period" )
1049+ if _ , ok := op .(int ); ! ok && np .(int ) == 1 {
1050+ periodSet = true
1051+ }
10601052 if d .HasChange ("instance_charge_type_prepaid_period" ) && ! periodSet {
10611053 chargeType := d .Get ("instance_charge_type" ).(string )
1062- if chargeType != CVM_CHARGE_TYPE_PREPAID {
1063- 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" )
1054+ period := d .Get ("instance_charge_type_prepaid_period" ).(int )
1055+ renewFlag := ""
1056+
1057+ if v , ok := d .GetOk ("instance_charge_type_prepaid_renew_flag" ); ok {
1058+ renewFlag = v .(string )
10641059 }
1065- if ! d .HasChange ("instance_charge_type" ) {
1066- return fmt .Errorf ("tencentcloud_cvm_instance update on instance_charge_type_prepaid_period is only with charge type change to PREPAID" )
1060+ err := cvmService .ModifyInstanceChargeType (ctx , instanceId , chargeType , period , renewFlag )
1061+ if err != nil {
1062+ return err
10671063 }
1064+ // query cvm status
1065+ err = waitForOperationFinished (d , meta , 5 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
1066+ if err != nil {
1067+ return err
1068+ }
1069+ renewFlagSet = true
10681070 }
10691071
10701072 if d .HasChange ("instance_charge_type_prepaid_renew_flag" ) && ! renewFlagSet {
1071- //check
1072- chargeType := d .Get ("instance_charge_type" ).(string )
1073- if chargeType != CVM_CHARGE_TYPE_PREPAID {
1074- 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" )
1075- }
1076-
10771073 //renew api
10781074 err := cvmService .ModifyRenewParam (ctx , instanceId , d .Get ("instance_charge_type_prepaid_renew_flag" ).(string ))
10791075 if err != nil {
10801076 return err
10811077 }
10821078
10831079 //check success
1084- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1085- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1086- if errRet != nil {
1087- return retryError (errRet , InternalError )
1088- }
1089- if instance != nil && instance .LatestOperationState != nil {
1090- if * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_SUCCESS {
1091- return nil
1092- } else if * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_FAILED {
1093- return resource .NonRetryableError (fmt .Errorf ("update instance %s prepaid charge type failed" , instanceId ))
1094- } else {
1095- return resource .RetryableError (fmt .Errorf ("cvm instance status is %s, retry..." , * instance .InstanceState ))
1096- }
1097- } else {
1098- return resource .RetryableError (fmt .Errorf ("cvm instance %s returns nil status" , instanceId ))
1099- }
1100-
1101- })
1080+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
11021081 if err != nil {
11031082 return err
11041083 }
@@ -1217,18 +1196,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
12171196 if err != nil {
12181197 return err
12191198 }
1220- d .SetPartial ("password" )
1221- time .Sleep (10 * time .Second )
1222- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1223- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1224- if errRet != nil {
1225- return retryError (errRet , InternalError )
1226- }
1227- if instance != nil && instance .LatestOperationState != nil && * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING {
1228- return resource .RetryableError (fmt .Errorf ("cvm instance latest operetion status is %s, retry..." , * instance .LatestOperationState ))
1229- }
1230- return nil
1231- })
1199+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
12321200 if err != nil {
12331201 return err
12341202 }
@@ -1243,17 +1211,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
12431211 if err != nil {
12441212 return err
12451213 }
1246- time .Sleep (10 * time .Second )
1247- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1248- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1249- if errRet != nil {
1250- return retryError (errRet , InternalError )
1251- }
1252- if instance != nil && instance .LatestOperationState != nil && * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING {
1253- return resource .RetryableError (fmt .Errorf ("cvm instance latest operetion status is %s, retry..." , * instance .LatestOperationState ))
1254- }
1255- return nil
1256- })
1214+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
12571215 if err != nil {
12581216 return err
12591217 }
@@ -1264,17 +1222,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
12641222 if err != nil {
12651223 return err
12661224 }
1267- time .Sleep (10 * time .Second )
1268- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1269- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1270- if errRet != nil {
1271- return retryError (errRet , InternalError )
1272- }
1273- if instance != nil && instance .LatestOperationState != nil && * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING {
1274- return resource .RetryableError (fmt .Errorf ("cvm instance latest operetion status is %s, retry..." , * instance .LatestOperationState ))
1275- }
1276- return nil
1277- })
1225+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
12781226 if err != nil {
12791227 return err
12801228 }
@@ -1379,20 +1327,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
13791327 }
13801328 d .SetPartial ("instance_type" )
13811329
1382- // wait for status
1383- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1384- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1385- if errRet != nil {
1386- return retryError (errRet , InternalError )
1387- }
1388- // Modifying instance type need restart the instance
1389- // so status of CVM must be running when running flag is true
1390- if instance != nil && instance .LatestOperationState != nil && (* instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING ||
1391- (flag && * instance .InstanceState != CVM_STATUS_RUNNING )) {
1392- return resource .RetryableError (fmt .Errorf ("cvm instance latest operetion status is %s, retry..." , * instance .LatestOperationState ))
1393- }
1394- return nil
1395- })
1330+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
13961331 if err != nil {
13971332 return err
13981333 }
@@ -1405,20 +1340,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
14051340 }
14061341 d .SetPartial ("cdh_instance_type" )
14071342
1408- // wait for status
1409- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1410- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1411- if errRet != nil {
1412- return retryError (errRet , InternalError )
1413- }
1414- // Modifying instance type need restart the instance
1415- // so status of CVM must be running when running flag is true
1416- if instance != nil && (instance .LatestOperationState != nil && * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING ||
1417- (flag && instance .LatestOperationState != nil && * instance .InstanceState != CVM_STATUS_RUNNING )) {
1418- return resource .RetryableError (fmt .Errorf ("cvm instance latest operetion status is %s, retry..." , * instance .LatestOperationState ))
1419- }
1420- return nil
1421- })
1343+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
14221344 if err != nil {
14231345 return err
14241346 }
@@ -1491,17 +1413,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
14911413 return err
14921414 }
14931415 d .SetPartial ("internet_max_bandwidth_out" )
1494- time .Sleep (1 * time .Second )
1495- err = resource .Retry (2 * readRetryTimeout , func () * resource.RetryError {
1496- instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1497- if errRet != nil {
1498- return retryError (errRet , InternalError )
1499- }
1500- if instance != nil && * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_OPERATING {
1501- return resource .RetryableError (fmt .Errorf ("cvm instance latest operetion status is %s, retry..." , * instance .LatestOperationState ))
1502- }
1503- return nil
1504- })
1416+ err = waitForOperationFinished (d , meta , 2 * readRetryTimeout , CVM_LATEST_OPERATION_STATE_OPERATING , false )
15051417 if err != nil {
15061418 return err
15071419 }
@@ -1749,3 +1661,39 @@ func switchInstance(cvmService *CvmService, ctx context.Context, d *schema.Resou
17491661 }
17501662 return nil
17511663}
1664+
1665+ func waitForOperationFinished (d * schema.ResourceData , meta interface {}, timeout time.Duration , state string , immediately bool ) error {
1666+ logId := getLogId (contextNil )
1667+ ctx := context .WithValue (context .TODO (), logIdKey , logId )
1668+ client := meta .(* TencentCloudClient ).apiV3Conn
1669+ cvmService := CvmService {client }
1670+ instanceId := d .Id ()
1671+ // We cannot catch LatestOperationState change immediately after modification returns, we must wait for LatestOperationState update to expected.
1672+ if ! immediately {
1673+ time .Sleep (time .Second * 10 )
1674+ }
1675+
1676+ err := resource .Retry (timeout , func () * resource.RetryError {
1677+ instance , errRet := cvmService .DescribeInstanceById (ctx , instanceId )
1678+ if errRet != nil {
1679+ return retryError (errRet , InternalError )
1680+ }
1681+ if instance == nil {
1682+ return resource .NonRetryableError (fmt .Errorf ("%s not exists" , instanceId ))
1683+ }
1684+ if instance .LatestOperationState == nil {
1685+ return resource .RetryableError (fmt .Errorf ("wait for operation update" ))
1686+ }
1687+ if * instance .LatestOperationState == state {
1688+ return resource .RetryableError (fmt .Errorf ("waiting for instance %s operation" , instanceId ))
1689+ }
1690+ if * instance .LatestOperationState == CVM_LATEST_OPERATION_STATE_FAILED {
1691+ return resource .NonRetryableError (fmt .Errorf ("failed operation" ))
1692+ }
1693+ return nil
1694+ })
1695+ if err != nil {
1696+ return err
1697+ }
1698+ return nil
1699+ }
0 commit comments