diff --git a/.changelog/11967.txt b/.changelog/11967.txt new file mode 100644 index 00000000000..c76920ac6e0 --- /dev/null +++ b/.changelog/11967.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ssm_parameter: Add support for `Intelligent-Tiering` +``` diff --git a/aws/resource_aws_ssm_parameter.go b/aws/resource_aws_ssm_parameter.go index d1c1728c50a..901fd3d81be 100644 --- a/aws/resource_aws_ssm_parameter.go +++ b/aws/resource_aws_ssm_parameter.go @@ -41,23 +41,18 @@ func resourceAwsSsmParameter() *schema.Resource { Optional: true, }, "tier": { - Type: schema.TypeString, - Optional: true, - Default: ssm.ParameterTierStandard, - ValidateFunc: validation.StringInSlice([]string{ - ssm.ParameterTierStandard, - ssm.ParameterTierAdvanced, - ssm.ParameterTierIntelligentTiering, - }, false), + Type: schema.TypeString, + Optional: true, + Default: ssm.ParameterTierStandard, + ValidateFunc: validation.StringInSlice(ssm.ParameterTier_Values(), false), + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return d.Get("tier").(string) == ssm.ParameterTierIntelligentTiering + }, }, "type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - ssm.ParameterTypeString, - ssm.ParameterTypeStringList, - ssm.ParameterTypeSecureString, - }, false), + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(ssm.ParameterType_Values(), false), }, "value": { Type: schema.TypeString, @@ -101,8 +96,10 @@ func resourceAwsSsmParameter() *schema.Resource { CustomizeDiff: customdiff.All( // Prevent the following error during tier update from Advanced to Standard: // ValidationException: This parameter uses the advanced-parameter tier. You can't downgrade a parameter from the advanced-parameter tier to the standard-parameter tier. If necessary, you can delete the advanced parameter and recreate it as a standard parameter. + // In the case of Advanced to Intelligent-Tiering, a ValidationException is not thrown + // but rather no change occurs without resource re-creation customdiff.ForceNewIfChange("tier", func(_ context.Context, old, new, meta interface{}) bool { - return old.(string) == ssm.ParameterTierAdvanced && new.(string) == ssm.ParameterTierStandard + return old.(string) == ssm.ParameterTierAdvanced && (new.(string) == ssm.ParameterTierStandard || new.(string) == ssm.ParameterTierIntelligentTiering) }), ), } diff --git a/aws/resource_aws_ssm_parameter_test.go b/aws/resource_aws_ssm_parameter_test.go index c50e61226dd..c1ca33f899a 100644 --- a/aws/resource_aws_ssm_parameter_test.go +++ b/aws/resource_aws_ssm_parameter_test.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ssm" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -55,10 +56,10 @@ func TestAccAWSSSMParameter_Tier(t *testing.T) { CheckDestroy: testAccCheckAWSSSMParameterDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSSSMParameterConfigTier(rName, "Intelligent-Tiering"), + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierAdvanced), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMParameterExists(resourceName, ¶meter1), - resource.TestCheckResourceAttr(resourceName, "tier", "Standard"), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierAdvanced), ), }, { @@ -68,19 +69,113 @@ func TestAccAWSSSMParameter_Tier(t *testing.T) { ImportStateVerifyIgnore: []string{"overwrite"}, }, { - Config: testAccAWSSSMParameterConfigTier(rName, "Standard"), + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierStandard), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMParameterExists(resourceName, ¶meter2), - resource.TestCheckResourceAttr(resourceName, "tier", "Standard"), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierStandard), ), }, { - Config: testAccAWSSSMParameterConfigTier(rName, "Advanced"), + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierAdvanced), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMParameterExists(resourceName, ¶meter3), - resource.TestCheckResourceAttr(resourceName, "tier", "Advanced"), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierAdvanced), + ), + }, + }, + }) +} + +func TestAccAWSSSMParameter_Tier_IntelligentTieringToStandard(t *testing.T) { + var parameter ssm.Parameter + rName := fmt.Sprintf("%s_%s", t.Name(), acctest.RandString(10)) + resourceName := "aws_ssm_parameter.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMParameterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierIntelligentTiering), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMParameterExists(resourceName, ¶meter), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierStandard), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"overwrite"}, + }, + { + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierStandard), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMParameterExists(resourceName, ¶meter), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierStandard), + ), + }, + { + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierIntelligentTiering), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMParameterExists(resourceName, ¶meter), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierStandard), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"overwrite"}, + }, + }, + }) +} + +func TestAccAWSSSMParameter_Tier_IntelligentTieringToAdvanced(t *testing.T) { + var parameter1, parameter2 ssm.Parameter + rName := fmt.Sprintf("%s_%s", t.Name(), acctest.RandString(10)) + resourceName := "aws_ssm_parameter.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMParameterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierIntelligentTiering), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMParameterExists(resourceName, ¶meter1), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierStandard), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"overwrite"}, + }, + { + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierAdvanced), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMParameterExists(resourceName, ¶meter1), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierAdvanced), + ), + }, + { + Config: testAccAWSSSMParameterConfigTier(rName, ssm.ParameterTierIntelligentTiering), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMParameterExists(resourceName, ¶meter2), + resource.TestCheckResourceAttr(resourceName, "tier", ssm.ParameterTierStandard), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"overwrite"}, + }, }, }) } @@ -99,7 +194,7 @@ func TestAccAWSSSMParameter_disappears(t *testing.T) { Config: testAccAWSSSMParameterBasicConfig(name, "String", "test2"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMParameterExists(resourceName, ¶m), - testAccCheckAWSSSMParameterDisappears(¶m), + testAccCheckResourceDisappears(testAccProvider, resourceAwsSsmParameter(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -476,20 +571,6 @@ func testAccCheckAWSSSMParameterExists(n string, param *ssm.Parameter) resource. } } -func testAccCheckAWSSSMParameterDisappears(param *ssm.Parameter) resource.TestCheckFunc { - return func(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ssmconn - - paramInput := &ssm.DeleteParameterInput{ - Name: param.Name, - } - - _, err := conn.DeleteParameter(paramInput) - - return err - } -} - func testAccCheckAWSSSMParameterDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ssmconn @@ -504,13 +585,21 @@ func testAccCheckAWSSSMParameterDestroy(s *terraform.State) error { }, } - resp, _ := conn.GetParameters(paramInput) + resp, err := conn.GetParameters(paramInput) - if len(resp.Parameters) > 0 { - return fmt.Errorf("Expected AWS SSM Parameter to be gone, but was still found") + if tfawserr.ErrCodeEquals(err, ssm.ErrCodeParameterNotFound) { + continue } - return nil + if err != nil { + return fmt.Errorf("error reading SSM Parameter (%s): %w", rs.Primary.ID, err) + } + + if resp == nil || len(resp.Parameters) == 0 { + continue + } + + return fmt.Errorf("Expected AWS SSM Parameter to be gone, but was still found") } return nil