|
4 | 4 | "context"
|
5 | 5 | "fmt"
|
6 | 6 | "log"
|
| 7 | + "net/http" |
7 | 8 | "strconv"
|
8 | 9 | "strings"
|
9 | 10 | "time"
|
@@ -61,6 +62,7 @@ type ctxType string
|
61 | 62 | // @API RDS PUT /v3/{project_id}/instances/{instance_id}/ip
|
62 | 63 | // @API RDS PUT /v3/{project_id}/instances/{instance_id}/security-group
|
63 | 64 | // @API RDS POST /v3/{project_id}/instances/{instance_id}/password
|
| 65 | +// @API RDS POST /v3/{project_id}/instances/{instance_id}/to-period |
64 | 66 | // @API RDS PUT /v3/{project_id}/instances/{instance_id}/binlog/clear-policy
|
65 | 67 | // @API RDS DELETE /v3/{project_id}/instances/{instance_id}
|
66 | 68 | // @API EPS POST /v1.0/enterprise-projects/{enterprise_project_id}/resources-migrat
|
@@ -501,12 +503,30 @@ func ResourceRdsInstance() *schema.Resource {
|
501 | 503 | ForceNew: true,
|
502 | 504 | },
|
503 | 505 |
|
504 |
| - // charge info: charging_mode, period_unit, period, auto_renew, auto_pay |
505 |
| - "charging_mode": common.SchemaChargingMode(nil), |
506 |
| - "period_unit": common.SchemaPeriodUnit(nil), |
507 |
| - "period": common.SchemaPeriod(nil), |
508 |
| - "auto_renew": common.SchemaAutoRenewUpdatable(nil), |
509 |
| - "auto_pay": common.SchemaAutoPay(nil), |
| 506 | + // charging_mode, period_unit and period only support changing post-paid to pre-paid billing mode. |
| 507 | + "charging_mode": { |
| 508 | + Type: schema.TypeString, |
| 509 | + Optional: true, |
| 510 | + Computed: true, |
| 511 | + ValidateFunc: validation.StringInSlice([]string{ |
| 512 | + "prePaid", "postPaid", |
| 513 | + }, false), |
| 514 | + }, |
| 515 | + "period_unit": { |
| 516 | + Type: schema.TypeString, |
| 517 | + Optional: true, |
| 518 | + RequiredWith: []string{"period"}, |
| 519 | + ValidateFunc: validation.StringInSlice([]string{ |
| 520 | + "month", "year", |
| 521 | + }, false), |
| 522 | + }, |
| 523 | + "period": { |
| 524 | + Type: schema.TypeInt, |
| 525 | + Optional: true, |
| 526 | + RequiredWith: []string{"period_unit"}, |
| 527 | + }, |
| 528 | + "auto_renew": common.SchemaAutoRenewUpdatable(nil), |
| 529 | + "auto_pay": common.SchemaAutoPay(nil), |
510 | 530 | },
|
511 | 531 | }
|
512 | 532 | }
|
@@ -1035,7 +1055,15 @@ func resourceRdsInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta
|
1035 | 1055 | }
|
1036 | 1056 | }
|
1037 | 1057 |
|
1038 |
| - if d.HasChange("auto_renew") { |
| 1058 | + if d.HasChange("charging_mode") { |
| 1059 | + if d.Get("charging_mode").(string) == "postPaid" { |
| 1060 | + return diag.Errorf("error updating the charging mode of the RDS instance (%s): %s", d.Id(), |
| 1061 | + "only support changing post-paid instance to pre-paid") |
| 1062 | + } |
| 1063 | + if err = updateBillingModeToPeriod(ctx, d, cfg, client, instanceID); err != nil { |
| 1064 | + return diag.FromErr(err) |
| 1065 | + } |
| 1066 | + } else if d.HasChange("auto_renew") { |
1039 | 1067 | bssClient, err := cfg.BssV2Client(region)
|
1040 | 1068 | if err != nil {
|
1041 | 1069 | return diag.Errorf("error creating BSS V2 client: %s", err)
|
@@ -1674,6 +1702,82 @@ func updateRdsInstanceSSLConfig(ctx context.Context, d *schema.ResourceData, cli
|
1674 | 1702 | return configRdsInstanceSSL(ctx, d, client, instanceID)
|
1675 | 1703 | }
|
1676 | 1704 |
|
| 1705 | +func updateBillingModeToPeriod(ctx context.Context, d *schema.ResourceData, cfg *config.Config, client *golangsdk.ServiceClient, |
| 1706 | + instanceID string) error { |
| 1707 | + var ( |
| 1708 | + httpUrl = "v3/{project_id}/instances/{instance_id}/to-period" |
| 1709 | + ) |
| 1710 | + updatePath := client.Endpoint + httpUrl |
| 1711 | + updatePath = strings.ReplaceAll(updatePath, "{project_id}", client.ProjectID) |
| 1712 | + updatePath = strings.ReplaceAll(updatePath, "{instance_id}", d.Id()) |
| 1713 | + |
| 1714 | + updateOpt := golangsdk.RequestOpts{ |
| 1715 | + KeepResponseBody: true, |
| 1716 | + } |
| 1717 | + updateOpt.JSONBody = utils.RemoveNil(buildUpdateBillingModeToPeriodBodyParams(d)) |
| 1718 | + |
| 1719 | + retryFunc := func() (interface{}, bool, error) { |
| 1720 | + res, err := client.Request("POST", updatePath, &updateOpt) |
| 1721 | + retry, err := handleMultiOperationsError(err) |
| 1722 | + return res, retry, err |
| 1723 | + } |
| 1724 | + res, err := common.RetryContextWithWaitForState(&common.RetryContextWithWaitForStateParam{ |
| 1725 | + Ctx: ctx, |
| 1726 | + RetryFunc: retryFunc, |
| 1727 | + WaitFunc: rdsInstanceStateRefreshFunc(client, d.Id()), |
| 1728 | + WaitTarget: []string{"ACTIVE"}, |
| 1729 | + Timeout: d.Timeout(schema.TimeoutUpdate), |
| 1730 | + DelayTimeout: 10 * time.Second, |
| 1731 | + PollInterval: 10 * time.Second, |
| 1732 | + }) |
| 1733 | + if err != nil { |
| 1734 | + return fmt.Errorf("error updating instance(%s) billing mode from post-paid to pre-paid: %s", d.Id(), err) |
| 1735 | + } |
| 1736 | + |
| 1737 | + updateRespBody, err := utils.FlattenResponse(res.(*http.Response)) |
| 1738 | + if err != nil { |
| 1739 | + return err |
| 1740 | + } |
| 1741 | + |
| 1742 | + orderId := utils.PathSearch("order_id", updateRespBody, "").(string) |
| 1743 | + if orderId == "" { |
| 1744 | + return fmt.Errorf("error updating RDS instance (%s) MSDTC hosts: order_id is not found in the API rsponse", d.Id()) |
| 1745 | + } |
| 1746 | + bssClient, err := cfg.BssV2Client(cfg.GetRegion(d)) |
| 1747 | + if err != nil { |
| 1748 | + return fmt.Errorf("error creating BSS v2 client: %s", err) |
| 1749 | + } |
| 1750 | + // wait for order success |
| 1751 | + err = common.WaitOrderComplete(ctx, bssClient, orderId, d.Timeout(schema.TimeoutUpdate)) |
| 1752 | + if err != nil { |
| 1753 | + return err |
| 1754 | + } |
| 1755 | + |
| 1756 | + stateConf := &resource.StateChangeConf{ |
| 1757 | + Target: []string{"ACTIVE"}, |
| 1758 | + Refresh: rdsInstanceStateRefreshFunc(client, instanceID), |
| 1759 | + Timeout: d.Timeout(schema.TimeoutUpdate), |
| 1760 | + Delay: 1 * time.Second, |
| 1761 | + PollInterval: 10 * time.Second, |
| 1762 | + } |
| 1763 | + if _, err = stateConf.WaitForStateContext(ctx); err != nil { |
| 1764 | + return fmt.Errorf("error waiting for instance (%s) billing mode to be updated: %s", instanceID, err) |
| 1765 | + } |
| 1766 | + return nil |
| 1767 | +} |
| 1768 | + |
| 1769 | +func buildUpdateBillingModeToPeriodBodyParams(d *schema.ResourceData) map[string]interface{} { |
| 1770 | + bodyParams := map[string]interface{}{ |
| 1771 | + "period_type": strings.ToUpper(d.Get("period_unit").(string)), |
| 1772 | + "period_num": d.Get("period").(int), |
| 1773 | + "auto_pay_policy": "YES", |
| 1774 | + } |
| 1775 | + if d.Get("auto_renew").(string) == "true" { |
| 1776 | + bodyParams["auto_renew_policy"] = "YES" |
| 1777 | + } |
| 1778 | + return bodyParams |
| 1779 | +} |
| 1780 | + |
1677 | 1781 | func updateConfiguration(ctx context.Context, d *schema.ResourceData, client, clientV31 *golangsdk.ServiceClient,
|
1678 | 1782 | instanceID string) (context.Context, error) {
|
1679 | 1783 | if !d.HasChange("param_group_id") {
|
|
0 commit comments