Skip to content

Commit

Permalink
Merge pull request #6011 from terraform-providers/f-aws_db_instance-d…
Browse files Browse the repository at this point in the history
…eletion_protection

resource/aws_db_instance: Add deletion_protection argument
  • Loading branch information
bflad authored Oct 3, 2018
2 parents f971ab6 + 6851c6d commit 3b0f65d
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 0 deletions.
15 changes: 15 additions & 0 deletions aws/resource_aws_db_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ func resourceAwsDbInstance() *schema.Resource {
Sensitive: true,
},

"deletion_protection": {
Type: schema.TypeBool,
Optional: true,
},

"engine": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -466,6 +471,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts := rds.CreateDBInstanceReadReplicaInput{
AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
CopyTagsToSnapshot: aws.Bool(d.Get("copy_tags_to_snapshot").(bool)),
DeletionProtection: aws.Bool(d.Get("deletion_protection").(bool)),
DBInstanceClass: aws.String(d.Get("instance_class").(string)),
DBInstanceIdentifier: aws.String(identifier),
PubliclyAccessible: aws.Bool(d.Get("publicly_accessible").(bool)),
Expand Down Expand Up @@ -593,6 +599,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
DBName: aws.String(d.Get("name").(string)),
DBInstanceClass: aws.String(d.Get("instance_class").(string)),
DBInstanceIdentifier: aws.String(d.Get("identifier").(string)),
DeletionProtection: aws.Bool(d.Get("deletion_protection").(bool)),
Engine: aws.String(d.Get("engine").(string)),
EngineVersion: aws.String(d.Get("engine_version").(string)),
S3BucketName: aws.String(s3_bucket["bucket_name"].(string)),
Expand Down Expand Up @@ -749,6 +756,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
DBInstanceClass: aws.String(d.Get("instance_class").(string)),
DBInstanceIdentifier: aws.String(d.Get("identifier").(string)),
DBSnapshotIdentifier: aws.String(d.Get("snapshot_identifier").(string)),
DeletionProtection: aws.Bool(d.Get("deletion_protection").(bool)),
PubliclyAccessible: aws.Bool(d.Get("publicly_accessible").(bool)),
Tags: tags,
}
Expand Down Expand Up @@ -921,6 +929,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
DBName: aws.String(d.Get("name").(string)),
DBInstanceClass: aws.String(d.Get("instance_class").(string)),
DBInstanceIdentifier: aws.String(d.Get("identifier").(string)),
DeletionProtection: aws.Bool(d.Get("deletion_protection").(bool)),
MasterUsername: aws.String(d.Get("username").(string)),
MasterUserPassword: aws.String(d.Get("password").(string)),
Engine: aws.String(d.Get("engine").(string)),
Expand Down Expand Up @@ -1119,6 +1128,7 @@ func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error {
d.Set("identifier", v.DBInstanceIdentifier)
d.Set("resource_id", v.DbiResourceId)
d.Set("username", v.MasterUsername)
d.Set("deletion_protection", v.DeletionProtection)
d.Set("engine", v.Engine)
d.Set("engine_version", v.EngineVersion)
d.Set("allocated_storage", v.AllocatedStorage)
Expand Down Expand Up @@ -1335,6 +1345,11 @@ func resourceAwsDbInstanceUpdate(d *schema.ResourceData, meta interface{}) error
req.CopyTagsToSnapshot = aws.Bool(d.Get("copy_tags_to_snapshot").(bool))
requestUpdate = true
}
if d.HasChange("deletion_protection") {
d.SetPartial("deletion_protection")
req.DeletionProtection = aws.Bool(d.Get("deletion_protection").(bool))
requestUpdate = true
}
if d.HasChange("instance_class") {
d.SetPartial("instance_class")
req.DBInstanceClass = aws.String(d.Get("instance_class").(string))
Expand Down
190 changes: 190 additions & 0 deletions aws/resource_aws_db_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func TestAccAWSDBInstance_basic(t *testing.T) {
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "allocated_storage", "10"),
resource.TestMatchResourceAttr("aws_db_instance.bar", "arn", regexp.MustCompile(`^arn:[^:]+:rds:[^:]+:\d{12}:db:.+`)),
resource.TestCheckResourceAttr("aws_db_instance.bar", "deletion_protection", "false"),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "engine", "mysql"),
resource.TestCheckResourceAttr(
Expand Down Expand Up @@ -285,6 +286,46 @@ func TestAccAWSDBInstance_iamAuth(t *testing.T) {
})
}

func TestAccAWSDBInstance_DeletionProtection(t *testing.T) {
var dbInstance rds.DBInstance

rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_db_instance.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSDBInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSDBInstanceConfig_DeletionProtection(rName, true),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists(resourceName, &dbInstance),
resource.TestCheckResourceAttr(resourceName, "deletion_protection", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"apply_immediately",
"final_snapshot_identifier",
"password",
"skip_final_snapshot",
},
},
{
Config: testAccAWSDBInstanceConfig_DeletionProtection(rName, false),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists(resourceName, &dbInstance),
resource.TestCheckResourceAttr(resourceName, "deletion_protection", "false"),
),
},
},
})
}

func TestAccAWSDBInstance_FinalSnapshotIdentifier(t *testing.T) {
var snap rds.DBInstance
rInt := acctest.RandInt()
Expand Down Expand Up @@ -509,6 +550,53 @@ func TestAccAWSDBInstance_ReplicateSourceDb_BackupWindow(t *testing.T) {
})
}

func TestAccAWSDBInstance_ReplicateSourceDb_DeletionProtection(t *testing.T) {
t.Skip("CreateDBInstanceReadReplica API currently ignores DeletionProtection=true with SourceDBInstanceIdentifier set")
// --- FAIL: TestAccAWSDBInstance_ReplicateSourceDb_DeletionProtection (1624.88s)
// testing.go:527: Step 0 error: Check failed: Check 4/4 error: aws_db_instance.test: Attribute 'deletion_protection' expected "true", got "false"
//
// Action=CreateDBInstanceReadReplica&AutoMinorVersionUpgrade=true&CopyTagsToSnapshot=false&DBInstanceClass=db.t2.micro&DBInstanceIdentifier=tf-acc-test-6591588621809891413&DeletionProtection=true&PubliclyAccessible=false&SourceDBInstanceIdentifier=tf-acc-test-6591588621809891413-source&Tags=&Version=2014-10-31
// <RestoreDBInstanceFromDBSnapshotResponse xmlns="http://rds.amazonaws.com/doc/2014-10-31/">
// <RestoreDBInstanceFromDBSnapshotResult>
// <DBInstance>
// <DeletionProtection>false</DeletionProtection>
//
// AWS Support has confirmed this issue and noted that it will be fixed in the future.

var dbInstance, sourceDbInstance rds.DBInstance

rName := acctest.RandomWithPrefix("tf-acc-test")
sourceResourceName := "aws_db_instance.source"
resourceName := "aws_db_instance.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSDBInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSDBInstanceConfig_ReplicateSourceDb_DeletionProtection(rName, true),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists(sourceResourceName, &sourceDbInstance),
testAccCheckAWSDBInstanceExists(resourceName, &dbInstance),
testAccCheckAWSDBInstanceReplicaAttributes(&sourceDbInstance, &dbInstance),
resource.TestCheckResourceAttr(resourceName, "deletion_protection", "true"),
),
},
// Ensure we disable deletion protection before attempting to delete :)
{
Config: testAccAWSDBInstanceConfig_ReplicateSourceDb_DeletionProtection(rName, false),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists(sourceResourceName, &sourceDbInstance),
testAccCheckAWSDBInstanceExists(resourceName, &dbInstance),
testAccCheckAWSDBInstanceReplicaAttributes(&sourceDbInstance, &dbInstance),
resource.TestCheckResourceAttr(resourceName, "deletion_protection", "false"),
),
},
},
})
}

func TestAccAWSDBInstance_ReplicateSourceDb_IamDatabaseAuthenticationEnabled(t *testing.T) {
var dbInstance, sourceDbInstance rds.DBInstance

Expand Down Expand Up @@ -893,6 +981,43 @@ func TestAccAWSDBInstance_SnapshotIdentifier_BackupWindow(t *testing.T) {
})
}

func TestAccAWSDBInstance_SnapshotIdentifier_DeletionProtection(t *testing.T) {
var dbInstance, sourceDbInstance rds.DBInstance
var dbSnapshot rds.DBSnapshot

rName := acctest.RandomWithPrefix("tf-acc-test")
sourceDbResourceName := "aws_db_instance.source"
snapshotResourceName := "aws_db_snapshot.test"
resourceName := "aws_db_instance.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSDBInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSDBInstanceConfig_SnapshotIdentifier_DeletionProtection(rName, true),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists(sourceDbResourceName, &sourceDbInstance),
testAccCheckDbSnapshotExists(snapshotResourceName, &dbSnapshot),
testAccCheckAWSDBInstanceExists(resourceName, &dbInstance),
resource.TestCheckResourceAttr(resourceName, "deletion_protection", "true"),
),
},
// Ensure we disable deletion protection before attempting to delete :)
{
Config: testAccAWSDBInstanceConfig_SnapshotIdentifier_DeletionProtection(rName, false),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists(sourceDbResourceName, &sourceDbInstance),
testAccCheckDbSnapshotExists(snapshotResourceName, &dbSnapshot),
testAccCheckAWSDBInstanceExists(resourceName, &dbInstance),
resource.TestCheckResourceAttr(resourceName, "deletion_protection", "false"),
),
},
},
})
}

func TestAccAWSDBInstance_SnapshotIdentifier_IamDatabaseAuthenticationEnabled(t *testing.T) {
var dbInstance, sourceDbInstance rds.DBInstance
var dbSnapshot rds.DBSnapshot
Expand Down Expand Up @@ -3247,6 +3372,21 @@ resource "aws_db_instance" "test" {
`, rName)
}

func testAccAWSDBInstanceConfig_DeletionProtection(rName string, deletionProtection bool) string {
return fmt.Sprintf(`
resource "aws_db_instance" "test" {
allocated_storage = 5
deletion_protection = %t
engine = "mysql"
identifier = %q
instance_class = "db.t2.micro"
password = "avoid-plaintext-passwords"
username = "tfacctest"
skip_final_snapshot = true
}
`, deletionProtection, rName)
}

func testAccAWSDBInstanceConfig_EnabledCloudwatchLogsExports_Oracle(rName string) string {
return fmt.Sprintf(`
resource "aws_db_instance" "test" {
Expand Down Expand Up @@ -3401,6 +3541,29 @@ resource "aws_db_instance" "test" {
`, rName, backupWindow, rName)
}

func testAccAWSDBInstanceConfig_ReplicateSourceDb_DeletionProtection(rName string, deletionProtection bool) string {
return fmt.Sprintf(`
resource "aws_db_instance" "source" {
allocated_storage = 5
backup_retention_period = 1
engine = "mysql"
identifier = "%s-source"
instance_class = "db.t2.micro"
password = "avoid-plaintext-passwords"
username = "tfacctest"
skip_final_snapshot = true
}
resource "aws_db_instance" "test" {
deletion_protection = %t
identifier = %q
instance_class = "${aws_db_instance.source.instance_class}"
replicate_source_db = "${aws_db_instance.source.id}"
skip_final_snapshot = true
}
`, rName, deletionProtection, rName)
}

func testAccAWSDBInstanceConfig_ReplicateSourceDb_IamDatabaseAuthenticationEnabled(rName string, iamDatabaseAuthenticationEnabled bool) string {
return fmt.Sprintf(`
resource "aws_db_instance" "source" {
Expand Down Expand Up @@ -3800,6 +3963,33 @@ resource "aws_db_instance" "test" {
`, rName, rName, backupWindow, rName)
}

func testAccAWSDBInstanceConfig_SnapshotIdentifier_DeletionProtection(rName string, deletionProtection bool) string {
return fmt.Sprintf(`
resource "aws_db_instance" "source" {
allocated_storage = 5
engine = "mysql"
identifier = "%s-source"
instance_class = "db.t2.micro"
password = "avoid-plaintext-passwords"
username = "tfacctest"
skip_final_snapshot = true
}
resource "aws_db_snapshot" "test" {
db_instance_identifier = "${aws_db_instance.source.id}"
db_snapshot_identifier = %q
}
resource "aws_db_instance" "test" {
deletion_protection = %t
identifier = %q
instance_class = "${aws_db_instance.source.instance_class}"
snapshot_identifier = "${aws_db_snapshot.test.id}"
skip_final_snapshot = true
}
`, rName, rName, deletionProtection, rName)
}

func testAccAWSDBInstanceConfig_SnapshotIdentifier_IamDatabaseAuthenticationEnabled(rName string, iamDatabaseAuthenticationEnabled bool) string {
return fmt.Sprintf(`
resource "aws_db_instance" "source" {
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/db_instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ with read replicas, it needs to be specified only if the source database
specifies an instance in another AWS Region. See [DBSubnetGroupName in API
action CreateDBInstanceReadReplica](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstanceReadReplica.html)
for additional read replica contraints.
* `deletion_protection` - (Optional) If the DB instance should have deletion protection enabled. The database can't be deleted when this value is set to `true`. The default is `false`.
* `domain` - (Optional) The ID of the Directory Service Active Directory domain to create the instance in.
* `domain_iam_role_name` - (Optional, but required if domain is provided) The name of the IAM role to be used when making API calls to the Directory Service.
* `enabled_cloudwatch_logs_exports` - (Optional) List of log types to enable for exporting to CloudWatch logs. If omitted, no logs will be exported. Valid values (depending on `engine`): `alert`, `audit`, `error`, `general`, `listener`, `slowquery`, `trace`.
Expand Down

0 comments on commit 3b0f65d

Please sign in to comment.