@@ -541,9 +541,6 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{}
541
541
if period , ok := d .GetOk ("instance_charge_type_prepaid_period" ); ok {
542
542
periodInt64 := int64 (period .(int ))
543
543
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 )
547
544
}
548
545
if renewFlag , ok := d .GetOk ("instance_charge_type_prepaid_renew_flag" ); ok {
549
546
request .InstanceChargePrepaid .RenewFlag = helper .String (renewFlag .(string ))
@@ -1006,12 +1003,19 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1006
1003
1007
1004
d .Partial (true )
1008
1005
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
+
1009
1012
var (
1010
- periodSet = false
1011
- renewFlagSet = false
1013
+ periodSet = false
1014
+ renewFlagSet = false
1015
+ alreadyPrepaid = * instanceInfo .InstanceChargeType == CVM_CHARGE_TYPE_PREPAID
1012
1016
)
1013
1017
1014
- if d .HasChange ("instance_charge_type" ) {
1018
+ if d .HasChange ("instance_charge_type" ) && ! alreadyPrepaid {
1015
1019
old , chargeType := d .GetChange ("instance_charge_type" )
1016
1020
if old .(string ) != CVM_CHARGE_TYPE_POSTPAID || chargeType .(string ) != CVM_CHARGE_TYPE_PREPAID {
1017
1021
return fmt .Errorf ("Only support change chargeType from POSTPAID_BY_HOUR to PREPAID." )
@@ -1022,9 +1026,6 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1022
1026
)
1023
1027
if v , ok := d .GetOk ("instance_charge_type_prepaid_period" ); ok {
1024
1028
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 )
1028
1029
}
1029
1030
if v , ok := d .GetOk ("instance_charge_type_prepaid_renew_flag" ); ok {
1030
1031
renewFlag = v .(string )
@@ -1035,70 +1036,48 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1035
1036
return err
1036
1037
}
1037
1038
// 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 )
1053
1040
if err != nil {
1054
1041
return err
1055
1042
}
1056
1043
periodSet = true
1057
1044
renewFlagSet = true
1058
1045
}
1059
1046
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
+ }
1060
1052
if d .HasChange ("instance_charge_type_prepaid_period" ) && ! periodSet {
1061
1053
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 )
1064
1059
}
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
1067
1063
}
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
1068
1070
}
1069
1071
1070
1072
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
-
1077
1073
//renew api
1078
1074
err := cvmService .ModifyRenewParam (ctx , instanceId , d .Get ("instance_charge_type_prepaid_renew_flag" ).(string ))
1079
1075
if err != nil {
1080
1076
return err
1081
1077
}
1082
1078
1083
1079
//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 )
1102
1081
if err != nil {
1103
1082
return err
1104
1083
}
@@ -1217,18 +1196,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1217
1196
if err != nil {
1218
1197
return err
1219
1198
}
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 )
1232
1200
if err != nil {
1233
1201
return err
1234
1202
}
@@ -1243,17 +1211,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1243
1211
if err != nil {
1244
1212
return err
1245
1213
}
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 )
1257
1215
if err != nil {
1258
1216
return err
1259
1217
}
@@ -1264,17 +1222,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1264
1222
if err != nil {
1265
1223
return err
1266
1224
}
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 )
1278
1226
if err != nil {
1279
1227
return err
1280
1228
}
@@ -1379,20 +1327,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1379
1327
}
1380
1328
d .SetPartial ("instance_type" )
1381
1329
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 )
1396
1331
if err != nil {
1397
1332
return err
1398
1333
}
@@ -1405,20 +1340,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1405
1340
}
1406
1341
d .SetPartial ("cdh_instance_type" )
1407
1342
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 )
1422
1344
if err != nil {
1423
1345
return err
1424
1346
}
@@ -1491,17 +1413,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{}
1491
1413
return err
1492
1414
}
1493
1415
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 )
1505
1417
if err != nil {
1506
1418
return err
1507
1419
}
@@ -1749,3 +1661,39 @@ func switchInstance(cvmService *CvmService, ctx context.Context, d *schema.Resou
1749
1661
}
1750
1662
return nil
1751
1663
}
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