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

New resource: aws_db_instance_automated_backups_replication #23759

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
955b974
feat: add aws_db_instance_automated_backups_replication
marcin-janas Aug 5, 2021
b2e5468
db_instance_backup_replication - WIP on new resource
bschaatsbergen Mar 18, 2022
6827e79
db_instance_backup_replication - more wip on the new resource
bschaatsbergen Mar 18, 2022
43e9e42
db_instance_backup_replication - remove `destination_region`, as 'reg…
bschaatsbergen Mar 19, 2022
fca6fc0
db_instance_backup_replication - add a waiter
bschaatsbergen Mar 20, 2022
1c9d0c2
Touch up deletion flow, wait for source database to be available
bschaatsbergen Mar 22, 2022
23fe794
Add `db_instance_backup_replication` tests
bschaatsbergen Mar 22, 2022
2c2c7f8
Add `retention_period` and KMS encrypted backup acceptance test
bschaatsbergen Mar 23, 2022
a6f13f7
Rename to `aws_db_instance_automated_backup_replication`
bschaatsbergen Mar 24, 2022
bbb84a4
terrafmt `testAccInstanceAutomatedBackupReplicationConfig_kmsEncrypted`
bschaatsbergen Mar 24, 2022
411d4e7
Create CHANGELOG entry
bschaatsbergen Mar 24, 2022
0dc91aa
Update db_instance_automated_backup_replication.markdown
bschaatsbergen Mar 24, 2022
ede999b
Surround fenced code blocks with blank links and fix typo
bschaatsbergen Mar 24, 2022
b27db95
Remove tab
bschaatsbergen Mar 24, 2022
c7d9fff
Update db_instance_automated_backup_replication.markdown
bschaatsbergen Mar 24, 2022
6b7cea2
Revert "Update db_instance_automated_backup_replication.markdown"
bschaatsbergen Mar 24, 2022
1506c50
Move retained status check to `resourceInstanceAutomatedBackupReplica…
bschaatsbergen Mar 24, 2022
2dc70db
Remove NotFound check in delete op, this is already handled in the read
bschaatsbergen Mar 24, 2022
de608b4
Update instance_automated_backup_replication_test.go
bschaatsbergen Mar 24, 2022
c990f49
Fix acceptance tests, iterate through CheckDestroy response
bschaatsbergen Mar 28, 2022
8ade2a2
Removed unused const `dbInstanceAutomatedBackupReplicationRetained`
bschaatsbergen Mar 29, 2022
e4ff8de
r/aws_db_instance_automated_backup_replication: Alphabetize attributes.
ewbankkit Mar 29, 2022
d938b63
r/aws_db_instance_automated_backup_replication: No need to document a…
ewbankkit Mar 29, 2022
050331d
r/aws_db_instance_automated_backup_replication: 'waitDBInstanceAutoma…
ewbankkit Mar 29, 2022
7b4046f
r/aws_db_instance_automated_backup_replication: 'FindDBInstanceAutoma…
ewbankkit Mar 29, 2022
392d369
r/aws_db_instance_automated_backup_replication: Use 'FindDBInstanceAu…
ewbankkit Mar 29, 2022
b4f4967
Derive source DB region from its ARN.
ewbankkit Mar 29, 2022
c6ad6a7
r/aws_db_instance_automated_backup_replication: Change the logic for …
ewbankkit Mar 29, 2022
3e533da
Revert "feat: add aws_db_instance_automated_backups_replication"
ewbankkit Mar 29, 2022
12a87eb
Merge commit '3e533dadf2685fd50ae3c5cee62918d1e86a866c' into HEAD
ewbankkit Mar 29, 2022
38de16e
r/aws_db_instance_automated_backup_replication: Add 'pre_signed_url' …
ewbankkit Mar 29, 2022
2b33840
'aws_db_instance_automated_backup_replication' -> 'aws_db_instance_au…
ewbankkit Mar 29, 2022
9ced21c
'aws_db_instance_automated_backup_replication' -> 'aws_db_instance_au…
ewbankkit Mar 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/23759.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_db_instance_automated_backups_replication
```
39 changes: 20 additions & 19 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1659,25 +1659,26 @@ func Provider() *schema.Provider {
"aws_ram_resource_share": ram.ResourceResourceShare(),
"aws_ram_resource_share_accepter": ram.ResourceResourceShareAccepter(),

"aws_db_cluster_snapshot": rds.ResourceClusterSnapshot(),
"aws_db_event_subscription": rds.ResourceEventSubscription(),
"aws_db_instance": rds.ResourceInstance(),
"aws_db_instance_role_association": rds.ResourceInstanceRoleAssociation(),
"aws_db_option_group": rds.ResourceOptionGroup(),
"aws_db_parameter_group": rds.ResourceParameterGroup(),
"aws_db_proxy": rds.ResourceProxy(),
"aws_db_proxy_default_target_group": rds.ResourceProxyDefaultTargetGroup(),
"aws_db_proxy_endpoint": rds.ResourceProxyEndpoint(),
"aws_db_proxy_target": rds.ResourceProxyTarget(),
"aws_db_security_group": rds.ResourceSecurityGroup(),
"aws_db_snapshot": rds.ResourceSnapshot(),
"aws_db_subnet_group": rds.ResourceSubnetGroup(),
"aws_rds_cluster": rds.ResourceCluster(),
"aws_rds_cluster_endpoint": rds.ResourceClusterEndpoint(),
"aws_rds_cluster_instance": rds.ResourceClusterInstance(),
"aws_rds_cluster_parameter_group": rds.ResourceClusterParameterGroup(),
"aws_rds_cluster_role_association": rds.ResourceClusterRoleAssociation(),
"aws_rds_global_cluster": rds.ResourceGlobalCluster(),
"aws_db_cluster_snapshot": rds.ResourceClusterSnapshot(),
"aws_db_event_subscription": rds.ResourceEventSubscription(),
"aws_db_instance": rds.ResourceInstance(),
"aws_db_instance_automated_backups_replication": rds.ResourceInstanceAutomatedBackupsReplication(),
"aws_db_instance_role_association": rds.ResourceInstanceRoleAssociation(),
"aws_db_option_group": rds.ResourceOptionGroup(),
"aws_db_parameter_group": rds.ResourceParameterGroup(),
"aws_db_proxy": rds.ResourceProxy(),
"aws_db_proxy_default_target_group": rds.ResourceProxyDefaultTargetGroup(),
"aws_db_proxy_endpoint": rds.ResourceProxyEndpoint(),
"aws_db_proxy_target": rds.ResourceProxyTarget(),
"aws_db_security_group": rds.ResourceSecurityGroup(),
"aws_db_snapshot": rds.ResourceSnapshot(),
"aws_db_subnet_group": rds.ResourceSubnetGroup(),
"aws_rds_cluster": rds.ResourceCluster(),
"aws_rds_cluster_endpoint": rds.ResourceClusterEndpoint(),
"aws_rds_cluster_instance": rds.ResourceClusterInstance(),
"aws_rds_cluster_parameter_group": rds.ResourceClusterParameterGroup(),
"aws_rds_cluster_role_association": rds.ResourceClusterRoleAssociation(),
"aws_rds_global_cluster": rds.ResourceGlobalCluster(),

"aws_redshift_cluster": redshift.ResourceCluster(),
"aws_redshift_event_subscription": redshift.ResourceEventSubscription(),
Expand Down
6 changes: 6 additions & 0 deletions internal/service/rds/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ const (
InstanceStatusStorageOptimization = "storage-optimization"
)

const (
InstanceAutomatedBackupStatusPending = "pending"
InstanceAutomatedBackupStatusReplicating = "replicating"
InstanceAutomatedBackupStatusRetained = "retained"
)

const (
EventSubscriptionStatusActive = "active"
EventSubscriptionStatusCreating = "creating"
Expand Down
78 changes: 78 additions & 0 deletions internal/service/rds/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,81 @@ func FindEventSubscriptionByID(conn *rds.RDS, id string) (*rds.EventSubscription

return output.EventSubscriptionsList[0], nil
}

func FindDBInstanceAutomatedBackupByARN(conn *rds.RDS, arn string) (*rds.DBInstanceAutomatedBackup, error) {
input := &rds.DescribeDBInstanceAutomatedBackupsInput{
DBInstanceAutomatedBackupsArn: aws.String(arn),
}

output, err := findDBInstanceAutomatedBackup(conn, input)

if err != nil {
return nil, err
}

if status := aws.StringValue(output.Status); status == InstanceAutomatedBackupStatusRetained {
// If the automated backup is retained, the replication is stopped.
return nil, &resource.NotFoundError{
Message: status,
LastRequest: input,
}
}

// Eventual consistency check.
if aws.StringValue(output.DBInstanceAutomatedBackupsArn) != arn {
return nil, &resource.NotFoundError{
LastRequest: input,
}
}

return output, nil
}

func findDBInstanceAutomatedBackup(conn *rds.RDS, input *rds.DescribeDBInstanceAutomatedBackupsInput) (*rds.DBInstanceAutomatedBackup, error) {
output, err := findDBInstanceAutomatedBackups(conn, input)

if err != nil {
return nil, err
}

if len(output) == 0 || output[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

if count := len(output); count > 1 {
return nil, tfresource.NewTooManyResultsError(count, input)
}

return output[0], nil
}

func findDBInstanceAutomatedBackups(conn *rds.RDS, input *rds.DescribeDBInstanceAutomatedBackupsInput) ([]*rds.DBInstanceAutomatedBackup, error) {
var output []*rds.DBInstanceAutomatedBackup

err := conn.DescribeDBInstanceAutomatedBackupsPages(input, func(page *rds.DescribeDBInstanceAutomatedBackupsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, v := range page.DBInstanceAutomatedBackups {
if v != nil {
output = append(output, v)
}
}

return !lastPage
})

if tfawserr.ErrCodeEquals(err, rds.ErrCodeDBInstanceAutomatedBackupNotFoundFault) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

return output, nil
}
149 changes: 149 additions & 0 deletions internal/service/rds/instance_automated_backups_replication.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package rds

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourceInstanceAutomatedBackupsReplication() *schema.Resource {
return &schema.Resource{
Create: resourceInstanceAutomatedBackupsReplicationCreate,
Read: resourceInstanceAutomatedBackupsReplicationRead,
Delete: resourceInstanceAutomatedBackupsReplicationDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: verify.ValidARN,
},
"pre_signed_url": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"retention_period": {
Type: schema.TypeInt,
ForceNew: true,
Optional: true,
Default: 7,
},
"source_db_instance_arn": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: verify.ValidARN,
},
},
}
}

func resourceInstanceAutomatedBackupsReplicationCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).RDSConn

input := &rds.StartDBInstanceAutomatedBackupsReplicationInput{
BackupRetentionPeriod: aws.Int64(int64(d.Get("retention_period").(int))),
SourceDBInstanceArn: aws.String(d.Get("source_db_instance_arn").(string)),
}

if v, ok := d.GetOk("kms_key_id"); ok {
input.KmsKeyId = aws.String(v.(string))
}

if v, ok := d.GetOk("pre_signed_url"); ok {
input.PreSignedUrl = aws.String(v.(string))
}

log.Printf("[DEBUG] Starting RDS instance automated backups replication: %s", input)
output, err := conn.StartDBInstanceAutomatedBackupsReplication(input)

if err != nil {
return fmt.Errorf("error starting RDS instance automated backups replication: %w", err)
}

d.SetId(aws.StringValue(output.DBInstanceAutomatedBackup.DBInstanceAutomatedBackupsArn))

if _, err := waitDBInstanceAutomatedBackupCreated(conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return fmt.Errorf("error waiting for DB instance automated backup (%s) create: %w", d.Id(), err)
}

return resourceInstanceAutomatedBackupsReplicationRead(d, meta)
}

func resourceInstanceAutomatedBackupsReplicationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).RDSConn

backup, err := FindDBInstanceAutomatedBackupByARN(conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] RDS instance automated backup %s not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading RDS instance automated backup (%s): %w", d.Id(), err)
}

d.Set("kms_key_id", backup.KmsKeyId)
d.Set("retention_period", backup.BackupRetentionPeriod)
d.Set("source_db_instance_arn", backup.DBInstanceArn)

return nil
}

func resourceInstanceAutomatedBackupsReplicationDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).RDSConn

backup, err := FindDBInstanceAutomatedBackupByARN(conn, d.Id())

if tfresource.NotFound(err) {
return nil
}

if err != nil {
return fmt.Errorf("error reading RDS instance automated backup (%s): %w", d.Id(), err)
}

dbInstanceID := aws.StringValue(backup.DBInstanceIdentifier)
sourceDatabaseARN, err := arn.Parse(aws.StringValue(backup.DBInstanceArn))

if err != nil {
return err
}

log.Printf("[DEBUG] Stopping RDS instance automated backups replication: %s", d.Id())
_, err = conn.StopDBInstanceAutomatedBackupsReplication(&rds.StopDBInstanceAutomatedBackupsReplicationInput{
SourceDBInstanceArn: aws.String(d.Get("source_db_instance_arn").(string)),
})

if err != nil {
return fmt.Errorf("error stopping RDS instance automated backups replication (%s): %w", d.Id(), err)
}

// Create a new client to the source region.
sourceDatabaseConn := conn
if sourceDatabaseARN.Region != meta.(*conns.AWSClient).Region {
sourceDatabaseConn = rds.New(meta.(*conns.AWSClient).Session, aws.NewConfig().WithRegion(sourceDatabaseARN.Region))
}

if _, err := waitDBInstanceAutomatedBackupDeleted(sourceDatabaseConn, dbInstanceID, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
return fmt.Errorf("error waiting for DB instance automated backup (%s) delete: %w", d.Id(), err)
}

return nil
}
Loading