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

skip_destroy support for RDS Option and Parameter Group Resources #29663

Merged
merged 17 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
10 changes: 9 additions & 1 deletion internal/service/rds/option_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ func ResourceOptionGroup() *schema.Resource {
},
Set: resourceOptionHash,
},

"skip_destroy": {
Type: schema.TypeBool,
Optional: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
Expand Down Expand Up @@ -325,6 +328,11 @@ func resourceOptionGroupDelete(ctx context.Context, d *schema.ResourceData, meta
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).RDSConn()

if _, ok := d.GetOk("skip_destroy"); ok {
log.Printf("[DEBUG] Retaining DB Option Group %q", d.Id())
return diags
}

deleteOpts := &rds.DeleteOptionGroupInput{
OptionGroupName: aws.String(d.Id()),
}
Expand Down
98 changes: 82 additions & 16 deletions internal/service/rds/option_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestAccRDSOptionGroup_basic(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -75,7 +75,7 @@ func TestAccRDSOptionGroup_timeoutBlock(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand All @@ -102,7 +102,7 @@ func TestAccRDSOptionGroup_namePrefix(t *testing.T) {
ResourceName: "aws_db_option_group.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand All @@ -128,7 +128,7 @@ func TestAccRDSOptionGroup_generatedName(t *testing.T) {
ResourceName: "aws_db_option_group.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -157,7 +157,7 @@ func TestAccRDSOptionGroup_optionGroupDescription(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -185,7 +185,7 @@ func TestAccRDSOptionGroup_basicDestroyWithInstance(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -220,7 +220,7 @@ func TestAccRDSOptionGroup_Option_optionSettings(t *testing.T) {
ImportStateVerify: true,
// Ignore option since our current logic skips "unconfigured" default option settings
// Even with Config set, ImportState TestStep does not "see" the configuration to check against
ImportStateVerifyIgnore: []string{"name_prefix", "option"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy", "option"},
},
{
Config: testAccOptionGroupConfig_optionSettingsUpdate(rName),
Expand All @@ -238,7 +238,7 @@ func TestAccRDSOptionGroup_Option_optionSettings(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -269,7 +269,7 @@ func TestAccRDSOptionGroup_OptionOptionSettings_iamRole(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -298,7 +298,7 @@ func TestAccRDSOptionGroup_sqlServerOptionsUpdate(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
{
Config: testAccOptionGroupConfig_sqlServerEEOptionsUpdate(rName),
Expand Down Expand Up @@ -338,7 +338,7 @@ func TestAccRDSOptionGroup_oracleOptionsUpdate(t *testing.T) {
ImportState: true,
ImportStateVerify: true,
// Ignore option since API responds with **** instead of password
ImportStateVerifyIgnore: []string{"name_prefix", "option"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy", "option"},
},
{
Config: testAccOptionGroupConfig_oracleEEOptionSettings(rName, "13.3.0.0.v2"),
Expand Down Expand Up @@ -377,7 +377,7 @@ func TestAccRDSOptionGroup_OptionOptionSettings_multipleNonDefault(t *testing.T)
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
{
Config: testAccOptionGroupConfig_settingsMultiple(rName, "example1,example2"),
Expand Down Expand Up @@ -414,7 +414,7 @@ func TestAccRDSOptionGroup_multipleOptions(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
},
})
Expand Down Expand Up @@ -444,7 +444,7 @@ func TestAccRDSOptionGroup_tags(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
{
Config: testAccOptionGroupConfig_tags2(rName, "key1", "value1updated", "key2", "value2"),
Expand Down Expand Up @@ -493,7 +493,7 @@ func TestAccRDSOptionGroup_Tags_withOptions(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"name_prefix"},
ImportStateVerifyIgnore: []string{"name_prefix", "skip_destroy"},
},
{
Config: testAccOptionGroupConfig_tagsOption2(rName, "key1", "value1updated", "key2", "value2"),
Expand All @@ -518,6 +518,58 @@ func TestAccRDSOptionGroup_Tags_withOptions(t *testing.T) {
})
}

func TestAccCheckOptionGroup_skipDestroy(t *testing.T) {
var v rds.OptionGroup
ctx := acctest.Context(t)
resourceName := "aws_db_option_group.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, rds.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckOptionGroupNoDestroy(ctx, t),
Steps: []resource.TestStep{
{
Config: testAccOptionGroupConfig_skip_destroy(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckOptionGroupExists(ctx, resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "skip_destroy", "true"),
),
},
},
})
}

func testAccCheckOptionGroupNoDestroy(ctx context.Context, t *testing.T) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).RDSConn()

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_db_option_group" {
continue
}

opts := rds.DescribeOptionGroupsInput{
OptionGroupName: aws.String(rs.Primary.ID),
}
_, err := conn.DescribeOptionGroupsWithContext(ctx, &opts)

// cleanup option group if it was properly verified not to be destroyed by tf in the first place
if err == nil {
deleteOpts := rds.DeleteOptionGroupInput{
OptionGroupName: aws.String(rs.Primary.ID),
}
_, _ = conn.DeleteOptionGroupWithContext(ctx, &deleteOpts)
}

return err
}

return nil
}
}

func testAccCheckOptionGroupOptionSettingsIAMRole(optionGroup *rds.OptionGroup) resource.TestCheckFunc {
return func(s *terraform.State) error {
if optionGroup == nil {
Expand Down Expand Up @@ -623,7 +675,6 @@ func testAccCheckOptionGroupDestroy(ctx context.Context) resource.TestCheckFunc
return nil
}
}

func testAccOptionGroupConfig_timeoutBlock(rName string) string {
return fmt.Sprintf(`
data "aws_rds_engine_version" "default" {
Expand Down Expand Up @@ -698,6 +749,21 @@ resource "aws_db_option_group" "test" {
`, mySQLPreferredInstanceClasses, rName)
}

func testAccOptionGroupConfig_skip_destroy(rName string) string {
return fmt.Sprintf(`
data "aws_rds_engine_version" "default" {
engine = "mysql"
}

resource "aws_db_option_group" "test" {
name = %[1]q
engine_name = data.aws_rds_engine_version.default.engine
major_engine_version = regex("^\\d+\\.\\d+", data.aws_rds_engine_version.default.version)
skip_destroy = true
}
`, rName)
}

func testAccOptionGroupConfig_optionSettings(rName string) string {
return fmt.Sprintf(`
data "aws_rds_engine_version" "default" {
Expand Down
10 changes: 10 additions & 0 deletions internal/service/rds/parameter_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ func ResourceParameterGroup() *schema.Resource {
},
Set: resourceParameterHash,
},
"skip_destroy": {
Type: schema.TypeBool,
Optional: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
Expand Down Expand Up @@ -341,6 +345,12 @@ func resourceParameterGroupUpdate(ctx context.Context, d *schema.ResourceData, m

func resourceParameterGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) (diags diag.Diagnostics) {
conn := meta.(*conns.AWSClient).RDSClient()

if _, ok := d.GetOk("skip_destroy"); ok {
log.Printf("[DEBUG] Retaining DB Parameter Group %q", d.Id())
return diags
}

input := &rds_sdkv2.DeleteDBParameterGroupInput{
DBParameterGroupName: aws.String(d.Id()),
}
Expand Down
Loading