Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource/aws_kinesis_firehose_delivery_stream: Use IAM timeout constant for retries, add LakeFormation permissions retries and configuration to tests #17254

Merged
merged 2 commits into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/17254.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_kinesis_firehose_delivery_stream: Use standard retry timeout for IAM eventual consistency and retry on LakeFormation access errors
```
52 changes: 28 additions & 24 deletions aws/resource_aws_kinesis_firehose_delivery_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/firehose"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
iamwaiter "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iam/waiter"
)

const (
Expand Down Expand Up @@ -2515,30 +2517,31 @@ func resourceAwsKinesisFirehoseDeliveryStreamCreate(d *schema.ResourceData, meta
createInput.Tags = keyvaluetags.New(v.(map[string]interface{})).IgnoreAws().FirehoseTags()
}

err := resource.Retry(1*time.Minute, func() *resource.RetryError {
err := resource.Retry(iamwaiter.PropagationTimeout, func() *resource.RetryError {
_, err := conn.CreateDeliveryStream(createInput)
if err != nil {
log.Printf("[DEBUG] Error creating Firehose Delivery Stream: %s", err)
// Access was denied when calling Glue. Please ensure that the role specified in the data format conversion configuration has the necessary permissions.
if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Access was denied") {
return resource.RetryableError(err)
}

// Retry for IAM eventual consistency
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "is not authorized to") {
if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "is not authorized to") {
return resource.RetryableError(err)
}
// Retry for IAM eventual consistency
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "Please make sure the role specified in VpcConfiguration has permissions") {

if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Please make sure the role specified in VpcConfiguration has permissions") {
return resource.RetryableError(err)
}

// InvalidArgumentException: Verify that the IAM role has access to the ElasticSearch domain.
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "Verify that the IAM role has access") {
if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Verify that the IAM role has access") {
return resource.RetryableError(err)
}
// IAM roles can take ~10 seconds to propagate in AWS:
// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "Firehose is unable to assume role") {
log.Printf("[DEBUG] Firehose could not assume role referenced, retrying...")

if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Firehose is unable to assume role") {
return resource.RetryableError(err)
}
// Not retryable

return resource.NonRetryableError(err)
}

Expand Down Expand Up @@ -2660,30 +2663,31 @@ func resourceAwsKinesisFirehoseDeliveryStreamUpdate(d *schema.ResourceData, meta
}
}

err := resource.Retry(1*time.Minute, func() *resource.RetryError {
err := resource.Retry(iamwaiter.PropagationTimeout, func() *resource.RetryError {
_, err := conn.UpdateDestination(updateInput)
if err != nil {
log.Printf("[DEBUG] Error updating Firehose Delivery Stream: %s", err)
// Access was denied when calling Glue. Please ensure that the role specified in the data format conversion configuration has the necessary permissions.
if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Access was denied") {
return resource.RetryableError(err)
}

// Retry for IAM eventual consistency
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "is not authorized to") {
if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "is not authorized to") {
return resource.RetryableError(err)
}
// Retry for IAM eventual consistency
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "Please make sure the role specified in VpcConfiguration has permissions") {

if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Please make sure the role specified in VpcConfiguration has permissions") {
return resource.RetryableError(err)
}

// InvalidArgumentException: Verify that the IAM role has access to the ElasticSearch domain.
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "Verify that the IAM role has access") {
if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Verify that the IAM role has access") {
return resource.RetryableError(err)
}
// IAM roles can take ~10 seconds to propagate in AWS:
// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console
if isAWSErr(err, firehose.ErrCodeInvalidArgumentException, "Firehose is unable to assume role") {
log.Printf("[DEBUG] Firehose could not assume role referenced, retrying...")

if tfawserr.ErrMessageContains(err, firehose.ErrCodeInvalidArgumentException, "Firehose is unable to assume role") {
return resource.RetryableError(err)
}
// Not retryable

return resource.NonRetryableError(err)
}

Expand Down
70 changes: 65 additions & 5 deletions aws/resource_aws_kinesis_firehose_delivery_stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1833,11 +1833,21 @@ resource "aws_iam_role_policy" "firehose" {
"Sid": "GlueAccess",
"Effect": "Allow",
"Action": [
"glue:GetTable",
"glue:GetTableVersion",
"glue:GetTableVersions"
],
"Resource": [
"*"
]
},
{
"Sid": "LakeFormationDataAccess",
"Effect": "Allow",
"Action": [
"lakeformation:GetDataAccess"
],
"Resource": "*"
}
]
}
Expand Down Expand Up @@ -2226,6 +2236,16 @@ resource "aws_glue_catalog_table" "test" {
}
}

resource "aws_lakeformation_permissions" "test" {
permissions = ["ALL"]
principal = aws_iam_role.firehose.arn

table {
database_name = aws_glue_catalog_database.test.name
name = aws_glue_catalog_table.test.name
}
}

resource "aws_kinesis_firehose_delivery_stream" "test" {
destination = "extended_s3"
name = %[1]q
Expand Down Expand Up @@ -2259,7 +2279,7 @@ resource "aws_kinesis_firehose_delivery_stream" "test" {
}
}

depends_on = [aws_iam_role_policy.firehose]
depends_on = [aws_iam_role_policy.firehose, aws_lakeformation_permissions.test]
}
`, rName, enabled)
}
Expand All @@ -2282,6 +2302,16 @@ resource "aws_glue_catalog_table" "test" {
}
}

resource "aws_lakeformation_permissions" "test" {
permissions = ["ALL"]
principal = aws_iam_role.firehose.arn

table {
database_name = aws_glue_catalog_database.test.name
name = aws_glue_catalog_table.test.name
}
}

resource "aws_kinesis_firehose_delivery_stream" "test" {
destination = "extended_s3"
name = %[1]q
Expand Down Expand Up @@ -2313,7 +2343,7 @@ resource "aws_kinesis_firehose_delivery_stream" "test" {
}
}

depends_on = [aws_iam_role_policy.firehose]
depends_on = [aws_iam_role_policy.firehose, aws_lakeformation_permissions.test]
}
`, rName)
}
Expand Down Expand Up @@ -2350,6 +2380,16 @@ resource "aws_glue_catalog_table" "test" {
}
}

resource "aws_lakeformation_permissions" "test" {
permissions = ["ALL"]
principal = aws_iam_role.firehose.arn

table {
database_name = aws_glue_catalog_database.test.name
name = aws_glue_catalog_table.test.name
}
}

resource "aws_kinesis_firehose_delivery_stream" "test" {
destination = "extended_s3"
name = %[1]q
Expand Down Expand Up @@ -2381,7 +2421,7 @@ resource "aws_kinesis_firehose_delivery_stream" "test" {
}
}

depends_on = [aws_iam_role_policy.firehose]
depends_on = [aws_iam_role_policy.firehose, aws_lakeformation_permissions.test]
}
`, rName)
}
Expand All @@ -2404,6 +2444,16 @@ resource "aws_glue_catalog_table" "test" {
}
}

resource "aws_lakeformation_permissions" "test" {
permissions = ["ALL"]
principal = aws_iam_role.firehose.arn

table {
database_name = aws_glue_catalog_database.test.name
name = aws_glue_catalog_table.test.name
}
}

resource "aws_kinesis_firehose_delivery_stream" "test" {
destination = "extended_s3"
name = %[1]q
Expand Down Expand Up @@ -2435,7 +2485,7 @@ resource "aws_kinesis_firehose_delivery_stream" "test" {
}
}

depends_on = [aws_iam_role_policy.firehose]
depends_on = [aws_iam_role_policy.firehose, aws_lakeformation_permissions.test]
}
`, rName)
}
Expand All @@ -2458,6 +2508,16 @@ resource "aws_glue_catalog_table" "test" {
}
}

resource "aws_lakeformation_permissions" "test" {
permissions = ["ALL"]
principal = aws_iam_role.firehose.arn

table {
database_name = aws_glue_catalog_database.test.name
name = aws_glue_catalog_table.test.name
}
}

resource "aws_kinesis_firehose_delivery_stream" "test" {
destination = "extended_s3"
name = %[1]q
Expand Down Expand Up @@ -2489,7 +2549,7 @@ resource "aws_kinesis_firehose_delivery_stream" "test" {
}
}

depends_on = [aws_iam_role_policy.firehose]
depends_on = [aws_iam_role_policy.firehose, aws_lakeformation_permissions.test]
}
`, rName)
}
Expand Down