Skip to content

Commit

Permalink
[RDS]: opentelekomcloud_rds_instance_v3 restore to point (#2337)
Browse files Browse the repository at this point in the history
[RDS]: `opentelekomcloud_rds_instance_v3` restore to point

Summary of the Pull Request
Feature to restore backups to an existing rds v3 instance.
PR Checklist

 Refers to: #2238
 Tests added/passed.
 Documentation updated.
 Schema updated.
 Release notes added.

Acceptance Steps Performed
=== RUN   TestAccRdsPostgre13V3ParamsBasic
--- PASS: TestAccRdsPostgre13V3ParamsBasic (478.33s)
PASS

Process finished with the exit code 0

=== RUN   TestAccRdsInstanceV3ElasticIP
--- PASS: TestAccRdsInstanceV3ElasticIP (752.79s)
PASS

Process finished with the exit code 0

=== RUN   TestAccRdsInstanceV3Basic
--- PASS: TestAccRdsInstanceV3Basic (850.40s)
PASS

Process finished with the exit code 0

=== RUN   TestAccRdsInstanceV3RestoreToPITR
--- PASS: TestAccRdsInstanceV3RestoreToPITR (670.13s)
PASS

Process finished with the exit code 0

Reviewed-by: Vladimir Vshivkov
Reviewed-by: Aloento
Reviewed-by: Anton Sidelnikov
  • Loading branch information
artem-lifshits committed Oct 11, 2023
1 parent ab09157 commit 8d1a5d1
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 15 deletions.
55 changes: 40 additions & 15 deletions docs/resources/rds_instance_v3.md
Expand Up @@ -313,15 +313,15 @@ resource "opentelekomcloud_rds_parametergroup_v3" "pg_1" {

The following arguments are supported:

* `availability_zone` - (Required) Specifies the AZ name. Changing this parameter will create a new resource.
* `availability_zone` - (Required, ForceNew) Specifies the AZ name. Changing this parameter will create a new resource.

* `db` - (Required) Specifies the database information. Structure is documented below. Changing this parameter will create a new resource.
* `db` - (Required, ForceNew) Specifies the database information. Structure is documented below. Changing this parameter will create a new resource.

* `flavor` - (Required) Specifies the specification code.
Use data source [opentelekomcloud_rds_flavors_v3](../data-sources/rds_flavors_v3.md) to get a list of available flavor names.
Examples could be `rds.pg.c2.medium` or `rds.pg.c2.medium.ha` for HA clusters.

* `name` - (Required) Specifies the DB instance name. The DB instance name of the same type
* `name` - (Required, ForceNew) Specifies the DB instance name. The DB instance name of the same type
must be unique for the same tenant. The value must be 4 to 64
characters in length and start with a letter. It is case-sensitive
and can contain only letters, digits, hyphens (-), and underscores
Expand All @@ -330,15 +330,15 @@ The following arguments are supported:
* `security_group_id` - (Required) Specifies the security group which the RDS DB instance belongs to.
Changing this parameter will create a new resource.

* `subnet_id` - (Required) Specifies the subnet id. Changing this parameter will create a new resource.
* `subnet_id` - (Required, ForceNew) Specifies the subnet id. Changing this parameter will create a new resource.

* `volume` - (Required) Specifies the volume information. Structure is documented below.
* `volume` - (Required, ForceNew) Specifies the volume information. Structure is documented below.

* `vpc_id` - (Required) Specifies the VPC ID. Changing this parameter will create a new resource.
* `vpc_id` - (Required, ForceNew) Specifies the VPC ID. Changing this parameter will create a new resource.

* `backup_strategy` - (Optional) Specifies the advanced backup policy. Structure is documented below.

* `ha_replication_mode` - (Optional) Specifies the replication mode for the standby DB instance. For MySQL, the value
* `ha_replication_mode` - (Optional, ForceNew) Specifies the replication mode for the standby DB instance. For MySQL, the value
is async or semisync. For PostgreSQL, the value is async or sync. For Microsoft SQL Server, the value is sync.

-> Async indicates the asynchronous replication mode. `semisync` indicates the
Expand All @@ -350,7 +350,7 @@ The following arguments are supported:
* `parameters` - (Optional) Map of additional configuration parameters. Values should be strings. Parameters set here
overrides values from configuration template (parameter group).

* `lower_case_table_names` - Specifies the case-sensitive state of the database table name,
* `lower_case_table_names` - (Optional, ForceNew) Specifies the case-sensitive state of the database table name,
the default value is "1". Changing this parameter will create a new resource.
+ 0: Table names are stored as fixed and table names are case-sensitive.
+ 1: Table names will be stored in lower case and table names are not case-sensitive.
Expand All @@ -368,13 +368,17 @@ The following arguments are supported:

* `tags` - (Optional) Tags key/value pairs to associate with the instance.

* `restore_point` - (Optional) Specifies the restoration information.
* `restore_point` - (Optional, ForceNew) Specifies the restoration information. By selecting this option a new RDS
instance will be created from separate instance backup. Structure is documented below.

* `restore_from_backup` - (Optional) Specifies whether to restore database to an instance described in current resource.
Structure is documented below.

* `ssl_enable` - (Optional) Specifies whether SSL should be enabled for MySql instances.

The `db` block supports:

* `password` - (Required) Specifies the database password. The value cannot be
* `password` - (Required, ForceNew) Specifies the database password. The value cannot be
empty and should contain 8 to 32 characters, including uppercase
and lowercase letters, digits, and the following special
characters: ~!@#%^*-_=+? You are advised to enter a strong
Expand All @@ -391,21 +395,21 @@ The `db` block supports:
the default value is 5432. For Microsoft SQL Server, the default
value is 1433. Changing this parameter will create a new resource.

* `type` - (Required) Specifies the DB engine. Value: MySQL, PostgreSQL, SQLServer. Changing this parameter will create a new resource.
* `type` - (Required, ForceNew) Specifies the DB engine. Value: MySQL, PostgreSQL, SQLServer. Changing this parameter will create a new resource.

* `version` - (Required) Specifies the database version. MySQL databases support MySQL 5.6
* `version` - (Required, ForceNew) Specifies the database version. MySQL databases support MySQL 5.6
and above. PostgreSQL databases support PostgreSQL 9.5 and above. Microsoft SQL Server
databases support 2014 SE, 2016 SE, and above.
Changing this parameter will create a new resource.

The `volume` block supports:

* `disk_encryption_id` - (Optional) Specifies the key ID for disk encryption. Changing this parameter will create a new resource.
* `disk_encryption_id` - (Optional, ForceNew) Specifies the key ID for disk encryption. Changing this parameter will create a new resource.

* `size` - (Required) Specifies the volume size. Its value range is from 40 GB to 4000
GB. The value must be a multiple of 10. Changing this resize the volume.

* `type` - (Required) Specifies the volume type. Its value can be any of the following
* `type` - (Required, ForceNew) Specifies the volume type. Its value can be any of the following
and is case-sensitive: COMMON: indicates the SATA type.
ULTRAHIGH: indicates the SSD type. Changing this parameter will create a new resource.

Expand All @@ -426,9 +430,27 @@ The `backup_strategy` block supports:

The `restore_point` block supports:

* `instance_id` - (Required) Specifies the original DB instance ID.
* `instance_id` - (Required, ForceNew) Specifies the original DB instance ID.

* `backup_id` - (Optional, ForceNew) Specifies the ID of the backup used to restore data.

* `restore_time` - (Optional, ForceNew) Specifies the time point of data restoration in the UNIX timestamp.
The unit is millisecond and the time zone is UTC.

-> Exactly one of `backup_id` and `restore_time` needs to be set.

The `restore_from_backup` block supports:

* `source_instance_id` - (Required) Specifies the source instance ID.

* `type` - (Required) Specifies the restoration mode. The values can be:
* `backup` - Indicates using backup files for restoration.
In this mode `backup_id` is mandatory.
* `timestamp` - Indicates the point-in-time restoration mode.
In this mode `restore_time` is mandatory.

* `backup_id` - (Optional) Specifies the ID of the backup used to restore data.
This parameter must be specified when the backup file is used for restoration.

* `restore_time` - (Optional) Specifies the time point of data restoration in the UNIX timestamp.
The unit is millisecond and the time zone is UTC.
Expand All @@ -443,6 +465,9 @@ In addition to the arguments listed above, the following computed attributes are

* `created` - Indicates the creation time.

* `restored_backup_id` - Indicates the backup ID in cases when instance was restored by using
`restore_from_backup` block.

* `nodes` - Indicates the instance nodes information. Structure is documented below.

* `private_ips` - Indicates the private IP address list. It is a blank string until an
Expand Down
Expand Up @@ -338,6 +338,39 @@ func TestAccRdsInstanceV3TimeZoneAndSSL(t *testing.T) {
})
}

func TestAccRdsInstanceV3RestoreToPITR(t *testing.T) {
postfix := acctest.RandString(3)
var rdsInstance instances.InstanceResponse

resource.Test(t, resource.TestCase{
PreCheck: func() { common.TestAccPreCheck(t) },
ProviderFactories: common.TestAccProviderFactories,
CheckDestroy: testAccCheckRdsInstanceV3Destroy,
Steps: []resource.TestStep{
{
Config: testAccRdsInstanceV3RestorePITRBasic(postfix),
Check: resource.ComposeTestCheckFunc(
testAccCheckRdsInstanceV3Exists(instanceV3ResourceName, &rdsInstance),
),
},
{
Config: testAccRdsInstanceV3RestorePITRUpdate(postfix),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(instanceV3ResourceName, "flavor", "rds.pg.c2.large"),
resource.TestCheckResourceAttrSet(instanceV3ResourceName, "restored_backup_id"),
),
},
{
Config: testAccRdsInstanceV3RestorePITRBasic(postfix),
Check: resource.ComposeTestCheckFunc(
testAccCheckRdsInstanceV3Exists(instanceV3ResourceName, &rdsInstance),
resource.TestCheckResourceAttrSet(instanceV3ResourceName, "restored_backup_id"),
),
},
},
})
}

func testAccCheckRdsInstanceV3Destroy(s *terraform.State) error {
config := common.TestAccProvider.Meta().(*cfg.Config)
client, err := config.RdsV3Client(env.OS_REGION_NAME)
Expand Down Expand Up @@ -969,3 +1002,112 @@ resource "opentelekomcloud_rds_instance_v3" "instance" {
}
`, common.DataSourceSecGroupDefault, common.DataSourceSubnet, postfix, env.OS_AVAILABILITY_ZONE)
}

func testAccRdsInstanceV3RestorePITRBasic(postfix string) string {
return fmt.Sprintf(`
%[1]s
%[2]s
resource "opentelekomcloud_rds_instance_v3" "instance" {
name = "tf_rds_instance_%[3]s"
availability_zone = ["%[4]s"]
db {
password = "Postgres!120521"
type = "PostgreSQL"
version = "10"
port = "8635"
}
security_group_id = data.opentelekomcloud_networking_secgroup_v2.default_secgroup.id
subnet_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.network_id
vpc_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.vpc_id
volume {
type = "COMMON"
size = 40
}
flavor = "rds.pg.c2.large"
}
resource "opentelekomcloud_rds_instance_v3" "instance_2" {
name = "tf_rds_source_%[3]s"
availability_zone = ["%[4]s"]
db {
password = "Postgres!120521"
type = "PostgreSQL"
version = "10"
port = "8635"
}
security_group_id = data.opentelekomcloud_networking_secgroup_v2.default_secgroup.id
subnet_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.network_id
vpc_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.vpc_id
volume {
type = "COMMON"
size = 40
}
flavor = "rds.pg.c2.large"
}
resource "opentelekomcloud_rds_backup_v3" "test" {
instance_id = opentelekomcloud_rds_instance_v3.instance_2.id
name = "tf_rds_backup_%[5]s"
}
`, common.DataSourceSecGroupDefault, common.DataSourceSubnet, postfix, env.OS_AVAILABILITY_ZONE, postfix)
}

func testAccRdsInstanceV3RestorePITRUpdate(postfix string) string {
return fmt.Sprintf(`
%[1]s
%[2]s
resource "opentelekomcloud_rds_instance_v3" "instance" {
name = "tf_rds_instance_%[3]s"
availability_zone = ["%[4]s"]
db {
password = "Postgres!120521"
type = "PostgreSQL"
version = "10"
port = "8635"
}
security_group_id = data.opentelekomcloud_networking_secgroup_v2.default_secgroup.id
subnet_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.network_id
vpc_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.vpc_id
volume {
type = "COMMON"
size = 40
}
flavor = "rds.pg.c2.large"
restore_from_backup {
source_instance_id = opentelekomcloud_rds_backup_v3.test.instance_id
backup_id = opentelekomcloud_rds_backup_v3.test.id
type = "backup"
}
}
resource "opentelekomcloud_rds_instance_v3" "instance_2" {
name = "tf_rds_source_%[3]s"
availability_zone = ["%[4]s"]
db {
password = "Postgres!120521"
type = "PostgreSQL"
version = "10"
port = "8635"
}
security_group_id = data.opentelekomcloud_networking_secgroup_v2.default_secgroup.id
subnet_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.network_id
vpc_id = data.opentelekomcloud_vpc_subnet_v1.shared_subnet.vpc_id
volume {
type = "COMMON"
size = 40
}
flavor = "rds.pg.c2.large"
}
resource "opentelekomcloud_rds_backup_v3" "test" {
instance_id = opentelekomcloud_rds_instance_v3.instance_2.id
name = "tf_rds_backup_%[3]s"
}
`, common.DataSourceSecGroupDefault, common.DataSourceSubnet, postfix, env.OS_AVAILABILITY_ZONE)
}
Expand Up @@ -90,6 +90,32 @@ func ResourceRdsInstanceV3() *schema.Resource {
},
},
},
"restore_from_backup": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Computed: false,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"source_instance_id": {
Type: schema.TypeString,
Required: true,
},
"type": {
Type: schema.TypeString,
Required: true,
},
"backup_id": {
Type: schema.TypeString,
Optional: true,
},
"restore_time": {
Type: schema.TypeInt,
Optional: true,
},
},
},
},
"db": {
Type: schema.TypeList,
Required: true,
Expand Down Expand Up @@ -294,6 +320,10 @@ func ResourceRdsInstanceV3() *schema.Resource {
Computed: false,
Optional: true,
},
"restored_backup_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand Down Expand Up @@ -372,6 +402,10 @@ func resourceRdsInstanceV3Create(ctx context.Context, d *schema.ResourceData, me
return fmterr.Errorf(errCreateClient, err)
}

if _, ok := d.GetOk("restore_from_backup.0.source_instance_id"); ok {
return fmterr.Errorf("point in time restoration can be only produced on existing instance")
}

dbInfo := resourceRDSDbInfo(d)
volumeInfo := d.Get("volume").([]interface{})[0].(map[string]interface{})
dbPort := dbInfo["port"].(int)
Expand Down Expand Up @@ -794,6 +828,31 @@ func resourceRdsInstanceV3Update(ctx context.Context, d *schema.ResourceData, me
return fmterr.Errorf(errCreateClient, err)
}

if d.HasChange("restore_from_backup") {
rawPitr := d.Get("restore_from_backup").([]interface{})
if len(rawPitr) > 0 {
pitr := rawPitr[0].(map[string]interface{})
pitrOpts := backups.RestorePITROpts{
Source: backups.Source{
BackupID: pitr["backup_id"].(string),
InstanceID: pitr["source_instance_id"].(string),
RestoreTime: int64(pitr["restore_time"].(int)),
Type: pitr["type"].(string),
},
Target: backups.Target{
InstanceID: d.Id(),
},
}
_, err = backups.RestorePITR(client, pitrOpts)
if err != nil {
return fmterr.Errorf("error in point in time restoration: %s ", err)
}
if err := instances.WaitForStateAvailable(client, 1200, d.Id()); err != nil {
return diag.FromErr(err)
}
}
}

if d.HasChange("security_group_id") {
updateOpts := security.SetSecurityGroupOpts{
InstanceId: d.Id(),
Expand Down Expand Up @@ -1084,6 +1143,16 @@ func resourceRdsInstanceV3Read(ctx context.Context, d *schema.ResourceData, meta
d.Set("ssl_enable", *rdsInstance.EnableSSL),
)

if v, ok := d.GetOk("restore_from_backup"); ok {
rawPitr := v.([]interface{})
if len(rawPitr) > 0 {
backupId := rawPitr[0].(map[string]interface{})["backup_id"]
if backupId != "" {
me = multierror.Append(me, d.Set("restored_backup_id", backupId))
}
}
}

if me.ErrorOrNil() != nil {
return diag.FromErr(me)
}
Expand Down
@@ -0,0 +1,4 @@
---
enhancements:
- |
**[RDS]** Enable restoration from backup to an existing RDS instance for ``resource/opentelekomcloud_rds_instance_v3`` (`#2337 <https://github.com/opentelekomcloud/terraform-provider-opentelekomcloud/pull/2337>`_)

0 comments on commit 8d1a5d1

Please sign in to comment.