alibabacloudstack/service_apsarastack_rds.go (1,329 lines of code) (raw):

package alibabacloudstack import ( "encoding/json" "fmt" "log" "regexp" "strconv" "strings" "time" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/alibaba-cloud-sdk-go/services/rds" "github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/connectivity" "github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/errmsgs" "github.com/denverdino/aliyungo/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) type RdsService struct { client *connectivity.AlibabacloudStackClient } // _______________ _______________ _______________ // | | ______param______\ | | _____request_____\ | | // | Business | | Service | | SDK/API | // | | __________________ | | __________________ | | // |______________| \ (obj, err) |______________| \ (status, cont) |______________| // | | // |A. {instance, nil} |a. {200, content} // |B. {nil, error} |b. {200, nil} // |c. {4xx, nil} // // The API return 200 for resource not found. // When getInstance is empty, then throw InstanceNotfound error. // That the business layer only need to check error. var DBInstanceStatusCatcher = Catcher{"OperationDenied.DBInstanceStatus", 60, 5} func (s *RdsService) DescribeDBInstance(id string) (*rds.DBInstanceAttribute, error) { instance := &rds.DBInstanceAttribute{} request := rds.CreateDescribeDBInstanceAttributeRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDBInstanceAttribute(request) }) response, ok := raw.(*rds.DescribeDBInstanceAttributeResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return instance, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return instance, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if len(response.Items.DBInstanceAttribute) < 1 { return instance, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBInstance", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } return &response.Items.DBInstanceAttribute[0], nil } func (s *RdsService) DescribeTasks(id string) (task *rds.DescribeTasksResponse, err error) { request := rds.CreateDescribeTasksRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeTasks(request) }) response, ok := raw.(*rds.DescribeTasksResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return task, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return task, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return response, nil } func (s *RdsService) DescribeDBReadonlyInstance(id string) (*rds.DBInstanceAttribute, error) { instance := &rds.DBInstanceAttribute{} request := rds.CreateDescribeDBInstanceAttributeRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDBInstanceAttribute(request) }) response, ok := raw.(*rds.DescribeDBInstanceAttributeResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return instance, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return instance, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if len(response.Items.DBInstanceAttribute) < 1 { return instance, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBInstance", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } return &response.Items.DBInstanceAttribute[0], nil } func (s *RdsService) DoRdsDescribeaccountsRequest(id string) (*rds.DBInstanceAccount, error) { return s.DescribeDBAccount(id) } func (s *RdsService) DescribeDBAccount(id string) (*rds.DBInstanceAccount, error) { ds := &rds.DBInstanceAccount{} parts, err := ParseResourceId(id, 2) if err != nil { return ds, errmsgs.WrapError(err) } request := rds.CreateDescribeAccountsRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = parts[0] request.AccountName = parts[1] invoker := NewInvoker() invoker.AddCatcher(DBInstanceStatusCatcher) var raw interface{} err = invoker.Run(func() error { raw, err = s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeAccounts(request) }) if err != nil { return err } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) response, ok := raw.(*rds.DescribeAccountsResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return ds, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return ds, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } if len(response.Accounts.DBInstanceAccount) < 1 { return ds, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBAccount", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } return &response.Accounts.DBInstanceAccount[0], nil } func (s *RdsService) DescribeDBAccountPrivilege(id string) (*rds.DBInstanceAccount, error) { ds := &rds.DBInstanceAccount{} parts, err := ParseResourceId(id, 3) if err != nil { return ds, errmsgs.WrapError(err) } request := rds.CreateDescribeAccountsRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = parts[0] request.AccountName = parts[1] invoker := NewInvoker() invoker.AddCatcher(DBInstanceStatusCatcher) var raw interface{} err = invoker.Run(func() error { raw, err = s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeAccounts(request) }) if err != nil { return err } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) response, ok := raw.(*rds.DescribeAccountsResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return ds, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return ds, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } if len(response.Accounts.DBInstanceAccount) < 1 { return ds, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBAccountPrivilege", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } return &response.Accounts.DBInstanceAccount[0], nil } func (s *RdsService) DoRdsDescribedatabasesRequest(id string) (*rds.Database, error) { return s.DescribeDBDatabase(id) } func (s *RdsService) DescribeDBDatabase(id string) (*rds.Database, error) { ds := &rds.Database{} parts, err := ParseResourceId(id, 2) if err != nil { return ds, errmsgs.WrapError(err) } dbName := parts[1] request := rds.CreateDescribeDatabasesRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = parts[0] request.DBName = dbName err = resource.Retry(30*time.Minute, func() *resource.RetryError { raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDatabases(request) }) response, ok := raw.(*rds.DescribeDatabasesResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InternalError", "OperationDenied.DBInstanceStatus"}) { return resource.RetryableError(errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR)) } if errmsgs.NotFoundError(err) || errmsgs.IsExpectedErrors(err, []string{"InvalidDBName.NotFound"}) { return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR)) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if len(response.Databases.Database) < 1 { return resource.NonRetryableError(errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBDatabase", dbName)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR)) } ds = &response.Databases.Database[0] return nil }) return ds, err } func (s *RdsService) DescribeParameters(id string) (*rds.DescribeParametersResponse, error) { ds := &rds.DescribeParametersResponse{} request := rds.CreateDescribeParametersRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeParameters(request) }) response, ok := raw.(*rds.DescribeParametersResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return ds, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return ds, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return response, err } func (s *RdsService) RefreshParameters(d *schema.ResourceData, attribute string) error { var param []map[string]interface{} documented, ok := d.GetOk(attribute) if !ok { d.Set(attribute, param) return nil } object, err := s.DescribeParameters(d.Id()) if err != nil { return errmsgs.WrapError(err) } var parameters = make(map[string]interface{}) for _, i := range object.RunningParameters.DBInstanceParameter { if i.ParameterName != "" { parameter := map[string]interface{}{ "name": i.ParameterName, "value": i.ParameterValue, } parameters[i.ParameterName] = parameter } } for _, i := range object.ConfigParameters.DBInstanceParameter { if i.ParameterName != "" { parameter := map[string]interface{}{ "name": i.ParameterName, "value": i.ParameterValue, } parameters[i.ParameterName] = parameter } } for _, parameter := range documented.(*schema.Set).List() { name := parameter.(map[string]interface{})["name"] for _, value := range parameters { if value.(map[string]interface{})["name"] == name { param = append(param, value.(map[string]interface{})) break } } } if err := d.Set(attribute, param); err != nil { return errmsgs.WrapError(err) } return nil } func (s *RdsService) ModifyParameters(d *schema.ResourceData, attribute string) error { request := rds.CreateModifyParameterRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = d.Id() request.Forcerestart = requests.NewBoolean(d.Get("force_restart").(bool)) config := make(map[string]string) allConfig := make(map[string]string) o, n := d.GetChange(attribute) os, ns := o.(*schema.Set), n.(*schema.Set) add := ns.Difference(os).List() if len(add) > 0 { for _, i := range add { key := i.(map[string]interface{})["name"].(string) value := i.(map[string]interface{})["value"].(string) config[key] = value } cfg, _ := json.Marshal(config) request.Parameters = string(cfg) // wait instance status is Normal before modifying if err := s.WaitForDBInstance(d.Id(), Running, DefaultLongTimeout); err != nil { return errmsgs.WrapError(err) } // Need to check whether some parameter needs restart if !d.Get("force_restart").(bool) { req := rds.CreateDescribeParameterTemplatesRequest() s.client.InitRpcRequest(*req.RpcRequest) req.DBInstanceId = d.Id() req.Engine = d.Get("engine").(string) req.EngineVersion = d.Get("engine_version").(string) req.ClientToken = buildClientToken(req.GetActionName()) forceRestartMap := make(map[string]string) raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeParameterTemplates(req) }) response, ok := raw.(*rds.DescribeParameterTemplatesResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } for _, para := range response.Parameters.TemplateRecord { if para.ForceRestart == "true" { forceRestartMap[para.ParameterName] = para.ForceRestart } } if len(forceRestartMap) > 0 { for key, _ := range config { if _, ok := forceRestartMap[key]; ok { return errmsgs.WrapError(fmt.Errorf("Modifying RDS instance's parameter '%s' requires setting 'force_restart = true'.", key)) } } } } raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ModifyParameter(request) }) response, ok := raw.(*rds.ModifyParameterResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) // wait instance parameter expect after modifying for _, i := range ns.List() { key := i.(map[string]interface{})["name"].(string) value := i.(map[string]interface{})["value"].(string) allConfig[key] = value } if err := s.WaitForDBParameter(d.Id(), DefaultTimeoutMedium, allConfig); err != nil { return errmsgs.WrapError(err) } } //d.SetPartial(attribute) return nil } func (s *RdsService) DescribeDBInstanceNetInfo(id string) ([]rds.DBInstanceNetInfo, error) { request := rds.CreateDescribeDBInstanceNetInfoRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDBInstanceNetInfo(request) }) response, ok := raw.(*rds.DescribeDBInstanceNetInfoResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return nil, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return nil, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if len(response.DBInstanceNetInfos.DBInstanceNetInfo) < 1 { return nil, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBInstanceNetInfo", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } return response.DBInstanceNetInfos.DBInstanceNetInfo, nil } func (s *RdsService) DescribeDBConnection(id string) (*rds.DBInstanceNetInfo, error) { info := &rds.DBInstanceNetInfo{} parts, err := ParseResourceId(id, 2) if err != nil { return info, errmsgs.WrapError(err) } object, err := s.DescribeDBInstanceNetInfo(parts[0]) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidCurrentConnectionString.NotFound"}) { return info, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } return info, errmsgs.WrapError(err) } if object != nil { for _, o := range object { if strings.HasPrefix(o.ConnectionString, parts[1]) { return &o, nil } } } return info, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("DBConnection", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } func (s *RdsService) DescribeDBReadWriteSplittingConnection(id string) (*rds.DBInstanceNetInfo, error) { ds := &rds.DBInstanceNetInfo{} object, err := s.DescribeDBInstanceNetInfo(id) if err != nil && !errmsgs.NotFoundError(err) { return ds, err } if object != nil { for _, conn := range object { if conn.ConnectionStringType != "ReadWriteSplitting" { continue } if conn.MaxDelayTime == "" { continue } if _, err := strconv.Atoi(conn.MaxDelayTime); err != nil { return ds, err } return &conn, nil } } return ds, errmsgs.WrapErrorf(errmsgs.Error(errmsgs.GetNotFoundMessage("ReadWriteSplittingConnection", id)), errmsgs.NotFoundMsg, errmsgs.ProviderERROR) } func (s *RdsService) GrantAccountPrivilege(id, dbName string) error { parts, err := ParseResourceId(id, 3) if err != nil { return errmsgs.WrapError(err) } request := rds.CreateGrantAccountPrivilegeRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = parts[0] request.AccountName = parts[1] request.DBName = dbName request.AccountPrivilege = parts[2] err = resource.Retry(3*time.Minute, func() *resource.RetryError { raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.GrantAccountPrivilege(request) }) response, ok := raw.(*rds.GrantAccountPrivilegeResponse) if err != nil { if errmsgs.IsExpectedErrors(err, errmsgs.OperationDeniedDBStatus) { return resource.RetryableError(err) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) if err != nil { return errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR) } if err := s.WaitForAccountPrivilege(id, dbName, Available, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } return nil } func (s *RdsService) RevokeAccountPrivilege(id, dbName string) error { parts, err := ParseResourceId(id, 3) if err != nil { return errmsgs.WrapError(err) } request := rds.CreateRevokeAccountPrivilegeRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = parts[0] request.AccountName = parts[1] request.DBName = dbName err = resource.Retry(3*time.Minute, func() *resource.RetryError { raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.RevokeAccountPrivilege(request) }) response, ok := raw.(*rds.RevokeAccountPrivilegeResponse) if err != nil { if errmsgs.IsExpectedErrors(err, errmsgs.OperationDeniedDBStatus) { return resource.RetryableError(err) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) if err != nil { return errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR) } if err := s.WaitForAccountPrivilegeRevoked(id, dbName, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } return nil } func (s *RdsService) ReleaseDBPublicConnection(instanceId, connection string) error { request := rds.CreateReleaseInstancePublicConnectionRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = instanceId request.CurrentConnectionString = connection raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ReleaseInstancePublicConnection(request) }) response, ok := raw.(*rds.ReleaseInstancePublicConnectionResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, instanceId, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil } func (s *RdsService) ModifyDBBackupPolicy(d *schema.ResourceData, updateForData, updateForLog bool) error { enableBackupLog := "1" backupPeriod := "" if v, ok := d.GetOk("preferred_backup_period"); ok && v.(*schema.Set).Len() > 0 { periodList := expandStringList(v.(*schema.Set).List()) backupPeriod = fmt.Sprintf("%s", strings.Join(periodList[:], COMMA_SEPARATED)) } backupTime := "02:00Z-03:00Z" if v, ok := d.GetOk("preferred_backup_time"); ok && v.(string) != "02:00Z-03:00Z" { backupTime = v.(string) } retentionPeriod := "7" if v, ok := d.GetOk("backup_retention_period"); ok && v.(int) != 7 { retentionPeriod = strconv.Itoa(v.(int)) } logBackupRetentionPeriod := "" if v, ok := d.GetOk("log_backup_retention_period"); ok && v.(int) != 0 { logBackupRetentionPeriod = strconv.Itoa(v.(int)) } localLogRetentionHours := "" if v, ok := d.GetOk("local_log_retention_hours"); ok { localLogRetentionHours = strconv.Itoa(v.(int)) } localLogRetentionSpace := "" if v, ok := d.GetOk("local_log_retention_space"); ok { localLogRetentionSpace = strconv.Itoa(v.(int)) } highSpaceUsageProtection := d.Get("high_space_usage_protection").(string) if !d.Get("enable_backup_log").(bool) { enableBackupLog = "0" } if d.HasChange("log_backup_retention_period") { if d.Get("log_backup_retention_period").(int) > d.Get("backup_retention_period").(int) { logBackupRetentionPeriod = retentionPeriod } } logBackupFrequency := "" if v, ok := d.GetOk("log_backup_frequency"); ok { logBackupFrequency = v.(string) } compressType := "" if v, ok := d.GetOk("compress_type"); ok { compressType = v.(string) } archiveBackupRetentionPeriod := "0" if v, ok := d.GetOk("archive_backup_retention_period"); ok { archiveBackupRetentionPeriod = strconv.Itoa(v.(int)) } archiveBackupKeepCount := 1 if v, ok := d.GetOk("archive_backup_keep_count"); ok { archiveBackupKeepCount = v.(int) } archiveBackupKeepPolicy := "0" if v, ok := d.GetOk("archive_backup_keep_policy"); ok { archiveBackupKeepPolicy = v.(string) } instance, err := s.DescribeDBInstance(d.Id()) if err != nil { return errmsgs.WrapError(err) } if updateForData { request := rds.CreateModifyBackupPolicyRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = d.Id() request.PreferredBackupPeriod = backupPeriod request.PreferredBackupTime = backupTime request.BackupRetentionPeriod = retentionPeriod request.CompressType = compressType request.BackupPolicyMode = "DataBackupPolicy" if instance.Engine == "SQLServer" && logBackupFrequency == "LogInterval" { request.LogBackupFrequency = logBackupFrequency } if instance.Engine == "MySQL" && instance.DBInstanceStorageType == "local_ssd" { request.ArchiveBackupRetentionPeriod = archiveBackupRetentionPeriod request.ArchiveBackupKeepCount = requests.NewInteger(archiveBackupKeepCount) request.ArchiveBackupKeepPolicy = archiveBackupKeepPolicy } raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ModifyBackupPolicy(request) }) response, ok := raw.(*rds.ModifyBackupPolicyResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if err := s.WaitForDBInstance(d.Id(), Running, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } } // At present, the sql server database does not support setting logBackupRetentionPeriod if updateForLog && instance.Engine != "SQLServer" { request := rds.CreateModifyBackupPolicyRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = d.Id() request.EnableBackupLog = enableBackupLog request.LocalLogRetentionHours = localLogRetentionHours request.LocalLogRetentionSpace = localLogRetentionSpace request.HighSpaceUsageProtection = highSpaceUsageProtection request.BackupPolicyMode = "LogBackupPolicy" request.LogBackupRetentionPeriod = logBackupRetentionPeriod raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ModifyBackupPolicy(request) }) response, ok := raw.(*rds.ModifyBackupPolicyResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if err := s.WaitForDBInstance(d.Id(), Running, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } } return nil } func (s *RdsService) ModifyDBSecurityIps(instanceId, ips string) error { request := rds.CreateModifySecurityIpsRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = instanceId request.SecurityIps = ips raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ModifySecurityIps(request) }) response, ok := raw.(*rds.ModifySecurityIpsResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, instanceId, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) if err := s.WaitForDBInstance(instanceId, Running, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } return nil } func (s *RdsService) DescribeDBSecurityIps(instanceId string) (ips []rds.DBInstanceIPArray, err error) { request := rds.CreateDescribeDBInstanceIPArrayListRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = instanceId raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDBInstanceIPArrayList(request) }) resp, ok := raw.(*rds.DescribeDBInstanceIPArrayListResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(resp.BaseResponse) } return nil, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, instanceId, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return resp.Items.DBInstanceIPArray, nil } func (s *RdsService) GetSecurityIps(instanceId string) ([]string, error) { object, err := s.DescribeDBSecurityIps(instanceId) if err != nil { return nil, errmsgs.WrapError(err) } var ips, separator string ipsMap := make(map[string]string) for _, ip := range object { if ip.DBInstanceIPArrayAttribute == "hidden" { continue } ips += separator + ip.SecurityIPList separator = COMMA_SEPARATED } for _, ip := range strings.Split(ips, COMMA_SEPARATED) { ipsMap[ip] = ip } var finalIps []string if len(ipsMap) > 0 { for key := range ipsMap { finalIps = append(finalIps, key) } } return finalIps, nil } func (s *RdsService) DescribeSecurityGroupConfiguration(id string) ([]string, error) { request := rds.CreateDescribeSecurityGroupConfigurationRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeSecurityGroupConfiguration(request) }) response, ok := raw.(*rds.DescribeSecurityGroupConfigurationResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return nil, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) groupIds := make([]string, 0) for _, v := range response.Items.EcsSecurityGroupRelation { groupIds = append(groupIds, v.SecurityGroupId) } return groupIds, nil } func (s *RdsService) DescribeDBInstanceSSL(id string) (*rds.DescribeDBInstanceSSLResponse, error) { response := &rds.DescribeDBInstanceSSLResponse{} request := rds.CreateDescribeDBInstanceSSLRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDBInstanceSSL(request) }) response, ok := raw.(*rds.DescribeDBInstanceSSLResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return response, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return response, nil } func (s *RdsService) DescribeRdsTDEInfo(id string) (*rds.DescribeDBInstanceTDEResponse, error) { response := &rds.DescribeDBInstanceTDEResponse{} request := rds.CreateDescribeDBInstanceTDERequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id statErr := s.WaitForDBInstance(id, Running, DefaultLongTimeout) if statErr != nil { return response, errmsgs.WrapError(statErr) } raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeDBInstanceTDE(request) }) response, ok := raw.(*rds.DescribeDBInstanceTDEResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return response, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return response, nil } func (s *RdsService) ModifySecurityGroupConfiguration(id string, groupid string) error { request := rds.CreateModifySecurityGroupConfigurationRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id // openapi required that input "Empty" if groupid is "" if len(groupid) == 0 { groupid = "Empty" } request.SecurityGroupId = groupid raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ModifySecurityGroupConfiguration(request) }) response, ok := raw.(*rds.ModifySecurityGroupConfigurationResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil } // return multiIZ list of current region func (s *RdsService) DescribeMultiIZByRegion() (izs []string, err error) { request := rds.CreateDescribeRegionsRequest() s.client.InitRpcRequest(*request.RpcRequest) request.RegionId = s.client.RegionId raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeRegions(request) }) response, ok := raw.(*rds.DescribeRegionsResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return nil, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "DescribeMultiIZByRegion", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) regions := response.Regions.RDSRegion zoneIds := []string{} for _, r := range regions { if r.RegionId == string(s.client.Region) && strings.Contains(r.ZoneId, MULTI_IZ_SYMBOL) { zoneIds = append(zoneIds, r.ZoneId) } } return zoneIds, nil } func (s *RdsService) DescribeBackupPolicy(id string) (*rds.DescribeBackupPolicyResponse, error) { policy := &rds.DescribeBackupPolicyResponse{} request := rds.CreateDescribeBackupPolicyRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeBackupPolicy(request) }) response, ok := raw.(*rds.DescribeBackupPolicyResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return policy, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return nil, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "DescribeMultiIZByRegion", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return raw.(*rds.DescribeBackupPolicyResponse), nil } func (s *RdsService) DescribeDbInstanceMonitor(id string) (monitoringPeriod int, err error) { request := rds.CreateDescribeDBInstanceMonitorRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(client *rds.Client) (interface{}, error) { return client.DescribeDBInstanceMonitor(request) }) response, ok := raw.(*rds.DescribeDBInstanceMonitorResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return 0, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) monPeriod, err := strconv.Atoi(response.Period) if err != nil { return 0, errmsgs.WrapError(err) } return monPeriod, nil } func (s *RdsService) DescribeSQLCollectorPolicy(id string) (collectorPolicy *rds.DescribeSQLCollectorPolicyResponse, err error) { request := rds.CreateDescribeSQLCollectorPolicyRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeSQLCollectorPolicy(request) }) response, ok := raw.(*rds.DescribeSQLCollectorPolicyResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return collectorPolicy, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return response, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return response, nil } func (s *RdsService) DescribeSQLCollectorRetention(id string) (collectorRetention *rds.DescribeSQLCollectorRetentionResponse, err error) { request := rds.CreateDescribeSQLCollectorRetentionRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = id raw, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DescribeSQLCollectorRetention(request) }) response, ok := raw.(*rds.DescribeSQLCollectorRetentionResponse) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"InvalidDBInstanceId.NotFound"}) { return collectorRetention, errmsgs.WrapErrorf(err, errmsgs.NotFoundMsg, errmsgs.AlibabacloudStackSdkGoERROR) } errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return response, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return response, nil } // WaitForInstance waits for instance to given status func (s *RdsService) WaitForDBInstance(id string, status Status, timeout int) error { deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBInstance(id) if err != nil { if errmsgs.NotFoundError(err) { if status == Deleted { return nil } } else { return errmsgs.WrapError(err) } } if object != nil && strings.ToLower(object.DBInstanceStatus) == strings.ToLower(string(status)) { break } time.Sleep(DefaultIntervalShort * time.Second) if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, object.DBInstanceStatus, status, errmsgs.ProviderERROR) } } return nil } func (s *RdsService) RdsDBInstanceStateRefreshFunc(id string, failStates []string) resource.StateRefreshFunc { return func() (interface{}, string, error) { object, err := s.DescribeDBInstance(id) if err != nil { if errmsgs.NotFoundError(err) { // Set this to nil as if we didn't find anything. return nil, "", nil } return nil, "", errmsgs.WrapError(err) } for _, failState := range failStates { if object.DBInstanceStatus == failState { return object, object.DBInstanceStatus, errmsgs.WrapError(errmsgs.Error(errmsgs.FailedToReachTargetStatus, object.DBInstanceStatus)) } } return object, object.DBInstanceStatus, nil } } func (s *RdsService) RdsTaskStateRefreshFunc(id string, taskAction string) resource.StateRefreshFunc { return func() (interface{}, string, error) { object, err := s.DescribeTasks(id) if err != nil { if errmsgs.NotFoundError(err) { // Set this to nil as if we didn't find anything. return nil, "", nil } return nil, "", errmsgs.WrapError(err) } for _, t := range object.Items.TaskProgressInfo { if t.TaskAction == taskAction { return object, t.Status, nil } } return object, "Pending", nil } } // WaitForDBParameter waits for instance parameter to given value. // Status of DB instance is Running after ModifyParameters API was // call, so we can not just wait for instance status become // Running, we should wait until parameters have expected values. func (s *RdsService) WaitForDBParameter(instanceId string, timeout int, expects map[string]string) error { deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeParameters(instanceId) if err != nil { return errmsgs.WrapError(err) } var actuals = make(map[string]string) for _, i := range object.RunningParameters.DBInstanceParameter { actuals[i.ParameterName] = i.ParameterValue } for _, i := range object.ConfigParameters.DBInstanceParameter { actuals[i.ParameterName] = i.ParameterValue } match := true got_value := "" expected_value := "" for name, expect := range expects { if actual, ok := actuals[name]; ok { if expect != actual { match = false got_value = actual expected_value = expect break } } else { match = false } } if match { break } time.Sleep(DefaultIntervalShort * time.Second) if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, instanceId, GetFunc(1), timeout, got_value, expected_value, errmsgs.ProviderERROR) } } return nil } func (s *RdsService) WaitForDBConnection(id string, status Status, timeout int) error { deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBConnection(id) if err != nil { if errmsgs.NotFoundError(err) { if status == Deleted { return nil } } else { return errmsgs.WrapError(err) } } if object != nil && object.ConnectionString != "" { return nil } if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, object.ConnectionString, id, errmsgs.ProviderERROR) } } } func (s *RdsService) WaitForDBReadWriteSplitting(id string, status Status, timeout int) error { deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBReadWriteSplittingConnection(id) if err != nil { if errmsgs.NotFoundError(err) { if status == Deleted { return nil } } else { return errmsgs.WrapError(err) } } if err == nil { break } time.Sleep(DefaultIntervalShort * time.Second) if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, object.ConnectionString, id, errmsgs.ProviderERROR) } } return nil } func (s *RdsService) WaitForAccount(id string, status Status, timeout int) error { deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBAccount(id) if err != nil { if errmsgs.NotFoundError(err) { if status == Deleted { return nil } } else { return errmsgs.WrapError(err) } } if object != nil { if object.AccountStatus == string(status) { break } else if object.AccountStatus == "Lock" { request := rds.CreateDeleteAccountRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = object.DBInstanceId request.AccountName = object.AccountName _, err := s.client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.DeleteAccount(request) }) if err != nil && !errmsgs.IsExpectedErrors(err, []string{"InvalidAccountName.NotFound"}) { return errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, id, request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR) } } } if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, object.AccountStatus, status, errmsgs.ProviderERROR) } } return nil } func (s *RdsService) WaitForAccountPrivilege(id, dbName string, status Status, timeout int) error { parts, err := ParseResourceId(id, 3) if err != nil { return errmsgs.WrapError(err) } deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBDatabase(parts[0] + ":" + dbName) if err != nil { if errmsgs.NotFoundError(err) { if status == Deleted { return nil } } else { return errmsgs.WrapError(err) } } ready := false if object != nil { for _, account := range object.Accounts.AccountPrivilegeInfo { // At present, postgresql response has a bug, DBOwner will be changed to ALL if account.Account == parts[1] && (account.AccountPrivilege == parts[2] || (parts[2] == "DBOwner" && account.AccountPrivilege == "ALL")) { ready = true break } } } if status == Deleted && !ready { break } if ready { break } if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, "", id, errmsgs.ProviderERROR) } } return nil } func (s *RdsService) WaitForAccountPrivilegeRevoked(id, dbName string, timeout int) error { parts, err := ParseResourceId(id, 3) if err != nil { return errmsgs.WrapError(err) } deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBDatabase(parts[0] + ":" + dbName) if err != nil { if errmsgs.NotFoundError(err) { return nil } return errmsgs.WrapError(err) } exist := false if object != nil { for _, account := range object.Accounts.AccountPrivilegeInfo { if account.Account == parts[1] && (account.AccountPrivilege == parts[2] || (parts[2] == "DBOwner" && account.AccountPrivilege == "ALL")) { exist = true break } } } if !exist { break } if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, "", dbName, errmsgs.ProviderERROR) } } return nil } func (s *RdsService) WaitForDBDatabase(id string, status Status, timeout int) error { parts, err := ParseResourceId(id, 2) if err != nil { return errmsgs.WrapError(err) } deadline := time.Now().Add(time.Duration(timeout) * time.Second) for { object, err := s.DescribeDBDatabase(id) if err != nil { if errmsgs.NotFoundError(err) { if status == Deleted { return nil } } return errmsgs.WrapError(err) } if object != nil && object.DBName == parts[1] { break } time.Sleep(DefaultIntervalShort * time.Second) if time.Now().After(deadline) { return errmsgs.WrapErrorf(err, errmsgs.WaitTimeoutMsg, id, GetFunc(1), timeout, object.DBName, parts[1], errmsgs.ProviderERROR) } } return nil } // turn period to TimeType func (s *RdsService) TransformPeriod2Time(period int, chargeType string) (ut int, tt common.TimeType) { if chargeType == string(Postpaid) { return 1, common.Day } if period >= 1 && period <= 9 { return period, common.Month } if period == 12 { return 1, common.Year } if period == 24 { return 2, common.Year } return 0, common.Day } // turn TimeType to Period func (s *RdsService) TransformTime2Period(ut int, tt common.TimeType) (period int) { if tt == common.Year { return 12 * ut } return ut } func (s *RdsService) flattenDBSecurityIPs(list []rds.DBInstanceIPArray) []map[string]interface{} { result := make([]map[string]interface{}, 0, len(list)) for _, i := range list { l := map[string]interface{}{ "security_ips": i.SecurityIPList, } result = append(result, l) } return result } func (s *RdsService) setInstanceTags(d *schema.ResourceData) error { if d.HasChange("tags") { oraw, nraw := d.GetChange("tags") o := oraw.(map[string]interface{}) n := nraw.(map[string]interface{}) remove, add := diffRdsTags(o, n) if len(remove) > 0 { request := rds.CreateUntagResourcesRequest() s.client.InitRpcRequest(*request.RpcRequest) request.ResourceId = &[]string{d.Id()} request.ResourceType = "INSTANCE" request.TagKey = &remove wait := incrementalWait(1*time.Second, 2*time.Second) var raw interface{} var err error err = resource.Retry(10*time.Minute, func() *resource.RetryError { raw, err = s.client.WithRdsClient(func(client *rds.Client) (interface{}, error) { return client.UntagResources(request) }) if err != nil { if errmsgs.IsThrottling(err) { wait() return resource.RetryableError(err) } return resource.NonRetryableError(err) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) response, ok := raw.(*rds.UntagResourcesResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } } if len(add) > 0 { request := rds.CreateTagResourcesRequest() s.client.InitRpcRequest(*request.RpcRequest) request.ResourceId = &[]string{d.Id()} request.Tag = &add request.ResourceType = "INSTANCE" wait := incrementalWait(1*time.Second, 2*time.Second) var raw interface{} var err error err = resource.Retry(10*time.Minute, func() *resource.RetryError { raw, err = s.client.WithRdsClient(func(client *rds.Client) (interface{}, error) { return client.TagResources(request) }) if err != nil { if errmsgs.IsThrottling(err) { wait() return resource.RetryableError(err) } return resource.NonRetryableError(err) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) response, ok := raw.(*rds.TagResourcesResponse) if err != nil { errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } } //d.SetPartial("tags") } return nil } func (s *RdsService) describeTags(d *schema.ResourceData) (tags []Tag, err error) { request := rds.CreateDescribeTagsRequest() s.client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = d.Id() raw, err := s.client.WithRdsClient(func(client *rds.Client) (interface{}, error) { return client.DescribeTags(request) }) response, ok := raw.(*rds.DescribeTagsResponse) if err != nil { tmp := make([]Tag, 0) errmsg := "" if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return tmp, errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return s.respToTags(response.Items.TagInfos), nil } func (s *RdsService) respToTags(tagSet []rds.TagInfos) (tags []Tag) { result := make([]Tag, 0, len(tagSet)) for _, t := range tagSet { tag := Tag{ Key: t.TagKey, Value: t.TagValue, } result = append(result, tag) } return result } func (s *RdsService) tagsToMap(tags []Tag) map[string]string { result := make(map[string]string) for _, t := range tags { if !s.ignoreTag(t) { result[t.Key] = t.Value } } return result } func (s *RdsService) ignoreTag(t Tag) bool { filter := []string{"^aliyun", "^acs:", "^http://", "^https://"} for _, v := range filter { log.Printf("[DEBUG] Matching prefix %v with %v\n", v, t.Key) ok, _ := regexp.MatchString(v, t.Key) if ok { log.Printf("[DEBUG] Found Alibaba Cloud specific t %s (val: %s), ignoring.\n", t.Key, t.Value) return true } } return false } func (s *RdsService) tagsToString(tags []Tag) string { v, _ := json.Marshal(s.tagsToMap(tags)) return string(v) }