Skip to content

Commit

Permalink
Merge pull request #22840 from thatderek/cloudformation-stack-iam-fix
Browse files Browse the repository at this point in the history
aws_cloudformation_stack: use retry logic on IAM role error
  • Loading branch information
ewbankkit authored Jan 31, 2022
2 parents 28bf9be + 16c1121 commit f9b8ec5
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .changelog/22840.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_cloudformation_stack: Retry resource Create and Update for IAM eventual consistency
```
43 changes: 32 additions & 11 deletions internal/service/cloudformation/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tfiam "github.com/hashicorp/terraform-provider-aws/internal/service/iam"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

Expand Down Expand Up @@ -181,13 +183,24 @@ func resourceStackCreate(d *schema.ResourceData, meta interface{}) error {
}

log.Printf("[DEBUG] Creating CloudFormation Stack: %s", input)
output, err := conn.CreateStack(input)
outputRaw, err := tfresource.RetryWhen(tfiam.PropagationTimeout,
func() (interface{}, error) {
return conn.CreateStack(input)
},
func(err error) (bool, error) {
if tfawserr.ErrMessageContains(err, "ValidationError", "is invalid or cannot be assumed") {
return true, err
}

return false, err
},
)

if err != nil {
return fmt.Errorf("error creating CloudFormation Stack (%s): %w", name, err)
}

d.SetId(aws.StringValue(output.StackId))
d.SetId(aws.StringValue(outputRaw.(*cloudformation.CreateStackOutput).StackId))

if _, err := WaitStackCreated(conn, d.Id(), requestToken, d.Timeout(schema.TimeoutCreate)); err != nil {
return fmt.Errorf("error waiting for CloudFormation Stack (%s) create: %w", d.Id(), err)
Expand Down Expand Up @@ -358,21 +371,29 @@ func resourceStackUpdate(d *schema.ResourceData, meta interface{}) error {
input.RoleARN = aws.String(d.Get("iam_role_arn").(string))
}

log.Printf("[DEBUG] Updating CloudFormation stack: %s", input)
_, err := conn.UpdateStack(input)
if tfawserr.ErrMessageContains(err, "ValidationError", "No updates are to be performed.") {
log.Printf("[DEBUG] Current CloudFormation stack has no updates")
} else if err != nil {
return fmt.Errorf("error updating CloudFormation stack (%s): %w", d.Id(), err)
log.Printf("[DEBUG] Updating CloudFormation Stack: %s", input)
_, err := tfresource.RetryWhen(tfiam.PropagationTimeout,
func() (interface{}, error) {
return conn.UpdateStack(input)
},
func(err error) (bool, error) {
if tfawserr.ErrMessageContains(err, "ValidationError", "is invalid or cannot be assumed") {
return true, err
}

return false, err
},
)

if err != nil {
return fmt.Errorf("error updating CloudFormation Stack (%s): %w", d.Id(), err)
}

_, err = WaitStackUpdated(conn, d.Id(), requestToken, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error waiting for CloudFormation Stack update: %w", err)
return fmt.Errorf("error waiting for CloudFormation Stack (%s) update: %w", d.Id(), err)
}

log.Printf("[INFO] CloudFormation stack (%s) updated", d.Id())

return resourceStackRead(d, meta)
}

Expand Down

0 comments on commit f9b8ec5

Please sign in to comment.