Skip to content

Commit b8b8d2c

Browse files
authored
Merge pull request #33167 from hashicorp/b-aws_kms_key-tag-update-timeout
r/aws_kms_key: Fix tag propagation timeout errors when `ignore_tags` is configured
2 parents 0d5c5f6 + d639d0c commit b8b8d2c

File tree

10 files changed

+153
-14
lines changed

10 files changed

+153
-14
lines changed

.changelog/33167.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
resource/aws_kms_key: Fix `tag propagation: timeout while waiting for state to become 'TRUE'` errors when [`ignore_tags`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#ignore_tags) has been configured
3+
```

internal/acctest/acctest.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,11 +1193,11 @@ func ConfigDefaultAndIgnoreTagsKeyPrefixes1(key1, value1, keyPrefix1 string) str
11931193
provider "aws" {
11941194
default_tags {
11951195
tags = {
1196-
%q = %q
1196+
%[1]q = %[2]q
11971197
}
11981198
}
11991199
ignore_tags {
1200-
key_prefixes = [%q]
1200+
key_prefixes = [%[3]q]
12011201
}
12021202
}
12031203
`, key1, value1, keyPrefix1)
@@ -1209,7 +1209,7 @@ func ConfigDefaultAndIgnoreTagsKeys1(key1, value1 string) string {
12091209
provider "aws" {
12101210
default_tags {
12111211
tags = {
1212-
%[1]q = %q
1212+
%[1]q = %[2]q
12131213
}
12141214
}
12151215
ignore_tags {
@@ -1569,7 +1569,7 @@ func ConfigDefaultTags_Tags1(tag1, value1 string) string {
15691569
provider "aws" {
15701570
default_tags {
15711571
tags = {
1572-
%q = %q
1572+
%[1]q = %[2]q
15731573
}
15741574
}
15751575
@@ -1588,8 +1588,8 @@ func ConfigDefaultTags_Tags2(tag1, value1, tag2, value2 string) string {
15881588
provider "aws" {
15891589
default_tags {
15901590
tags = {
1591-
%q = %q
1592-
%q = %q
1591+
%[1]q = %[2]q
1592+
%[3]q = %[4]q
15931593
}
15941594
}
15951595
@@ -1609,8 +1609,8 @@ func ConfigAssumeRolePolicy(policy string) string {
16091609
return fmt.Sprintf(`
16101610
provider "aws" {
16111611
assume_role {
1612-
role_arn = %q
1613-
policy = %q
1612+
role_arn = %[1]q
1613+
policy = %[2]q
16141614
}
16151615
}
16161616
`, os.Getenv(envvar.AccAssumeRoleARN), policy)

internal/generate/tags/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var (
5151
listTagsInIDElem = flag.String("ListTagsInIDElem", "ResourceArn", "listTagsInIDElem")
5252
listTagsInIDNeedSlice = flag.String("ListTagsInIDNeedSlice", "", "listTagsInIDNeedSlice")
5353
listTagsOp = flag.String("ListTagsOp", "ListTagsForResource", "listTagsOp")
54+
listTagsOpPaginated = flag.Bool("ListTagsOpPaginated", false, "whether ListTagsOp is paginated")
5455
listTagsOutTagsElem = flag.String("ListTagsOutTagsElem", "Tags", "listTagsOutTagsElem")
5556
setTagsOutFunc = flag.String("SetTagsOutFunc", "setTagsOut", "setTagsOutFunc")
5657
tagInCustomVal = flag.String("TagInCustomVal", "", "tagInCustomVal")
@@ -164,6 +165,7 @@ type TemplateData struct {
164165
ListTagsInIDElem string
165166
ListTagsInIDNeedSlice string
166167
ListTagsOp string
168+
ListTagsOpPaginated bool
167169
ListTagsOutTagsElem string
168170
ParentNotFoundErrCode string
169171
ParentNotFoundErrMsg string
@@ -318,6 +320,7 @@ func main() {
318320
ListTagsInIDElem: *listTagsInIDElem,
319321
ListTagsInIDNeedSlice: *listTagsInIDNeedSlice,
320322
ListTagsOp: *listTagsOp,
323+
ListTagsOpPaginated: *listTagsOpPaginated,
321324
ListTagsOutTagsElem: *listTagsOutTagsElem,
322325
ParentNotFoundErrCode: *parentNotFoundErrCode,
323326
ParentNotFoundErrMsg: *parentNotFoundErrMsg,

internal/generate/tags/templates/v1/list_tags_body.tmpl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,26 @@ func {{ .ListTagsFunc }}(ctx context.Context, conn {{ .ClientType }}, identifier
2121
{{- end }}
2222
{{- end }}
2323
}
24+
{{- if .ListTagsOpPaginated }}
25+
var output []*{{ .TagPackage }}.{{ .TagType }}
26+
27+
err := conn.{{ .ListTagsOp }}PagesWithContext(ctx, input, func(page *{{ .TagPackage }}.{{ .ListTagsOp }}Output, lastPage bool) bool {
28+
if page == nil {
29+
return !lastPage
30+
}
31+
32+
for _, v := range page.{{ .ListTagsOutTagsElem }} {
33+
if v != nil {
34+
output = append(output, v)
35+
}
36+
}
37+
38+
return !lastPage
39+
})
40+
{{ else }}
2441

2542
output, err := conn.{{ .ListTagsOp }}WithContext(ctx, input)
43+
{{- end }}
2644

2745
{{ if and ( .ParentNotFoundErrCode ) ( .ParentNotFoundErrMsg ) }}
2846
if tfawserr.ErrMessageContains(err, "{{ .ParentNotFoundErrCode }}", "{{ .ParentNotFoundErrMsg }}") {
@@ -44,7 +62,11 @@ func {{ .ListTagsFunc }}(ctx context.Context, conn {{ .ClientType }}, identifier
4462
return tftags.New(ctx, nil), err
4563
}
4664

65+
{{ if .ListTagsOpPaginated }}
66+
return {{ .KeyValueTagsFunc }}(ctx, output{{ if .TagTypeIDElem }}, identifier{{ if .TagResTypeElem }}, resourceType{{ end }}{{ end }}), nil
67+
{{- else }}
4768
return {{ .KeyValueTagsFunc }}(ctx, output.{{ .ListTagsOutTagsElem }}{{ if .TagTypeIDElem }}, identifier{{ if .TagResTypeElem }}, resourceType{{ end }}{{ end }}), nil
69+
{{- end }}
4870
}
4971

5072
{{- if .IsDefaultListTags }}

internal/generate/tags/templates/v1/wait_tags_propagated_body.tmpl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, conn {{ .ClientType }},
77
})
88

99
checkFunc := func() (bool, error) {
10-
output, err := listTags(ctx, conn, id)
10+
output, err := {{ .ListTagsFunc }}(ctx, conn, id)
1111

1212
if tfresource.NotFound(err) {
1313
return false, nil
@@ -17,6 +17,10 @@ func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, conn {{ .ClientType }},
1717
return false, err
1818
}
1919

20+
if inContext, ok := tftags.FromContext(ctx); ok {
21+
output = output.IgnoreConfig(inContext.IgnoreConfig)
22+
}
23+
2024
return output.Equal(tags), nil
2125
}
2226
opts := tfresource.WaitOpts{

internal/generate/tags/templates/v2/wait_tags_propagated_body.tmpl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, conn {{ .ClientType }},
77
})
88

99
checkFunc := func() (bool, error) {
10-
output, err := listTags(ctx, conn, id)
10+
output, err := {{ .ListTagsFunc }}(ctx, conn, id)
1111

1212
if tfresource.NotFound(err) {
1313
return false, nil
@@ -17,6 +17,10 @@ func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, conn {{ .ClientType }},
1717
return false, err
1818
}
1919

20+
if inContext, ok := tftags.FromContext(ctx); ok {
21+
output = output.IgnoreConfig(inContext.IgnoreConfig)
22+
}
23+
2024
return output.Equal(tags), nil
2125
}
2226
opts := tfresource.WaitOpts{

internal/service/kms/generate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) HashiCorp, Inc.
22
// SPDX-License-Identifier: MPL-2.0
33

4-
//go:generate go run ../../generate/tags/main.go -ListTags -ListTagsOp=ListResourceTags -ListTagsInIDElem=KeyId -ServiceTagsSlice -TagInIDElem=KeyId -TagTypeKeyElem=TagKey -TagTypeValElem=TagValue -UpdateTags -Wait -WaitContinuousOccurence 5 -WaitMinTimeout 1s -WaitTimeout 10m -ParentNotFoundErrCode=NotFoundException
4+
//go:generate go run ../../generate/tags/main.go -ListTags -ListTagsOp=ListResourceTags -ListTagsOpPaginated -ListTagsInIDElem=KeyId -ServiceTagsSlice -TagInIDElem=KeyId -TagTypeKeyElem=TagKey -TagTypeValElem=TagValue -UpdateTags -Wait -WaitContinuousOccurence 5 -WaitMinTimeout 1s -WaitTimeout 10m -ParentNotFoundErrCode=NotFoundException
55
//go:generate go run ../../generate/servicepackage/main.go
66
// ONLY generate directives and package declaration! Do not add anything else to this file.
77

internal/service/kms/key_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,48 @@ func TestAccKMSKey_tags(t *testing.T) {
516516
})
517517
}
518518

519+
// https://github.com/hashicorp/terraform-provider-aws/issues/26174.
520+
func TestAccKMSKey_ignoreTags(t *testing.T) {
521+
ctx := acctest.Context(t)
522+
var key kms.KeyMetadata
523+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
524+
resourceName := "aws_kms_key.test"
525+
526+
resource.ParallelTest(t, resource.TestCase{
527+
PreCheck: func() { acctest.PreCheck(ctx, t) },
528+
ErrorCheck: acctest.ErrorCheck(t, kms.EndpointsID),
529+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
530+
CheckDestroy: testAccCheckKeyDestroy(ctx),
531+
Steps: []resource.TestStep{
532+
{
533+
Config: testAccKeyConfig_ignoreTags(rName, "key1", "value1", "key2", "value2"),
534+
Check: resource.ComposeTestCheckFunc(
535+
testAccCheckKeyExists(ctx, resourceName, &key),
536+
resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
537+
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
538+
resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
539+
),
540+
},
541+
// Add an ignored tag.
542+
{
543+
Config: testAccKeyConfig_ignoreTags(rName, "key1", "value1", "key2", "value2"),
544+
Check: resource.ComposeTestCheckFunc(
545+
testAccCheckKeyAddTag(ctx, &key, "ignkey1", "ignvalue1"),
546+
),
547+
},
548+
{
549+
Config: testAccKeyConfig_ignoreTags(rName, "key1", "value1updated", "key3", "value3"),
550+
Check: resource.ComposeTestCheckFunc(
551+
testAccCheckKeyExists(ctx, resourceName, &key),
552+
resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
553+
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"),
554+
resource.TestCheckResourceAttr(resourceName, "tags.key3", "value3"),
555+
),
556+
},
557+
},
558+
})
559+
}
560+
519561
func testAccCheckKeyHasPolicy(ctx context.Context, name string, expectedPolicyText string) resource.TestCheckFunc {
520562
return func(s *terraform.State) error {
521563
rs, ok := s.RootModule().Resources[name]
@@ -605,6 +647,24 @@ func testAccCheckKeyExists(ctx context.Context, name string, key *kms.KeyMetadat
605647
}
606648
}
607649

650+
func testAccCheckKeyAddTag(ctx context.Context, key *kms.KeyMetadata, tagKey, tagValue string) resource.TestCheckFunc {
651+
return func(s *terraform.State) error {
652+
conn := acctest.Provider.Meta().(*conns.AWSClient).KMSConn(ctx)
653+
654+
input := &kms.TagResourceInput{
655+
KeyId: key.KeyId,
656+
Tags: []*kms.Tag{{
657+
TagKey: aws.String(tagKey),
658+
TagValue: aws.String(tagValue),
659+
}},
660+
}
661+
662+
_, err := conn.TagResourceWithContext(ctx, input)
663+
664+
return err
665+
}
666+
}
667+
608668
func testAccKeyConfig_basic() string {
609669
return `
610670
resource "aws_kms_key" "test" {}
@@ -1091,3 +1151,29 @@ resource "aws_kms_key" "test" {
10911151
}
10921152
`, rName)
10931153
}
1154+
1155+
func testAccKeyConfig_ignoreTags(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string {
1156+
// lintignore:AT004
1157+
return fmt.Sprintf(`
1158+
provider "aws" {
1159+
default_tags {
1160+
tags = {
1161+
"defkey1" = "defvalue1"
1162+
}
1163+
}
1164+
ignore_tags {
1165+
keys = ["ignkey1"]
1166+
}
1167+
}
1168+
1169+
resource "aws_kms_key" "test" {
1170+
description = %[1]q
1171+
deletion_window_in_days = 7
1172+
1173+
tags = {
1174+
%[2]q = %[3]q
1175+
%[4]q = %[5]q
1176+
}
1177+
}
1178+
`, rName, tagKey1, tagValue1, tagKey2, tagValue2)
1179+
}

internal/service/kms/tags_gen.go

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/tags/key_value_tags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func (tags KeyValueTags) IgnoreServerlessApplicationRepository() KeyValueTags {
177177
return result
178178
}
179179

180-
// IgnoreAWS returns non-system tag keys.
180+
// IgnoreSystem returns non-system tag keys.
181181
// The ignored keys vary on the specified service.
182182
func (tags KeyValueTags) IgnoreSystem(serviceName string) KeyValueTags {
183183
switch serviceName {

0 commit comments

Comments
 (0)