alibabacloudstack/resource_apsarastack_rds_dbconnection.go (220 lines of code) (raw):

package alibabacloudstack import ( "fmt" "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "regexp" "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/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) const dbConnectionSuffixRegex = "\\.mysql\\.([a-zA-Z0-9\\-]+\\.){0,1}rds\\.aliyuncs\\.com" const dbConnectionIdWithSuffixRegex = "^([a-zA-Z0-9\\-_]+:[a-zA-Z0-9\\-_]+)" + dbConnectionSuffixRegex + "$" var dbConnectionIdWithSuffixRegexp = regexp.MustCompile(dbConnectionIdWithSuffixRegex) func resourceAlibabacloudStackDBConnection() *schema.Resource { resource := &schema.Resource{ Schema: map[string]*schema.Schema{ "instance_id": { Type: schema.TypeString, ForceNew: true, Required: true, }, "connection_prefix": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, ValidateFunc: validation.StringLenBetween(1, 31), }, "port": { Type: schema.TypeString, Optional: true, ValidateFunc: validateDBConnectionPort, Default: "3306", }, "connection_string": { Type: schema.TypeString, Computed: true, }, "ip_address": { Type: schema.TypeString, Computed: true, }, }, } setResourceFunc(resource, resourceAlibabacloudStackDBConnectionCreate, resourceAlibabacloudStackDBConnectionRead, resourceAlibabacloudStackDBConnectionUpdate, resourceAlibabacloudStackDBConnectionDelete) return resource } func resourceAlibabacloudStackDBConnectionCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) rdsService := RdsService{client} instanceId := d.Get("instance_id").(string) prefix := d.Get("connection_prefix").(string) if prefix == "" { prefix = fmt.Sprintf("%stf", instanceId) } request := rds.CreateAllocateInstancePublicConnectionRequest() client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = instanceId request.ConnectionStringPrefix = prefix request.Port = d.Get("port").(string) var raw interface{} var err error err = resource.Retry(8*time.Minute, func() *resource.RetryError { raw, err = client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.AllocateInstancePublicConnection(request) }) if err != nil { if errmsgs.IsExpectedErrors(err, errmsgs.OperationDeniedDBStatus) { return resource.RetryableError(err) } return resource.NonRetryableError(err) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) if err != nil { errmsg := "" if raw != nil { response, ok := raw.(*rds.AllocateInstancePublicConnectionResponse) if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_db_connection", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } d.SetId(fmt.Sprintf("%s%s%s", instanceId, COLON_SEPARATED, request.ConnectionStringPrefix)) if err := rdsService.WaitForDBConnection(d.Id(), Available, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } // wait instance running after allocating if err := rdsService.WaitForDBInstance(instanceId, Running, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } return nil } func resourceAlibabacloudStackDBConnectionRead(d *schema.ResourceData, meta interface{}) error { submatch := dbConnectionIdWithSuffixRegexp.FindStringSubmatch(d.Id()) if len(submatch) > 1 { d.SetId(submatch[1]) } client := meta.(*connectivity.AlibabacloudStackClient) rdsService := RdsService{client} object, err := rdsService.DescribeDBConnection(d.Id()) if err != nil { if errmsgs.NotFoundError(err) { d.SetId("") return nil } return errmsgs.WrapError(err) } parts, err := ParseResourceId(d.Id(), 2) if err != nil { return errmsgs.WrapError(err) } d.Set("instance_id", parts[0]) d.Set("connection_prefix", parts[1]) d.Set("port", object.Port) d.Set("connection_string", object.ConnectionString) d.Set("ip_address", object.IPAddress) return nil } func resourceAlibabacloudStackDBConnectionUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) rdsService := RdsService{client} submatch := dbConnectionIdWithSuffixRegexp.FindStringSubmatch(d.Id()) if len(submatch) > 1 { d.SetId(submatch[1]) } parts, err := ParseResourceId(d.Id(), 2) if err != nil { return errmsgs.WrapError(err) } if d.HasChange("port") { request := rds.CreateModifyDBInstanceConnectionStringRequest() client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = parts[0] object, err := rdsService.DescribeDBConnection(d.Id()) if err != nil { return errmsgs.WrapError(err) } request.CurrentConnectionString = object.ConnectionString request.ConnectionStringPrefix = parts[1] request.Port = d.Get("port").(string) if err := resource.Retry(8*time.Minute, func() *resource.RetryError { raw, err := client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ModifyDBInstanceConnectionString(request) }) if err != nil { if errmsgs.IsExpectedErrors(err, errmsgs.OperationDeniedDBStatus) { return resource.RetryableError(err) } errmsg := "" if raw != nil { response, ok := raw.(*rds.ModifyDBInstanceConnectionStringResponse) if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } } err = errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) return resource.NonRetryableError(err) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }); err != nil { return err } // wait instance running after modifying if err := rdsService.WaitForDBInstance(request.DBInstanceId, Running, DefaultTimeoutMedium); err != nil { return errmsgs.WrapError(err) } } return nil } func resourceAlibabacloudStackDBConnectionDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) rdsService := RdsService{client} submatch := dbConnectionIdWithSuffixRegexp.FindStringSubmatch(d.Id()) if len(submatch) > 1 { d.SetId(submatch[1]) } split := strings.Split(d.Id(), COLON_SEPARATED) request := rds.CreateReleaseInstancePublicConnectionRequest() client.InitRpcRequest(*request.RpcRequest) request.DBInstanceId = split[0] err := resource.Retry(5*time.Minute, func() *resource.RetryError { object, err := rdsService.DescribeDBConnection(d.Id()) if err != nil { return resource.NonRetryableError(errmsgs.WrapError(err)) } request.CurrentConnectionString = object.ConnectionString var raw interface{} raw, err = client.WithRdsClient(func(rdsClient *rds.Client) (interface{}, error) { return rdsClient.ReleaseInstancePublicConnection(request) }) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"OperationDenied.DBInstanceStatus"}) { return resource.RetryableError(err) } errmsg := "" if raw != nil { response, ok := raw.(*rds.ReleaseInstancePublicConnectionResponse) if ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } } if errmsgs.NotFoundError(err) || errmsgs.IsExpectedErrors(err, []string{"InvalidCurrentConnectionString.NotFound", "AtLeastOneNetTypeExists"}) { return nil } err = errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) return resource.NonRetryableError(err) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) if err != nil { return err } return rdsService.WaitForDBConnection(d.Id(), Deleted, DefaultTimeoutMedium) }