Hi:
I am using the terraform-aws-rds module for one of our terraform project at work and recently have been looking into support for restore of aws rds (postgres specifically) using snapshot and PITR (point in time restore) api's that aws provides. terraform-aws-rds module today already support snapshot based restore but not PITR agreeably because terraform-provider-aws also does have have PITR support today.
I have opened this issue on git hub for the same for terraform-provider-aws: hashicorp/terraform-provider-aws#5286
Can someone share details on how I can contribute to the terraform-aws-rds module or if someone can provide support below PITR feature. Did not see any instructions to contribute on the terraform-modules github page. May be I can copy the module locally and make changes there?
Here are more details:
Beyond adding relevant code in terraform-provider-aws in this go file for PITR, I realized that I need to also update the terraform-aws-rds module that I am consuming to recognize the new variables that I need to support for PIRT.
This is a draft version of changes I am playing with in the resource_aws_db_instance.go on my local machine. As you can see I basically added four new arguments
SourceDBInstanceIdentifier: aws.String(d.Get("source_db_instance_identifier").(string)), TargetDBInstanceIdentifier: aws.String(d.Get("target_db_instance_dentifier").(string)), UseLatestRestorableTime: aws.Bool(d.Get("use_latest_restorable_time").(bool)), RestoreTime: aws.Time(d.Get("restore_time").(time.Time)),
And got rid of below that's required for snapshot based restore.
// DBInstanceIdentifier: aws.String(d.Get("identifier").(string)), // DBSnapshotIdentifier: aws.String(d.Get("snapshot_identifier").(string)),
Potential change to support PITR:
else if _, ok := d.GetOk("source_db_instance_identifier"); ok {
//opts := rds.RestoreDBInstanceFromDBSnapshotInput{
// DBInstanceClass: aws.String(d.Get("instance_class").(string)),
// DBInstanceIdentifier: aws.String(d.Get("identifier").(string)),
// DBSnapshotIdentifier: aws.String(d.Get("snapshot_identifier").(string)),
// AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
// PubliclyAccessible: aws.Bool(d.Get("publicly_accessible").(bool)),
// Tags: tags,
// CopyTagsToSnapshot: aws.Bool(d.Get("copy_tags_to_snapshot").(bool)),
//}
opts := rds.RestoreDBInstanceToPointInTimeInput{
DBInstanceClass: aws.String(d.Get("instance_class").(string)),
SourceDBInstanceIdentifier: aws.String(d.Get("source_db_instance_identifier").(string)),
TargetDBInstanceIdentifier: aws.String(d.Get("target_db_instance_dentifier").(string)),
UseLatestRestorableTime: aws.Bool(d.Get("use_latest_restorable_time").(bool)),
RestoreTime: aws.Time(d.Get("restore_time").(time.Time)),
AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
PubliclyAccessible: aws.Bool(d.Get("publicly_accessible").(bool)),
Tags: tags,
CopyTagsToSnapshot: aws.Bool(d.Get("copy_tags_to_snapshot").(bool)),
}
if attr, ok := d.GetOk("name"); ok {
// "Note: This parameter [DBName] doesn't apply to the MySQL, PostgreSQL, or MariaDB engines."
// https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_RestoreDBInstanceToPointInTime.html
switch strings.ToLower(d.Get("engine").(string)) {
case "mysql", "postgres", "mariadb":
// skip
default:
opts.DBName = aws.String(attr.(string))
}
}
if attr, ok := d.GetOk("availability_zone"); ok {
opts.AvailabilityZone = aws.String(attr.(string))
}
if attr, ok := d.GetOk("db_subnet_group_name"); ok {
opts.DBSubnetGroupName = aws.String(attr.(string))
}
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
opts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
}
if attr, ok := d.GetOk("engine"); ok {
opts.Engine = aws.String(attr.(string))
}
if attr, ok := d.GetOk("iops"); ok {
opts.Iops = aws.Int64(int64(attr.(int)))
}
if attr, ok := d.GetOk("license_model"); ok {
opts.LicenseModel = aws.String(attr.(string))
}
if attr, ok := d.GetOk("multi_az"); ok {
opts.MultiAZ = aws.Bool(attr.(bool))
}
if attr, ok := d.GetOk("option_group_name"); ok {
opts.OptionGroupName = aws.String(attr.(string))
}
if attr, ok := d.GetOk("port"); ok {
opts.Port = aws.Int64(int64(attr.(int)))
}
if attr, ok := d.GetOk("tde_credential_arn"); ok {
opts.TdeCredentialArn = aws.String(attr.(string))
}
if attr, ok := d.GetOk("storage_type"); ok {
opts.StorageType = aws.String(attr.(string))
}
//log.Printf("[DEBUG] DB Instance restore from snapshot configuration: %s", opts)
//_, err := conn.RestoreDBInstanceFromDBSnapshot(&opts)
//if err != nil {
// return fmt.Errorf("Error creating DB Instance: %s", err)
//}
log.Printf("[DEBUG] DB Instance restore to point in time configuration: %s", opts)
_, err := conn.RestoreDBInstanceToPointInTime(&opts)
if err != nil {
return fmt.Errorf("Error creating DB Instance: %s", err)
}
var sgUpdate bool
var passwordUpdate bool
if _, ok := d.GetOk("password"); ok {
passwordUpdate = true
}
if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 {
sgUpdate = true
}
if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
sgUpdate = true
}
if sgUpdate || passwordUpdate {
log.Printf("[INFO] DB is restoring to user requested point in time with default" +
" security, but custom security should be set, " +
"will now update after point in time restore is complete!")
// wait for instance to get up and then modify security
d.SetId(d.Get("target_db_instance_identifier").(string))
log.Printf("[INFO] DB Instance ID: %s", d.Id())
log.Println(
"[INFO] Waiting for DB Instance to be available")
stateConf := &resource.StateChangeConf{
Pending: resourceAwsDbInstanceCreatePendingStates,
Target: []string{"available", "storage-optimization"},
Refresh: resourceAwsDbInstanceStateRefreshFunc(d.Id(), conn),
Timeout: d.Timeout(schema.TimeoutCreate),
MinTimeout: 10 * time.Second,
Delay: 30 * time.Second, // Wait 30 secs before starting
}
// Wait, catching any errors
_, err := stateConf.WaitForState()
if err != nil {
return err
}
err = resourceAwsDbInstanceUpdate(d, meta)
if err != nil {
return err
}
}
}
My terragrunt plan is now failing as the terraform-aws-rds modules does not recognize the new parameters I introduced to support PITR and also complaining about the identifier that's not required for PIRT unless I replace target_db_instance_identifier as identifier.
`
terragrunt plan --terragrunt-source ../../../../../../../terraform-modules//rds/postgresql/restore/PITR
...
...
...
Initializing the backend...
Error: module "db": "source_db_instance_identifier" is not a valid argument
Error: module "db": "target_db_instance_identifier" is not a valid argument
Error: module "db": "use_latest_restorable_time" is not a valid argument
Error: module "db": missing required argument "identifier"
`
Looking forward to get the PITR support in terraform-aws-rds module (and also terraform-provider-aws ultimately which is a dependency for sure for the rds module to work).