diff --git a/internal/generate/tags/main.go b/internal/generate/tags/main.go index 256fac08b9e0..79d1541dbdaf 100644 --- a/internal/generate/tags/main.go +++ b/internal/generate/tags/main.go @@ -1,6 +1,9 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 +//go:build generate +// +build generate + package main import ( @@ -36,7 +39,6 @@ var ( serviceTagsSlice = flag.Bool("ServiceTagsSlice", false, "whether to generate service tags for slice") untagInNeedTagType = flag.Bool("UntagInNeedTagType", false, "whether Untag input needs tag type") updateTags = flag.Bool("UpdateTags", false, "whether to generate UpdateTags") - updateTagsForResource = flag.Bool("UpdateTagsForResource", false, "whether to generate UpdateTagsForResource") updateTagsNoIgnoreSystem = flag.Bool("UpdateTagsNoIgnoreSystem", false, "whether to not ignore system tags in UpdateTags") waitForPropagation = flag.Bool("Wait", false, "whether to generate WaitTagsPropagated") @@ -79,9 +81,9 @@ var ( untagInTagsElem = flag.String("UntagInTagsElem", "TagKeys", "untagInTagsElem") untagOp = flag.String("UntagOp", "UntagResource", "untagOp") updateTagsFunc = flag.String("UpdateTagsFunc", defaultUpdateTagsFunc, "updateTagsFunc") - updateTagsForResourceFunc = flag.String("UpdateTagsForResourceFunc", "updateTagsForResource", "updateTagsForResourceFunc") waitTagsPropagatedFunc = flag.String("WaitFunc", defaultWaitTagsPropagatedFunc, "waitFunc") waitContinuousOccurence = flag.Int("WaitContinuousOccurence", 0, "ContinuousTargetOccurence for Wait function") + waitFuncComparator = flag.String("WaitFuncComparator", "Equal", "waitFuncComparator") waitDelay = flag.Duration("WaitDelay", 0, "Delay for Wait function") waitMinTimeout = flag.Duration("WaitMinTimeout", 0, `"MinTimeout" (minimum poll interval) for Wait function`) waitPollInterval = flag.Duration("WaitPollInterval", 0, "PollInterval for Wait function") @@ -108,14 +110,13 @@ func usage() { } type TemplateBody struct { - getTag string - header string - listTags string - serviceTagsMap string - serviceTagsSlice string - updateTags string - updateTagsForResource string - waitTagsPropagated string + getTag string + header string + listTags string + serviceTagsMap string + serviceTagsSlice string + updateTags string + waitTagsPropagated string } func newTemplateBody(version int, kvtValues bool) *TemplateBody { @@ -133,25 +134,23 @@ func newTemplateBody(version int, kvtValues bool) *TemplateBody { case sdkV2: if kvtValues { return &TemplateBody{ - getTag: "\n" + v2.GetTagBody, - header: v2.HeaderBody, - listTags: "\n" + v2.ListTagsBody, - serviceTagsMap: "\n" + v2.ServiceTagsValueMapBody, - serviceTagsSlice: "\n" + v2.ServiceTagsSliceBody, - updateTags: "\n" + v2.UpdateTagsBody, - updateTagsForResource: "\n" + v2.UpdateTagsForResourceBody, - waitTagsPropagated: "\n" + v2.WaitTagsPropagatedBody, + getTag: "\n" + v2.GetTagBody, + header: v2.HeaderBody, + listTags: "\n" + v2.ListTagsBody, + serviceTagsMap: "\n" + v2.ServiceTagsValueMapBody, + serviceTagsSlice: "\n" + v2.ServiceTagsSliceBody, + updateTags: "\n" + v2.UpdateTagsBody, + waitTagsPropagated: "\n" + v2.WaitTagsPropagatedBody, } } return &TemplateBody{ - getTag: "\n" + v2.GetTagBody, - header: v2.HeaderBody, - listTags: "\n" + v2.ListTagsBody, - serviceTagsMap: "\n" + v2.ServiceTagsMapBody, - serviceTagsSlice: "\n" + v2.ServiceTagsSliceBody, - updateTags: "\n" + v2.UpdateTagsBody, - updateTagsForResource: "\n" + v2.UpdateTagsForResourceBody, - waitTagsPropagated: "\n" + v2.WaitTagsPropagatedBody, + getTag: "\n" + v2.GetTagBody, + header: v2.HeaderBody, + listTags: "\n" + v2.ListTagsBody, + serviceTagsMap: "\n" + v2.ServiceTagsMapBody, + serviceTagsSlice: "\n" + v2.ServiceTagsSliceBody, + updateTags: "\n" + v2.UpdateTagsBody, + waitTagsPropagated: "\n" + v2.WaitTagsPropagatedBody, } default: return nil @@ -211,13 +210,12 @@ type TemplateData struct { UntagInTagsElem string UntagOp string UpdateTagsFunc string - UpdateTagsForResource bool - UpdateTagsForResourceFunc string UpdateTagsIgnoreSystem bool WaitForPropagation bool WaitTagsPropagatedFunc string WaitContinuousOccurence int WaitDelay string + WaitFuncComparator string WaitMinTimeout string WaitPollInterval string WaitTimeout string @@ -372,9 +370,9 @@ func main() { UntagInTagsElem: *untagInTagsElem, UntagOp: *untagOp, UpdateTagsFunc: *updateTagsFunc, - UpdateTagsForResourceFunc: *updateTagsForResourceFunc, UpdateTagsIgnoreSystem: !*updateTagsNoIgnoreSystem, WaitForPropagation: *waitForPropagation, + WaitFuncComparator: *waitFuncComparator, WaitTagsPropagatedFunc: *waitTagsPropagatedFunc, WaitContinuousOccurence: *waitContinuousOccurence, WaitDelay: formatDuration(*waitDelay), @@ -432,12 +430,6 @@ func main() { } } - if *updateTagsForResource { - if err := d.WriteTemplate("updatetagsforresource", templateBody.updateTagsForResource, templateData); err != nil { - g.Fatalf("generating file (%s): %s", filename, err) - } - } - if *waitForPropagation { if err := d.WriteTemplate("waittagspropagated", templateBody.waitTagsPropagated, templateData); err != nil { g.Fatalf("generating file (%s): %s", filename, err) diff --git a/internal/generate/tags/templates/v2/update_tags_body.gtpl b/internal/generate/tags/templates/v2/update_tags_body.gtpl index 91db91dd85db..3ed05b03df74 100644 --- a/internal/generate/tags/templates/v2/update_tags_body.gtpl +++ b/internal/generate/tags/templates/v2/update_tags_body.gtpl @@ -164,8 +164,7 @@ func {{ .UpdateTagsFunc }}(ctx context.Context, conn {{ .ClientType }}, identifi {{ if .WaitForPropagation }} if len(removedTags) > 0 || len(updatedTags) > 0 { - check := checkFunc(ctx, conn, newTags, identifier, optFns...) - if err := {{ .WaitTagsPropagatedFunc }}(ctx, newTags, check); err != nil { + if err := {{ .WaitTagsPropagatedFunc }}(ctx, conn, identifier, newTags, optFns...); err != nil { return fmt.Errorf("waiting for resource (%s) tag propagation: %w", identifier, err) } } diff --git a/internal/generate/tags/templates/v2/update_tags_for_resource_body.gtpl b/internal/generate/tags/templates/v2/update_tags_for_resource_body.gtpl deleted file mode 100644 index 40242dab2ce6..000000000000 --- a/internal/generate/tags/templates/v2/update_tags_for_resource_body.gtpl +++ /dev/null @@ -1,195 +0,0 @@ -// {{ .UpdateTagsForResourceFunc }} updates tags in generated tag resource -// The identifier is typically the Amazon Resource Name (ARN), although -// it may also be a different identifier depending on the service. -{{if .TagTypeAddBoolElem -}} -func {{ .UpdateTagsForResourceFunc }}(ctx context.Context, conn {{ .ClientType }}, identifier{{ if .TagResTypeElem }}, resourceType{{ end }} string, oldTagsSet, newTagsSet any, optFns ...func(*{{ .AWSService }}.Options)) error { - oldTags := {{ .KeyValueTagsFunc }}(ctx, oldTagsSet, identifier{{ if .TagResTypeElem }}, resourceType{{ end }}) - newTags := {{ .KeyValueTagsFunc }}(ctx, newTagsSet, identifier{{ if .TagResTypeElem }}, resourceType{{ end }}) -{{- else -}} -func {{ .UpdateTagsForResourceFunc }}(ctx context.Context, conn {{ .ClientType }}, identifier{{ if .TagResTypeElem }}, resourceType{{ end }} string, oldTagsMap, newTagsMap any, optFns ...func(*{{ .AWSService }}.Options)) error { - oldTags := tftags.New(ctx, oldTagsMap) - newTags := tftags.New(ctx, newTagsMap) -{{- end }} - - ctx = tflog.SetField(ctx, logging.KeyResourceId, identifier) - - {{- if eq (.TagOp) (.UntagOp) }} - - removedTags := oldTags.Removed(newTags) - {{- if .UpdateTagsIgnoreSystem }} - removedTags = removedTags.IgnoreSystem(names.{{ .ProviderNameUpper }}) - {{- end }} - updatedTags := oldTags.Updated(newTags) - {{- if .UpdateTagsIgnoreSystem }} - updatedTags = updatedTags.IgnoreSystem(names.{{ .ProviderNameUpper }}) - {{- end }} - - // Ensure we do not send empty requests. - if len(removedTags) == 0 && len(updatedTags) == 0 { - return nil - } - - input := &{{ .AWSService }}.{{ .TagOp }}Input{ - {{- if not ( .TagTypeIDElem ) }} - {{- if .TagInIDNeedSlice }} - {{ .TagInIDElem }}: aws.StringSlice([]string{identifier}), - {{- else if .TagInIDNeedValueSlice }} - {{ .TagInIDElem }}: []string{identifier}, - {{- else }} - {{ .TagInIDElem }}: aws.String(identifier), - {{- end }} - {{- if .TagResTypeElem }} - {{- if .TagResTypeElemType }} - {{ .TagResTypeElem }}: awstypes.{{ .TagResTypeElemType }}(resourceType), - {{- else }} - {{ .TagResTypeElem }}: aws.String(resourceType), - {{- end }} - {{- end }} - {{- end }} - } - - if len(updatedTags) > 0 { - input.{{ .TagInTagsElem }} = {{ .TagsFunc }}(updatedTags) - } - - if len(removedTags) > 0 { - {{- if .UntagInNeedTagType }} - input.{{ .UntagInTagsElem }} = {{ .TagsFunc }}(removedTags) - {{- else if .UntagInNeedTagKeyType }} - input.{{ .UntagInTagsElem }} = TagKeys(removedTags) - {{- else if .UntagInCustomVal }} - input.{{ .UntagInTagsElem }} = {{ .UntagInCustomVal }} - {{- else }} - input.{{ .UntagInTagsElem }} = removedTags.Keys() - {{- end }} - } - - _, err := conn.{{ .TagOp }}(ctx, input, optFns...) - - if err != nil { - return fmt.Errorf("tagging resource (%s): %w", identifier, err) - } - - {{- else }} - - removedTags := oldTags.Removed(newTags) - {{- if .UpdateTagsIgnoreSystem }} - removedTags = removedTags.IgnoreSystem(names.{{ .ProviderNameUpper }}) - {{- end }} - if len(removedTags) > 0 { - {{- if .TagOpBatchSize }} - for _, removedTags := range removedTags.Chunks({{ .TagOpBatchSize }}) { - {{- end }} - input := &{{ .TagPackage }}.{{ .UntagOp }}Input{ - {{- if not ( .TagTypeIDElem ) }} - {{- if .TagInIDNeedSlice }} - {{ .TagInIDElem }}: aws.StringSlice([]string{identifier}), - {{- else if .TagInIDNeedValueSlice }} - {{ .TagInIDElem }}: []string{identifier}, - {{- else }} - {{ .TagInIDElem }}: aws.String(identifier), - {{- end }} - {{- if .TagResTypeElem }} - {{- if .TagResTypeElemType }} - {{ .TagResTypeElem }}: awstypes.{{ .TagResTypeElemType }}(resourceType), - {{- else }} - {{ .TagResTypeElem }}: aws.String(resourceType), - {{- end }} - {{- end }} - {{- end }} - {{- if .UntagInNeedTagType }} - {{ .UntagInTagsElem }}: {{ .TagsFunc }}(removedTags), - {{- else if .UntagInNeedTagKeyType }} - {{ .UntagInTagsElem }}: TagKeys(removedTags), - {{- else if .UntagInCustomVal }} - {{ .UntagInTagsElem }}: {{ .UntagInCustomVal }}, - {{- else }} - {{ .UntagInTagsElem }}: removedTags.Keys(), - {{- end }} - } - - _, err := conn.{{ .UntagOp }}(ctx, input, optFns...) - - if err != nil { - return fmt.Errorf("untagging resource (%s): %w", identifier, err) - } - {{- if .TagOpBatchSize }} - } - {{- end }} - } - - updatedTags := oldTags.Updated(newTags) - {{- if .UpdateTagsIgnoreSystem }} - updatedTags = updatedTags.IgnoreSystem(names.{{ .ProviderNameUpper }}) - {{- end }} - if len(updatedTags) > 0 { - {{- if .TagOpBatchSize }} - for _, updatedTags := range updatedTags.Chunks({{ .TagOpBatchSize }}) { - {{- end }} - input := &{{ .TagPackage }}.{{ .TagOp }}Input{ - {{- if not ( .TagTypeIDElem ) }} - {{- if .TagInIDNeedSlice }} - {{ .TagInIDElem }}: aws.StringSlice([]string{identifier}), - {{- else if .TagInIDNeedValueSlice }} - {{ .TagInIDElem }}: []string{identifier}, - {{- else }} - {{ .TagInIDElem }}: aws.String(identifier), - {{- end }} - {{- if .TagResTypeElem }} - {{- if .TagResTypeElemType }} - {{ .TagResTypeElem }}: awstypes.{{ .TagResTypeElemType }}(resourceType), - {{- else }} - {{ .TagResTypeElem }}: aws.String(resourceType), - {{- end }} - {{- end }} - {{- end }} - {{- if .TagInCustomVal }} - {{ .TagInTagsElem }}: {{ .TagInCustomVal }}, - {{- else }} - {{ .TagInTagsElem }}: {{ .TagsFunc }}(updatedTags), - {{- end }} - } - - _, err := conn.{{ .TagOp }}(ctx, input, optFns...) - - if err != nil { - return fmt.Errorf("tagging resource (%s): %w", identifier, err) - } - {{- if .TagOpBatchSize }} - } - {{- end }} - } - - {{- end }} - - {{ if .WaitForPropagation }} - if len(removedTags) > 0 || len(updatedTags) > 0 { - checkFunc := func(ctx context.Context, conn {{ .ClientType }}, tags tftags.KeyValueTags, id string, optFns ...func(*{{ .AWSService }}.Options)) func() (bool, error) { - return func() (bool, error) { - output, err := listTags(ctx, conn, id, optFns...) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - if inContext, ok := tftags.FromContext(ctx); ok { - tags = tags.IgnoreConfig(inContext.IgnoreConfig) - output = output.IgnoreConfig(inContext.IgnoreConfig) - } - - return output.ContainsAll(tags), nil - } - } - - if err := {{ .WaitTagsPropagatedFunc }}(ctx, newTags, checkFunc(ctx, conn, newTags, identifier, optFns...)); err != nil { - return fmt.Errorf("waiting for resource (%s) tag propagation: %w", identifier, err) - } - } - {{- end }} - - return nil -} diff --git a/internal/generate/tags/templates/v2/v2.go b/internal/generate/tags/templates/v2/v2.go index bd46d2521e5d..0ea733e812d4 100644 --- a/internal/generate/tags/templates/v2/v2.go +++ b/internal/generate/tags/templates/v2/v2.go @@ -31,8 +31,5 @@ var ServiceTagsSliceBody string //go:embed update_tags_body.gtpl var UpdateTagsBody string -//go:embed update_tags_for_resource_body.gtpl -var UpdateTagsForResourceBody string - //go:embed wait_tags_propagated_body.gtpl var WaitTagsPropagatedBody string diff --git a/internal/generate/tags/templates/v2/wait_tags_propagated_body.gtpl b/internal/generate/tags/templates/v2/wait_tags_propagated_body.gtpl index 35f3887209e9..b6d83c8fbdb3 100644 --- a/internal/generate/tags/templates/v2/wait_tags_propagated_body.gtpl +++ b/internal/generate/tags/templates/v2/wait_tags_propagated_body.gtpl @@ -1,11 +1,29 @@ // {{ .WaitTagsPropagatedFunc }} waits for {{ .ServicePackage }} service tags to be propagated. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, tags tftags.KeyValueTags, checkFunc func() (bool, error)) error { +func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, conn {{ .ClientType }}, id string, tags tftags.KeyValueTags, optFns ...func(*{{ .AWSService }}.Options)) error { tflog.Debug(ctx, "Waiting for tag propagation", map[string]any{ names.AttrTags: tags, }) + checkFunc := func() (bool, error) { + output, err := {{ .ListTagsFunc }}(ctx, conn, id, optFns...) + + if tfresource.NotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + if inContext, ok := tftags.FromContext(ctx); ok { + tags = tags.IgnoreConfig(inContext.IgnoreConfig) + output = output.IgnoreConfig(inContext.IgnoreConfig) + } + + return output.{{ .WaitFuncComparator }}(tags), nil + } opts := tfresource.WaitOpts{ {{- if ne .WaitContinuousOccurence 0 }} ContinuousTargetOccurence: {{ .WaitContinuousOccurence }}, @@ -23,29 +41,3 @@ func {{ .WaitTagsPropagatedFunc }}(ctx context.Context, tags tftags.KeyValueTags return tfresource.WaitUntil(ctx, {{ .WaitTimeout }}, checkFunc, opts) } - -// checkFunc returns a function that checks if the tags are propagated. -func checkFunc(ctx context.Context, conn {{ .ClientType }}, tags tftags.KeyValueTags, id string, optFns ...func(*{{ .AWSService }}.Options)) func() (bool, error) { - return func() (bool, error) { - output, err := listTags(ctx, conn, id, optFns...) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - if inContext, ok := tftags.FromContext(ctx); ok { - tags = tags.IgnoreConfig(inContext.IgnoreConfig) - output = output.IgnoreConfig(inContext.IgnoreConfig) - } - - {{- if .UpdateTagsForResource }} - return output.ContainsAll(tags), nil - {{- else }} - return output.Equal(tags), nil - {{- end }} - } -} diff --git a/internal/service/dynamodb/generate.go b/internal/service/dynamodb/generate.go index cd0dc787a857..d921cb4d67c6 100644 --- a/internal/service/dynamodb/generate.go +++ b/internal/service/dynamodb/generate.go @@ -1,8 +1,8 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tagresource/main.go -UpdateTagsFunc=updateTagsForResource -//go:generate go run ../../generate/tags/main.go -GetTag -ListTags -ListTagsOp=ListTagsOfResource -ServiceTagsSlice -UpdateTags -Wait -WaitContinuousOccurence 2 -WaitMinTimeout 1s -WaitTimeout 2m -UpdateTagsForResource -ParentNotFoundErrCode=ResourceNotFoundException +//go:generate go run ../../generate/tagresource/main.go +//go:generate go run ../../generate/tags/main.go -GetTag -ListTags -ListTagsOp=ListTagsOfResource -ServiceTagsSlice -UpdateTags -Wait -WaitContinuousOccurence 2 -WaitMinTimeout 1s -WaitTimeout 2m -WaitFuncComparator=ContainsAll -ParentNotFoundErrCode=ResourceNotFoundException //go:generate go run ../../generate/servicepackage/main.go //go:generate go run ../../generate/listpages/main.go -ListOps=ListBackups -InputPaginator=ExclusiveStartBackupArn -OutputPaginator=LastEvaluatedBackupArn -- list_backups_pages_gen.go //go:generate go run ../../generate/tagstests/main.go diff --git a/internal/service/dynamodb/tag_gen.go b/internal/service/dynamodb/tag_gen.go index 7fbb023cd266..1b45fa3999d0 100644 --- a/internal/service/dynamodb/tag_gen.go +++ b/internal/service/dynamodb/tag_gen.go @@ -54,7 +54,7 @@ func resourceTagCreate(ctx context.Context, d *schema.ResourceData, meta interfa key := d.Get(names.AttrKey).(string) value := d.Get(names.AttrValue).(string) - if err := updateTagsForResource(ctx, conn, identifier, nil, map[string]string{key: value}); err != nil { + if err := updateTags(ctx, conn, identifier, nil, map[string]string{key: value}); err != nil { return sdkdiag.AppendErrorf(diags, "creating %s resource (%s) tag (%s): %s", names.DynamoDB, identifier, key, err) } @@ -100,7 +100,7 @@ func resourceTagUpdate(ctx context.Context, d *schema.ResourceData, meta interfa return sdkdiag.AppendFromErr(diags, err) } - if err := updateTagsForResource(ctx, conn, identifier, nil, map[string]string{key: d.Get(names.AttrValue).(string)}); err != nil { + if err := updateTags(ctx, conn, identifier, nil, map[string]string{key: d.Get(names.AttrValue).(string)}); err != nil { return sdkdiag.AppendErrorf(diags, "updating %s resource (%s) tag (%s): %s", names.DynamoDB, identifier, key, err) } @@ -116,7 +116,7 @@ func resourceTagDelete(ctx context.Context, d *schema.ResourceData, meta interfa return sdkdiag.AppendFromErr(diags, err) } - if err := updateTagsForResource(ctx, conn, identifier, map[string]string{key: d.Get(names.AttrValue).(string)}, nil); err != nil { + if err := updateTags(ctx, conn, identifier, map[string]string{key: d.Get(names.AttrValue).(string)}, nil); err != nil { return sdkdiag.AppendErrorf(diags, "deleting %s resource (%s) tag (%s): %s", names.DynamoDB, identifier, key, err) } diff --git a/internal/service/dynamodb/tags_gen.go b/internal/service/dynamodb/tags_gen.go index 8d38c0088f5a..31e8940bc124 100644 --- a/internal/service/dynamodb/tags_gen.go +++ b/internal/service/dynamodb/tags_gen.go @@ -167,8 +167,7 @@ func updateTags(ctx context.Context, conn *dynamodb.Client, identifier string, o } if len(removedTags) > 0 || len(updatedTags) > 0 { - check := checkFunc(ctx, conn, newTags, identifier, optFns...) - if err := waitTagsPropagated(ctx, newTags, check); err != nil { + if err := waitTagsPropagated(ctx, conn, identifier, newTags, optFns...); err != nil { return fmt.Errorf("waiting for resource (%s) tag propagation: %w", identifier, err) } } @@ -182,94 +181,15 @@ func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier st return updateTags(ctx, meta.(*conns.AWSClient).DynamoDBClient(ctx), identifier, oldTags, newTags) } -// updateTagsForResource updates tags in generated tag resource -// The identifier is typically the Amazon Resource Name (ARN), although -// it may also be a different identifier depending on the service. -func updateTagsForResource(ctx context.Context, conn *dynamodb.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*dynamodb.Options)) error { - oldTags := tftags.New(ctx, oldTagsMap) - newTags := tftags.New(ctx, newTagsMap) - - ctx = tflog.SetField(ctx, logging.KeyResourceId, identifier) - - removedTags := oldTags.Removed(newTags) - removedTags = removedTags.IgnoreSystem(names.DynamoDB) - if len(removedTags) > 0 { - input := &dynamodb.UntagResourceInput{ - ResourceArn: aws.String(identifier), - TagKeys: removedTags.Keys(), - } - - _, err := conn.UntagResource(ctx, input, optFns...) - - if err != nil { - return fmt.Errorf("untagging resource (%s): %w", identifier, err) - } - } - - updatedTags := oldTags.Updated(newTags) - updatedTags = updatedTags.IgnoreSystem(names.DynamoDB) - if len(updatedTags) > 0 { - input := &dynamodb.TagResourceInput{ - ResourceArn: aws.String(identifier), - Tags: Tags(updatedTags), - } - - _, err := conn.TagResource(ctx, input, optFns...) - - if err != nil { - return fmt.Errorf("tagging resource (%s): %w", identifier, err) - } - } - - if len(removedTags) > 0 || len(updatedTags) > 0 { - checkFunc := func(ctx context.Context, conn *dynamodb.Client, tags tftags.KeyValueTags, id string, optFns ...func(*dynamodb.Options)) func() (bool, error) { - return func() (bool, error) { - output, err := listTags(ctx, conn, id, optFns...) - - if tfresource.NotFound(err) { - return false, nil - } - - if err != nil { - return false, err - } - - if inContext, ok := tftags.FromContext(ctx); ok { - tags = tags.IgnoreConfig(inContext.IgnoreConfig) - output = output.IgnoreConfig(inContext.IgnoreConfig) - } - - return output.ContainsAll(tags), nil - } - } - - if err := waitTagsPropagated(ctx, newTags, checkFunc(ctx, conn, newTags, identifier, optFns...)); err != nil { - return fmt.Errorf("waiting for resource (%s) tag propagation: %w", identifier, err) - } - } - - return nil -} - // waitTagsPropagated waits for dynamodb service tags to be propagated. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func waitTagsPropagated(ctx context.Context, tags tftags.KeyValueTags, checkFunc func() (bool, error)) error { +func waitTagsPropagated(ctx context.Context, conn *dynamodb.Client, id string, tags tftags.KeyValueTags, optFns ...func(*dynamodb.Options)) error { tflog.Debug(ctx, "Waiting for tag propagation", map[string]any{ names.AttrTags: tags, }) - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 2, - MinTimeout: 1 * time.Second, - } - - return tfresource.WaitUntil(ctx, 2*time.Minute, checkFunc, opts) -} - -// checkFunc returns a function that checks if the tags are propagated. -func checkFunc(ctx context.Context, conn *dynamodb.Client, tags tftags.KeyValueTags, id string, optFns ...func(*dynamodb.Options)) func() (bool, error) { - return func() (bool, error) { + checkFunc := func() (bool, error) { output, err := listTags(ctx, conn, id, optFns...) if tfresource.NotFound(err) { @@ -284,6 +204,13 @@ func checkFunc(ctx context.Context, conn *dynamodb.Client, tags tftags.KeyValueT tags = tags.IgnoreConfig(inContext.IgnoreConfig) output = output.IgnoreConfig(inContext.IgnoreConfig) } - return output.Equal(tags), nil + + return output.ContainsAll(tags), nil + } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 2, + MinTimeout: 1 * time.Second, } + + return tfresource.WaitUntil(ctx, 2*time.Minute, checkFunc, opts) } diff --git a/internal/service/kms/external_key.go b/internal/service/kms/external_key.go index 8409b4b1b81a..a94101232361 100644 --- a/internal/service/kms/external_key.go +++ b/internal/service/kms/external_key.go @@ -204,8 +204,7 @@ func resourceExternalKeyCreate(ctx context.Context, d *schema.ResourceData, meta } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { - check := checkFunc(ctx, conn, tags, d.Id()) - if err := waitTagsPropagated(ctx, tags, check); err != nil { + if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS External Key (%s) tag update: %s", d.Id(), err) } } diff --git a/internal/service/kms/key.go b/internal/service/kms/key.go index 457c91dfbdd5..2acb5a9851ae 100644 --- a/internal/service/kms/key.go +++ b/internal/service/kms/key.go @@ -218,8 +218,7 @@ func resourceKeyCreate(ctx context.Context, d *schema.ResourceData, meta interfa } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { - check := checkFunc(ctx, conn, tags, d.Id()) - if err := waitTagsPropagated(ctx, tags, check); err != nil { + if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Key (%s) tag update: %s", d.Id(), err) } } diff --git a/internal/service/kms/replica_external_key.go b/internal/service/kms/replica_external_key.go index 2ea9de2a6bb9..19f2228ebac4 100644 --- a/internal/service/kms/replica_external_key.go +++ b/internal/service/kms/replica_external_key.go @@ -199,8 +199,7 @@ func resourceReplicaExternalKeyCreate(ctx context.Context, d *schema.ResourceDat } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { - check := checkFunc(ctx, conn, tags, d.Id()) - if err := waitTagsPropagated(ctx, tags, check); err != nil { + if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica External Key (%s) tag update: %s", d.Id(), err) } } diff --git a/internal/service/kms/replica_key.go b/internal/service/kms/replica_key.go index 7fbe81eff0a7..6b9f7d5f9e6c 100644 --- a/internal/service/kms/replica_key.go +++ b/internal/service/kms/replica_key.go @@ -172,8 +172,7 @@ func resourceReplicaKeyCreate(ctx context.Context, d *schema.ResourceData, meta } if tags := KeyValueTags(ctx, getTagsIn(ctx)); len(tags) > 0 { - check := checkFunc(ctx, conn, tags, d.Id()) - if err := waitTagsPropagated(ctx, tags, check); err != nil { + if err := waitTagsPropagated(ctx, conn, d.Id(), tags); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for KMS Replica Key (%s) tag update: %s", d.Id(), err) } } diff --git a/internal/service/kms/tags_gen.go b/internal/service/kms/tags_gen.go index 23f72cc2e668..912093087640 100644 --- a/internal/service/kms/tags_gen.go +++ b/internal/service/kms/tags_gen.go @@ -156,8 +156,7 @@ func updateTags(ctx context.Context, conn *kms.Client, identifier string, oldTag } if len(removedTags) > 0 || len(updatedTags) > 0 { - check := checkFunc(ctx, conn, newTags, identifier, optFns...) - if err := waitTagsPropagated(ctx, newTags, check); err != nil { + if err := waitTagsPropagated(ctx, conn, identifier, newTags, optFns...); err != nil { return fmt.Errorf("waiting for resource (%s) tag propagation: %w", identifier, err) } } @@ -174,22 +173,12 @@ func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier st // waitTagsPropagated waits for kms service tags to be propagated. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func waitTagsPropagated(ctx context.Context, tags tftags.KeyValueTags, checkFunc func() (bool, error)) error { +func waitTagsPropagated(ctx context.Context, conn *kms.Client, id string, tags tftags.KeyValueTags, optFns ...func(*kms.Options)) error { tflog.Debug(ctx, "Waiting for tag propagation", map[string]any{ names.AttrTags: tags, }) - opts := tfresource.WaitOpts{ - ContinuousTargetOccurence: 5, - MinTimeout: 1 * time.Second, - } - - return tfresource.WaitUntil(ctx, 10*time.Minute, checkFunc, opts) -} - -// checkFunc returns a function that checks if the tags are propagated. -func checkFunc(ctx context.Context, conn *kms.Client, tags tftags.KeyValueTags, id string, optFns ...func(*kms.Options)) func() (bool, error) { - return func() (bool, error) { + checkFunc := func() (bool, error) { output, err := listTags(ctx, conn, id, optFns...) if tfresource.NotFound(err) { @@ -204,6 +193,13 @@ func checkFunc(ctx context.Context, conn *kms.Client, tags tftags.KeyValueTags, tags = tags.IgnoreConfig(inContext.IgnoreConfig) output = output.IgnoreConfig(inContext.IgnoreConfig) } + return output.Equal(tags), nil } + opts := tfresource.WaitOpts{ + ContinuousTargetOccurence: 5, + MinTimeout: 1 * time.Second, + } + + return tfresource.WaitUntil(ctx, 10*time.Minute, checkFunc, opts) }