diff --git a/.changelog/35231.txt b/.changelog/35231.txt new file mode 100644 index 00000000000..5f9c379e6c3 --- /dev/null +++ b/.changelog/35231.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_ecr_lifecycle_policy: Add missing `tagPatternList` change detection in policy JSON +``` \ No newline at end of file diff --git a/internal/service/ecr/lifecycle_policy.go b/internal/service/ecr/lifecycle_policy.go index 9e9c9e9c44a..0fc3e7e5681 100644 --- a/internal/service/ecr/lifecycle_policy.go +++ b/internal/service/ecr/lifecycle_policy.go @@ -188,11 +188,12 @@ func resourceLifecyclePolicyDelete(ctx context.Context, d *schema.ResourceData, } type lifecyclePolicyRuleSelection struct { - TagStatus *string `locationName:"tagStatus" type:"string" enum:"tagStatus" required:"true"` - TagPrefixList []*string `locationName:"tagPrefixList" type:"list"` - CountType *string `locationName:"countType" type:"string" enum:"countType" required:"true"` - CountUnit *string `locationName:"countUnit" type:"string" enum:"countType"` - CountNumber *int64 `locationName:"countNumber" min:"1" type:"integer"` + TagStatus *string `locationName:"tagStatus" type:"string" enum:"tagStatus" required:"true"` + TagPatternList []*string `locationName:"tagPatternList" type:"list"` + TagPrefixList []*string `locationName:"tagPrefixList" type:"list"` + CountType *string `locationName:"countType" type:"string" enum:"countType" required:"true"` + CountUnit *string `locationName:"countUnit" type:"string" enum:"countType"` + CountNumber *int64 `locationName:"countNumber" min:"1" type:"integer"` } type lifecyclePolicyRuleAction struct { @@ -221,6 +222,14 @@ func (lp *lifecyclePolicy) reduce() { } func (lprs *lifecyclePolicyRuleSelection) reduce() { + sort.Slice(lprs.TagPatternList, func(i, j int) bool { + return aws.StringValue(lprs.TagPatternList[i]) < aws.StringValue(lprs.TagPatternList[j]) + }) + + if len(lprs.TagPatternList) == 0 { + lprs.TagPatternList = nil + } + sort.Slice(lprs.TagPrefixList, func(i, j int) bool { return aws.StringValue(lprs.TagPrefixList[i]) < aws.StringValue(lprs.TagPrefixList[j]) }) diff --git a/internal/service/ecr/lifecycle_policy_test.go b/internal/service/ecr/lifecycle_policy_test.go index 5b3bacc0f31..e13dfcb93f2 100644 --- a/internal/service/ecr/lifecycle_policy_test.go +++ b/internal/service/ecr/lifecycle_policy_test.go @@ -143,6 +143,32 @@ func testAccCheckLifecyclePolicyExists(ctx context.Context, name string) resourc } } +func TestAccECRLifecyclePolicy_detectTagPatternListDiff(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecr_lifecycle_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, ecr.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLifecyclePolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLifecyclePolicyConfig_tagPatternList(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckLifecyclePolicyExists(ctx, resourceName), + ), + }, + { + Config: testAccLifecyclePolicyConfig_tagPatternListChanged(rName), + ExpectNonEmptyPlan: true, + PlanOnly: true, + }, + }, + }) +} + func testAccLifecyclePolicyConfig_basic(rName string) string { return fmt.Sprintf(` resource "aws_ecr_repository" "test" { @@ -302,3 +328,69 @@ resource "aws_ecr_lifecycle_policy" "test" { } `, rName) } + +func testAccLifecyclePolicyConfig_tagPatternList(rName string) string { + return fmt.Sprintf(` +resource "aws_ecr_repository" "test" { + name = "%s" +} + +resource "aws_ecr_lifecycle_policy" "test" { + repository = aws_ecr_repository.test.name + + policy = jsonencode({ + rules = [ + { + rulePriority = 1 + description = "Expire tagged images older than 14 days" + selection = { + tagStatus = "tagged" + tagPatternList = [ + "alpha-*" + ] + countType = "sinceImagePushed" + countUnit = "days" + countNumber = 14 + } + action = { + type = "expire" + } + } + ] + }) +} +`, rName) +} + +func testAccLifecyclePolicyConfig_tagPatternListChanged(rName string) string { + return fmt.Sprintf(` +resource "aws_ecr_repository" "test" { + name = "%s" +} + +resource "aws_ecr_lifecycle_policy" "test" { + repository = aws_ecr_repository.test.name + + policy = jsonencode({ + rules = [ + { + rulePriority = 1 + description = "Expire tagged images older than 14 days" + selection = { + tagStatus = "tagged" + tagPatternList = [ + "beta-*" + ] + countType = "sinceImagePushed" + countUnit = "days" + countNumber = 14 + } + action = { + type = "expire" + } + } + ] + }) +} +`, rName) +}