Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for point in time restore aws api for aws rds #65

Closed
psura opened this issue Jul 23, 2018 · 5 comments
Closed

support for point in time restore aws api for aws rds #65

psura opened this issue Jul 23, 2018 · 5 comments

Comments

@psura
Copy link

psura commented Jul 23, 2018

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).

@pjroth
Copy link

pjroth commented Nov 1, 2019

It looks like the aws provider is lacking this functionality. This issue will need to be implemented first before this module will be able to implement this feature as requested above if I understand things correctly: hashicorp/terraform-provider-aws#5286

@bryantbiggs
Copy link
Member

as @pjroth pointed out, this should be opened on the upstream provider

@pjroth
Copy link

pjroth commented Apr 25, 2021

It looks like the issue I linked above in aws provider has now implemented this feature. It looks like there is nothing technical preventing this issue from being worked on at this time. Should this be kept open @bryantbiggs?

@bryantbiggs
Copy link
Member

hey @pjroth - yes point in time restore support is available in the provider and an issue can definitely be created to add this support into the module. however, this issue is more geared towards the upstream provider and references the golang implementation details, etc. and therefore is not sufficient here for this module

@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants