diff --git a/aws/resource_aws_kinesis_firehose_delivery_stream.go b/aws/resource_aws_kinesis_firehose_delivery_stream.go index c3998de9548..60265f3267a 100644 --- a/aws/resource_aws_kinesis_firehose_delivery_stream.go +++ b/aws/resource_aws_kinesis_firehose_delivery_stream.go @@ -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 ( @@ -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) } @@ -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) } diff --git a/aws/resource_aws_kinesis_firehose_delivery_stream_test.go b/aws/resource_aws_kinesis_firehose_delivery_stream_test.go index 2b5b611a684..0eeb7ec0565 100644 --- a/aws/resource_aws_kinesis_firehose_delivery_stream_test.go +++ b/aws/resource_aws_kinesis_firehose_delivery_stream_test.go @@ -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": "*" } ] } @@ -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 @@ -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) } @@ -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 @@ -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) } @@ -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 @@ -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) } @@ -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 @@ -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) } @@ -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 @@ -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) }