diff --git a/tencentcloud/basic_test.go b/tencentcloud/basic_test.go index 446df42465..3c7df96997 100644 --- a/tencentcloud/basic_test.go +++ b/tencentcloud/basic_test.go @@ -147,6 +147,7 @@ resource "tencentcloud_mysql_instance" "default" { engine_version = "5.7" root_password = "0153Y474" availability_zone = var.availability_zone + force_delete = true } ` const mysqlInstanceHighPerformanceTestCase = defaultVpcVariable + ` diff --git a/tencentcloud/resource_tc_mysql_instance_test.go b/tencentcloud/resource_tc_mysql_instance_test.go index 3d03ab7df1..db15514a64 100644 --- a/tencentcloud/resource_tc_mysql_instance_test.go +++ b/tencentcloud/resource_tc_mysql_instance_test.go @@ -37,6 +37,7 @@ func testSweepMySQLInstance(region string) error { request := cdb.NewDescribeDBInstancesRequest() request.InstanceNames = []*string{ + helper.String(defaultInsName), helper.String(TestAccTencentCloudMysqlInstanceName), helper.String(TestAccTencentCloudMysqlInstanceNameVersion1), helper.String(TestAccTencentCloudMysqlInstanceNamePrepaid), @@ -309,7 +310,7 @@ func testAccCheckMysqlMasterInstanceExists(n string) resource.TestCheckFunc { func testAccMysqlMasterInstance_basic() string { return ` resource "tencentcloud_mysql_instance" "mysql_master" { - pay_type = 1 + charge_type = "POSTPAID" mem_size = 1000 volume_size = 50 instance_name = "testAccMysql" @@ -318,6 +319,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { intranet_port = 3360 availability_zone = "ap-guangzhou-3" first_slave_zone = "ap-guangzhou-3" + force_delete = true }` } @@ -357,7 +359,7 @@ resource "tencentcloud_mysql_instance" "prepaid" { func testAccMysqlMasterInstance_fullslave() string { return ` resource "tencentcloud_mysql_instance" "mysql_master" { - pay_type = 1 + charge_type = "POSTPAID" mem_size = 1000 volume_size = 50 instance_name = "testAccMysql" @@ -369,6 +371,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { first_slave_zone = "ap-guangzhou-3" second_slave_zone = "ap-guangzhou-3" slave_sync_mode = 2 + force_delete = true }` } @@ -379,7 +382,7 @@ func testAccMysqlMasterInstance_internet_service(open bool) string { } return ` resource "tencentcloud_mysql_instance" "mysql_master" { - pay_type = 1 + charge_type = "POSTPAID" mem_size = 1000 volume_size = 50 instance_name = "testAccMysql" @@ -389,6 +392,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { availability_zone = "ap-guangzhou-3" first_slave_zone = "ap-guangzhou-3" internet_service = ` + tag + ` + force_delete = true }` } @@ -396,7 +400,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { func testAccMysqlMasterInstance_parameters() string { return ` resource "tencentcloud_mysql_instance" "mysql_master" { - pay_type = 1 + charge_type = "POSTPAID" mem_size = 1000 volume_size = 50 instance_name = "testAccMysql" @@ -405,6 +409,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { intranet_port = 3360 availability_zone = "ap-guangzhou-3" first_slave_zone = "ap-guangzhou-3" + force_delete = true parameters = { max_connections = "1000" @@ -415,7 +420,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { func testAccMysqlMasterInstance_multiTags(value string) string { return fmt.Sprintf(` resource "tencentcloud_mysql_instance" "mysql_master" { - pay_type = 1 + charge_type = "POSTPAID" mem_size = 1000 volume_size = 50 instance_name = "testAccMysql" @@ -424,6 +429,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { intranet_port = 3360 availability_zone = "ap-guangzhou-3" first_slave_zone = "ap-guangzhou-3" + force_delete = true tags = { test = "test-tf" role = "%s" @@ -435,7 +441,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { func testAccMysqlMasterInstance_update(instance_name, instranet_port string) string { tpl := ` resource "tencentcloud_mysql_instance" "mysql_master" { - pay_type = 1 + charge_type = "POSTPAID" mem_size = 1000 volume_size = 50 instance_name = "%s" @@ -444,6 +450,7 @@ resource "tencentcloud_mysql_instance" "mysql_master" { intranet_port = %s availability_zone = "ap-guangzhou-3" first_slave_zone = "ap-guangzhou-3" + force_delete = true }` return fmt.Sprintf(tpl, instance_name, instranet_port) } diff --git a/tencentcloud/resource_tc_redis_instance.go b/tencentcloud/resource_tc_redis_instance.go index 24afcb76d9..62f86c37ac 100644 --- a/tencentcloud/resource_tc_redis_instance.go +++ b/tencentcloud/resource_tc_redis_instance.go @@ -701,12 +701,26 @@ func resourceTencentCloudRedisInstanceUpdate(d *schema.ResourceData, meta interf } if d.HasChange("password") { - password := d.Get("password").(string) - taskId, err := redisService.ResetPassword(ctx, id, password) + var ( + taskId int64 + password = d.Get("password").(string) + err error + ) + + // After redis spec modified, reset password may not successfully response immediately. + err = resource.Retry(writeRetryTimeout, func() *resource.RetryError { + taskId, err = redisService.ResetPassword(ctx, id, password) + if err != nil { + log.Printf("[CRITAL]%s redis change password error, reason:%s\n", logId, err.Error()) + return retryError(err, redis.FAILEDOPERATION_SYSTEMERROR) + } + return nil + }) + if err != nil { - log.Printf("[CRITAL]%s redis change password error, reason:%s\n", logId, err.Error()) return err } + err = resource.Retry(2*readRetryTimeout, func() *resource.RetryError { ok, err := redisService.DescribeTaskInfo(ctx, id, taskId) if err != nil { diff --git a/tencentcloud/resource_tc_redis_instance_test.go b/tencentcloud/resource_tc_redis_instance_test.go index 4e17aa0bc2..8e825f9e8e 100644 --- a/tencentcloud/resource_tc_redis_instance_test.go +++ b/tencentcloud/resource_tc_redis_instance_test.go @@ -3,13 +3,141 @@ package tencentcloud import ( "context" "fmt" + "log" + "strings" "testing" "time" + sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" ) +func init() { + resource.AddTestSweepers("redis_instance", &resource.Sweeper{ + Name: "redis_instance", + F: func(region string) error { + logId := getLogId(contextNil) + ctx := context.WithValue(context.TODO(), logIdKey, logId) + cli, _ := sharedClientForRegion(region) + client := cli.(*TencentCloudClient).apiV3Conn + + service := RedisService{client: client} + + instances, err := service.DescribeInstances(ctx, "ap-guangzhou-3", "", 0, 0) + + if err != nil { + return err + } + + for _, v := range instances { + name := v.Name + id := v.RedisId + if !strings.HasPrefix(name, "terrform_test") { + continue + } + // Collect infos before deleting action + var chargeType string + errQuery := resource.Retry(20*readRetryTimeout, func() *resource.RetryError { + has, online, info, err := service.CheckRedisOnlineOk(ctx, id) + if err != nil { + log.Printf("[CRITAL]%s redis querying before deleting fail, reason:%s\n", logId, err.Error()) + return resource.NonRetryableError(err) + } + if !has { + return nil + } + if online { + chargeType = REDIS_CHARGE_TYPE_NAME[*info.BillingMode] + return nil + } else { + return resource.RetryableError(fmt.Errorf("Deleting ERROR: Creating redis task is processing.")) + } + }) + if errQuery != nil { + log.Printf("[CRITAL]%s redis querying before deleting task fail, reason:%s\n", logId, errQuery.Error()) + return errQuery + } + + var wait = func(action string, taskInfo interface{}) (errRet error) { + + errRet = resource.Retry(writeRetryTimeout, func() *resource.RetryError { + var ok bool + var err error + switch v := taskInfo.(type) { + case int64: + ok, err = service.DescribeTaskInfo(ctx, id, v) + case string: + ok, _, err = service.DescribeInstanceDealDetail(ctx, v) + } + if err != nil { + if _, ok := err.(*sdkErrors.TencentCloudSDKError); !ok { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(err) + } + } + if ok { + return nil + } else { + return resource.RetryableError(fmt.Errorf("%s timeout.", action)) + } + }) + + if errRet != nil { + log.Printf("[CRITAL]%s redis %s fail, reason:%s\n", logId, action, errRet.Error()) + } + return errRet + } + + if chargeType == REDIS_CHARGE_TYPE_POSTPAID { + taskId, err := service.DestroyPostpaidInstance(ctx, id) + if err != nil { + log.Printf("[CRITAL]%s redis %s fail, reason:%s\n", logId, "DestroyPostpaidInstance", err.Error()) + return err + } + if err = wait("DestroyPostpaidInstance", taskId); err != nil { + return err + } + + } else { + if _, err := service.DestroyPrepaidInstance(ctx, id); err != nil { + log.Printf("[CRITAL]%s redis %s fail, reason:%s\n", logId, "DestroyPrepaidInstance", err.Error()) + return err + } + + // Deal info only support create and renew and resize, need to check destroy status by describing api. + if errDestroyChecking := resource.Retry(20*readRetryTimeout, func() *resource.RetryError { + has, isolated, err := service.CheckRedisDestroyOk(ctx, id) + if err != nil { + log.Printf("[CRITAL]%s CheckRedisDestroyOk fail, reason:%s\n", logId, err.Error()) + return resource.NonRetryableError(err) + } + if !has || isolated { + return nil + } + return resource.RetryableError(fmt.Errorf("instance is not ready to be destroyed")) + }); errDestroyChecking != nil { + log.Printf("[CRITAL]%s redis querying before deleting task fail, reason:%s\n", logId, errDestroyChecking.Error()) + return errDestroyChecking + } + } + + taskId, err := service.CleanUpInstance(ctx, id) + if err != nil { + log.Printf("[CRITAL]%s redis %s fail, reason:%s\n", logId, "CleanUpInstance", err.Error()) + return err + } + + wait("CleanUpInstance", taskId) + } + + return nil + }, + }) +} + func TestAccTencentCloudRedisInstance(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ diff --git a/tencentcloud/service_tencentcloud_mysql.go b/tencentcloud/service_tencentcloud_mysql.go index 148f177615..9ab9a32381 100644 --- a/tencentcloud/service_tencentcloud_mysql.go +++ b/tencentcloud/service_tencentcloud_mysql.go @@ -945,8 +945,7 @@ func (me *MysqlService) InitDBInstances(ctx context.Context, mysqlId, password, } paramsMap := map[string]string{ - "character_set_server": "LATIN1", // ["utf8","latin1","gbk","utf8mb4"] - "lower_case_table_names": "1", // ["0","1"] + "character_set_server": "LATIN1", // ["utf8","latin1","gbk","utf8mb4"] } if charset != "" { @@ -957,7 +956,6 @@ func (me *MysqlService) InitDBInstances(ctx context.Context, mysqlId, password, paramsMap["lower_case_table_names"] = lowerCase // ["0","1"] } - request.Parameters = make([]*cdb.ParamInfo, 0, len(paramsMap)) for k, v := range paramsMap { name := k value := v