in alicloud/resource_alicloud_polardb_cluster.go [583:1480]
func resourceAlicloudPolarDBClusterUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
polarDBService := PolarDBService{client}
d.Partial(true)
if !d.IsNewResource() && (d.HasChange("default_time_zone") || d.HasChange("lower_case_table_names") || d.HasChange("loose_polar_log_bin") || d.HasChange("loose_xengine") || d.HasChange("loose_xengine_use_memory_pct")) {
if err := polarDBService.CreateClusterParamsModifyParameters(d); err != nil {
return WrapError(err)
}
}
if d.HasChange("parameters") {
if err := polarDBService.ModifyParameters(d); err != nil {
return WrapError(err)
}
d.SetPartial("parameters")
}
if err := polarDBService.setClusterTags(d); err != nil {
return WrapError(err)
}
var err error
payType := d.Get("pay_type").(string)
if !d.IsNewResource() && d.HasChange("pay_type") {
action := "TransformDBClusterPayType"
requestPayType := convertPolarDBPayTypeUpdateRequest(payType)
request := map[string]interface{}{
"RegionId": client.RegionId,
"DBClusterId": d.Id(),
"PayType": requestPayType,
}
if payType == string(PrePaid) {
period := d.Get("period").(int)
request["UsedTime"] = strconv.Itoa(period)
request["Period"] = Month
if period > 9 {
request["UsedTime"] = strconv.Itoa(period / 12)
request["Period"] = Year
}
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
//wait asynchronously cluster payType
if err := polarDBService.WaitForPolarDBPayType(d.Id(), requestPayType, DefaultTimeout); err != nil {
return WrapError(err)
}
if payType == string(PrePaid) {
d.SetPartial("period")
}
d.SetPartial("pay_type")
}
if (d.Get("pay_type").(string) == string(PrePaid)) &&
(d.HasChange("renewal_status") || d.HasChange("auto_renew_period")) {
status := d.Get("renewal_status").(string)
request := polardb.CreateModifyAutoRenewAttributeRequest()
request.DBClusterIds = d.Id()
request.RenewalStatus = status
if status == string(RenewAutoRenewal) {
period := d.Get("auto_renew_period").(int)
request.Duration = strconv.Itoa(period)
request.PeriodUnit = string(Month)
if period > 9 {
request.Duration = strconv.Itoa(period / 12)
request.PeriodUnit = string(Year)
}
}
//wait asynchronously cluster payType
if err := polarDBService.WaitForPolarDBPayType(d.Id(), "Prepaid", DefaultLongTimeout); err != nil {
return WrapError(err)
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
raw, err := client.WithPolarDBClient(func(polardbClient *polardb.Client) (interface{}, error) {
return polardbClient.ModifyAutoRenewAttribute(request)
})
if err != nil {
if IsExpectedErrors(err, []string{"-999"}) || NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
d.SetPartial("renewal_status")
d.SetPartial("auto_renew_period")
}
if d.HasChange("maintain_time") {
request := polardb.CreateModifyDBClusterMaintainTimeRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.MaintainTime = d.Get("maintain_time").(string)
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.ModifyDBClusterMaintainTime(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
d.SetPartial("maintain_time")
}
if !d.IsNewResource() && d.HasChanges("upgrade_type", "from_time_service", "planned_start_time", "planned_end_time", "target_db_revision_version_code") {
versionInfo, err := polarDBService.DescribeDBClusterVersion(d.Id())
if err != nil {
return WrapError(err)
}
var isLatestVersion = versionInfo["IsLatestVersion"].(string)
action := "UpgradeDBClusterVersion"
request := map[string]interface{}{
"DBClusterId": d.Id(),
}
if v, ok := d.GetOk("upgrade_type"); ok {
request["UpgradeType"] = v
}
if v, ok := d.GetOk("from_time_service"); ok {
fromTimeService, _ := strconv.ParseBool(v.(string))
request["FromTimeService"] = fromTimeService
}
if v, ok := d.GetOk("planned_start_time"); ok {
request["PlannedStartTime"] = v
}
if v, ok := d.GetOk("planned_end_time"); ok {
request["PlannedEndTime"] = v
}
if v, ok := d.GetOk("target_db_revision_version_code"); ok && isLatestVersion == "false" {
request["TargetDBRevisionVersionCode"] = v
}
wait := incrementalWait(3*time.Minute, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if IsExpectedErrors(err, []string{"TaskExists"}) || NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
fromTimeService := d.Get("from_time_service")
TargetDBRevisionVersionCode := d.Get("target_db_revision_version_code")
if strings.EqualFold(fromTimeService.(string), "true") || TargetDBRevisionVersionCode != "" {
// maxscale upgrade is relatively slow, wait cluster maxscale proxy status from MinorVersionUpgrading to running
proxyStatusConf := BuildStateConf([]string{"MinorVersionUpgrading"}, []string{"Running"},
d.Timeout(schema.TimeoutUpdate), 5*time.Minute, polarDBService.PolarDBClusterProxyStateRefreshFunc(d.Id(), []string{""}))
if _, err := proxyStatusConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
// wait cluster status change from ConfigSwitching to running
stateConf := BuildStateConf([]string{"MinorVersionUpgrading"}, []string{"Running"},
d.Timeout(schema.TimeoutUpdate), 5*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
}
d.SetPartial("upgrade_type")
d.SetPartial("from_time_service")
d.SetPartial("planned_start_time")
d.SetPartial("planned_end_time")
d.SetPartial("target_db_revision_version_code")
}
if d.HasChange("db_cluster_ip_array") {
if err := polarDBService.ModifyDBClusterAccessWhitelist(d); err != nil {
return WrapError(err)
}
d.SetPartial("db_cluster_ip_array")
}
if !d.IsNewResource() && d.HasChange("security_ips") {
ipList := expandStringList(d.Get("security_ips").(*schema.Set).List())
ipstr := strings.Join(ipList[:], COMMA_SEPARATED)
// default disable connect from outside
if ipstr == "" {
ipstr = LOCAL_HOST_IP
}
if err := polarDBService.ModifyDBSecurityIps(d.Id(), ipstr); err != nil {
return WrapError(err)
}
d.SetPartial("security_ips")
}
if v, ok := d.GetOk("creation_category"); !ok || v.(string) != "Basic" {
if d.HasChange("db_node_count") {
cluster, err := polarDBService.DescribePolarDBCluster(d.Id())
if err != nil {
return WrapError(err)
}
currentDbNodeCount := len(cluster.DBNodes.DBNode)
expectDbNodeCount := d.Get("db_node_count").(int)
if expectDbNodeCount > currentDbNodeCount {
//create node
expandDbNodes := &[]polardb.CreateDBNodesDBNode{
{
TargetClass: cluster.DBNodeClass,
},
}
request := polardb.CreateCreateDBNodesRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.DBNode = expandDbNodes
if v, ok := d.GetOk("imci_switch"); ok && v.(string) != "" {
request.ImciSwitch = v.(string)
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.CreateDBNodes(request)
})
if err != nil {
if IsExpectedErrors(err, []string{"OperationDenied.OrderProcessing"}) || NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
// wait cluster status change from DBNodeCreating to running
stateConf := BuildStateConf([]string{"DBNodeCreating"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
} else if expectDbNodeCount < currentDbNodeCount {
//delete node
deleteDbNodeId := ""
for _, dbNode := range cluster.DBNodes.DBNode {
if dbNode.DBNodeRole == "Reader" {
deleteDbNodeId = dbNode.DBNodeId
}
}
request := polardb.CreateDeleteDBNodesRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.DBNodeId = &[]string{
deleteDbNodeId,
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.DeleteDBNodes(request)
})
if err != nil {
if IsExpectedErrors(err, []string{"OperationDenied.OrderProcessing"}) || NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
stateConf := BuildStateConf([]string{"DBNodeDeleting"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err = stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
}
}
}
if d.HasChange("collector_status") {
request := polardb.CreateModifyDBClusterAuditLogCollectorRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.CollectorStatus = d.Get("collector_status").(string)
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.ModifyDBClusterAuditLogCollector(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
d.SetPartial("collector_status")
}
if v, ok := d.GetOk("db_type"); ok && v.(string) == "MySQL" {
if d.HasChange("tde_status") {
if v, ok := d.GetOk("tde_status"); ok && v.(string) != "Disabled" {
action := "ModifyDBClusterTDE"
request := map[string]interface{}{
"DBClusterId": d.Id(),
"TDEStatus": convertPolarDBTdeStatusUpdateRequest(v.(string)),
}
if s, ok := d.GetOk("encrypt_new_tables"); ok && s.(string) != "" {
request["EncryptNewTables"] = s.(string)
}
if v, ok := d.GetOk("encryption_key"); ok && v.(string) != "" {
request["EncryptionKey"] = v.(string)
}
if v, ok := d.GetOk("role_arn"); ok && v.(string) != "" {
request["RoleArn"] = v.(string)
}
//retry
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
//wait tde status 'Enabled'
stateConf := BuildStateConf([]string{}, []string{"Enabled"}, d.Timeout(schema.TimeoutUpdate), 3*time.Minute, polarDBService.PolarDBClusterTDEStateRefreshFunc(d.Id(), []string{}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("tde_status")
d.SetPartial("encrypt_new_tables")
d.SetPartial("encryption_key")
d.SetPartial("role_arn")
}
}
}
if d.HasChange("security_group_ids") {
securityGroupsList := expandStringList(d.Get("security_group_ids").(*schema.Set).List())
securityGroupsStr := strings.Join(securityGroupsList[:], COMMA_SEPARATED)
request := polardb.CreateModifyDBClusterAccessWhitelistRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.WhiteListType = "SecurityGroup"
request.SecurityGroupIds = securityGroupsStr
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.ModifyDBClusterAccessWhitelist(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
d.SetPartial("security_group_ids")
}
if d.HasChange("deletion_lock") {
if v, ok := d.GetOk("pay_type"); ok && v.(string) == string(PrePaid) {
return nil
}
action := "ModifyDBClusterDeletion"
protection := d.Get("deletion_lock").(int)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"Protection": protection == 1,
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
addDebug(action, response, request)
}
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidDBCluster.NotFound"}) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, ProviderERROR)
}
d.SetPartial("deletion_lock")
}
if d.HasChange("serverless_steady_switch") {
// Enable steady state
if d.HasChanges("scale_min", "scale_max", "scale_ro_num_min", "scale_ro_num_max", "scale_ap_ro_num_min", "scale_ap_ro_num_max") {
action := "EnableDBClusterServerless"
request := map[string]interface{}{
"DBClusterId": d.Id(),
}
scaleMin := d.Get("scale_min")
if scaleMin != nil {
request["ScaleMin"] = scaleMin
}
scaleMax := d.Get("scale_max")
if scaleMax != nil {
request["ScaleMax"] = scaleMax
}
scaleRoNumMin := d.Get("scale_ro_num_min")
if scaleRoNumMin != nil {
request["ScaleRoNumMin"] = scaleRoNumMin
}
scaleRoNumMax := d.Get("scale_ro_num_max")
if scaleRoNumMax != nil {
request["ScaleRoNumMax"] = scaleRoNumMax
}
clusterAttribute, err := polarDBService.DescribePolarDBClusterAttribute(d.Id())
if err != nil {
return WrapError(err)
}
imciParamterSwitch := false
for _, nodes := range clusterAttribute.DBNodes {
if nodes.ImciSwitch == "ON" {
imciParamterSwitch = true
}
}
if imciParamterSwitch {
ScaleApRoNumMin := d.Get("scale_ap_ro_num_min")
if ScaleApRoNumMin != nil {
scaleApRoNumMin := ScaleApRoNumMin.(int)
request["ScaleApRoNumMin"] = strconv.Itoa(scaleApRoNumMin)
}
ScaleApRoNumMax := d.Get("scale_ap_ro_num_max")
if ScaleApRoNumMax != nil {
scaleApRoNumMax := ScaleApRoNumMax.(int)
request["ScaleApRoNumMax"] = strconv.Itoa(scaleApRoNumMax)
}
}
//retry
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) || IsExpectedErrors(err, []string{"TaskExists"}) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait cluster status change from ConfigSwitching to running
stateConf := BuildStateConf([]string{"ConfigSwitching", "Maintaining"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 8*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("scale_min")
d.SetPartial("scale_max")
d.SetPartial("scale_ro_num_min")
d.SetPartial("scale_ro_num_max")
d.SetPartial("scale_ap_ro_num_min")
d.SetPartial("scale_ap_ro_num_max")
}
// Turn off steady state
if u, ok := d.GetOk("serverless_steady_switch"); ok {
switchValue := u.(string)
cluster, err := polarDBService.DescribePolarDBCluster(d.Id())
if err != nil {
return WrapError(err)
}
if switchValue == "OFF" && "SteadyServerless" == cluster.ServerlessType {
action := "DisableDBClusterServerless"
request := map[string]interface{}{
"DBClusterId": d.Id(),
}
//retry
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait cluster status change from ConfigSwitching to running
stateConf := BuildStateConf([]string{"ConfigSwitching", "Maintaining"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 8*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
}
}
}
if d.HasChange("compress_storage") {
action := "ModifyDBCluster"
compressStorage := d.Get("compress_storage").(string)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"CompressStorage": compressStorage,
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
addDebug(action, response, request)
}
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidDBCluster.NotFound"}) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, ProviderERROR)
}
// wait cluster status change from StorageExpanding to running
stateConf := BuildStateConf([]string{"ConfigSwitching"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 4*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("compress_storage")
}
if d.IsNewResource() {
d.Partial(false)
return resourceAlicloudPolarDBClusterRead(d, meta)
}
if v, ok := d.GetOk("creation_category"); !ok || v.(string) != "Basic" {
if d.HasChange("db_node_class") {
request := polardb.CreateModifyDBNodeClassRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.ModifyType = d.Get("modify_type").(string)
request.DBNodeTargetClass = d.Get("db_node_class").(string)
if v, ok := d.GetOk("sub_category"); ok && v.(string) != "" {
request.SubCategory = convertPolarDBSubCategoryUpdateRequest(v.(string))
}
//wait asynchronously cluster nodes num the same
if err := polarDBService.WaitForPolarDBNodeClass(d.Id(), DefaultLongTimeout); err != nil {
return WrapError(err)
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutUpdate)), func() *resource.RetryError {
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.ModifyDBNodeClass(request)
})
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
if err != nil {
if NeedRetry(err) || IsExpectedErrors(err, []string{"InternalError"}) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
// wait cluster status change from Creating to running
stateConf := BuildStateConf([]string{"ClassChanging", "ClassChanged"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{"Deleting"}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("db_node_class")
}
}
if d.HasChange("description") {
request := polardb.CreateModifyDBClusterDescriptionRequest()
request.RegionId = client.RegionId
request.DBClusterId = d.Id()
request.DBClusterDescription = d.Get("description").(string)
raw, err := client.WithPolarDBClient(func(polarDBClient *polardb.Client) (interface{}, error) {
return polarDBClient.ModifyDBClusterDescription(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
d.SetPartial("description")
}
if !d.IsNewResource() && d.HasChanges("scale_min", "scale_max", "allow_shut_down", "scale_ro_num_min", "scale_ro_num_max", "seconds_until_auto_pause", "scale_ap_ro_num_min", "scale_ap_ro_num_max") {
action := "ModifyDBClusterServerlessConf"
request := map[string]interface{}{
"DBClusterId": d.Id(),
}
scaleMin := d.Get("scale_min")
if scaleMin != nil {
request["ScaleMin"] = scaleMin
}
scaleMax := d.Get("scale_max")
if scaleMax != nil {
request["ScaleMax"] = scaleMax
}
scaleRoNumMin := d.Get("scale_ro_num_min")
if scaleRoNumMin != nil {
request["ScaleRoNumMin"] = scaleRoNumMin
}
scaleRoNumMax := d.Get("scale_ro_num_max")
if scaleRoNumMax != nil {
request["ScaleRoNumMax"] = scaleRoNumMax
}
if v, ok := d.GetOk("allow_shut_down"); ok && v.(string) != "" {
request["AllowShutDown"] = v.(string)
}
if v, ok := d.GetOk("seconds_until_auto_pause"); ok {
secondsUntilAutoPause := v.(int)
request["SecondsUntilAutoPause"] = strconv.Itoa(secondsUntilAutoPause)
}
clusterAttribute, err := polarDBService.DescribePolarDBClusterAttribute(d.Id())
if err != nil {
return WrapError(err)
}
imciParamterSwitch := false
for _, nodes := range clusterAttribute.DBNodes {
if nodes.ImciSwitch == "ON" {
imciParamterSwitch = true
}
}
if imciParamterSwitch {
if v, ok := d.GetOk("scale_ap_ro_num_min"); ok {
scaleApRoNumMin := v.(int)
request["ScaleApRoNumMin"] = strconv.Itoa(scaleApRoNumMin)
}
if v, ok := d.GetOk("scale_ap_ro_num_max"); ok {
scaleApRoNumMax := v.(int)
request["ScaleApRoNumMax"] = strconv.Itoa(scaleApRoNumMax)
}
}
//retry
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait cluster status change from ConfigSwitching to running
stateConf := BuildStateConf([]string{"ConfigSwitching", "Stopped", "STARTING"}, []string{"Running"}, d.Timeout(schema.TimeoutCreate), 5*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("scale_min")
d.SetPartial("scale_max")
d.SetPartial("scale_ro_num_min")
d.SetPartial("scale_ro_num_max")
d.SetPartial("allow_shut_down")
d.SetPartial("seconds_until_auto_pause")
}
if !d.IsNewResource() && d.HasChange("storage_type") {
action := "ModifyDBClusterStoragePerformance"
storageType := d.Get("storage_type").(string)
modifyType := d.Get("modify_type").(string)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"StorageType": storageType,
"ModifyType": modifyType,
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
addDebug(action, response, request)
}
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait cluster status change from ClassChanging/ConfigSwitching to running
stateConf := BuildStateConf([]string{"ClassChanging", "ConfigSwitching"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 4*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("storage_type")
}
if !d.IsNewResource() && d.HasChange("provisioned_iops") {
action := "ModifyDBClusterStoragePerformance"
storageType := d.Get("storage_type").(string)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"StorageType": storageType,
}
if v, ok := d.GetOk("provisioned_iops"); ok && v.(string) != "" {
request["ProvisionedIops"] = v
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
addDebug(action, response, request)
}
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait cluster status change from ClassChanging/ConfigSwitching to running
stateConf := BuildStateConf([]string{"ClassChanging", "ConfigSwitching"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 4*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("provisioned_iops")
}
if d.HasChange("storage_space") {
action := "ModifyDBClusterStorageSpace"
storageSpace := d.Get("storage_space").(int)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"StorageSpace": storageSpace,
}
if v, ok := d.GetOk("planned_start_time"); ok && v.(string) != "" {
request["PlannedStartTime"] = v
}
if v, ok := d.GetOk("planned_end_time"); ok && v.(string) != "" {
request["PlannedEndTime"] = v
}
if v, ok := d.GetOk("sub_category"); ok && v.(string) != "" {
request["SubCategory"] = convertPolarDBSubCategoryUpdateRequest(v.(string))
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
addDebug(action, response, request)
}
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidDBCluster.NotFound"}) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, ProviderERROR)
}
// wait cluster status change from StorageExpanding to running
stateConf := BuildStateConf([]string{"StorageExpanding"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 4*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("storage_space")
}
if d.HasChange("hot_replica_mode") {
dbNodeIdIndex := ""
if v, ok := d.GetOk("db_node_id"); ok && v.(string) != "" {
if len(v.(string)) > 2 {
dbNodeIdIndex = v.(string)
} else {
clusterAttribute, err := polarDBService.DescribePolarDBClusterAttribute(d.Id())
if err != nil {
return WrapError(err)
}
index := formatInt(v)
dbNodeIdIndex = clusterAttribute.DBNodes[index].DBNodeId
}
}
if v, ok := d.GetOk("db_type"); ok && v.(string) == "MySQL" {
action := "ModifyDBNodeHotReplicaMode"
hotReplicaMode := d.Get("hot_replica_mode").(string)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"HotReplicaMode": hotReplicaMode,
"DBNodeId": dbNodeIdIndex,
}
//retry
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
//wait tde status 'Running'
stateConf := BuildStateConf([]string{"RoleSwitching"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 5*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("hot_replica_mode")
d.SetPartial("db_node_id")
}
}
if !d.IsNewResource() && d.HasChange("standby_az") {
action := "ModifyDBClusterPrimaryZone"
standby_az := d.Get("standby_az").(string)
request := map[string]interface{}{
"DBClusterId": d.Id(),
"ZoneId": standby_az,
"ZoneType": "Standby",
}
wait := incrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError {
response, err := client.RpcPost("polardb", "2017-08-01", action, nil, request, false)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
addDebug(action, response, request)
}
return nil
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
}
// wait cluster status change from ClassChanging/ConfigSwitching to running
stateConf := BuildStateConf([]string{"StandbyTransing"}, []string{"Running"}, d.Timeout(schema.TimeoutUpdate), 4*time.Minute, polarDBService.PolarDBClusterStateRefreshFunc(d.Id(), []string{""}))
if _, err := stateConf.WaitForState(); err != nil {
return WrapErrorf(err, IdMsg, d.Id())
}
d.SetPartial("standby_az")
}
d.Partial(false)
return resourceAlicloudPolarDBClusterRead(d, meta)
}