From bfa4a881700c1498cb1b0085aff65c47a13db2b7 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Mon, 14 Dec 2015 11:12:06 -0800 Subject: [PATCH 1/5] Retry InvalidParameterValueException errors due to newly created resources --- ...esource_aws_lambda_event_source_mapping.go | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go index 70ca3a01c..4adb3f044 100644 --- a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go +++ b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go @@ -3,10 +3,13 @@ package aws import ( "fmt" "log" + "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/lambda" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" ) @@ -88,14 +91,28 @@ func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta inte Enabled: aws.Bool(d.Get("enabled").(bool)), } - eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params) + err := resource.Retry(1*time.Minute, func() error { + eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params) + if err != nil { + if awserr, ok := err.(awserr.Error); ok { + if awserr.Code() == "InvalidParameterValueException" { + // Retryable + return awserr + } + } + // Not retryable + return resource.RetryError{Err: err} + } + // No error + d.Set("uuid", eventSourceMappingConfiguration.UUID) + d.SetId(*eventSourceMappingConfiguration.UUID) + return nil + }) + if err != nil { return fmt.Errorf("Error creating Lambda event source mapping: %s", err) } - d.Set("uuid", eventSourceMappingConfiguration.UUID) - d.SetId(*eventSourceMappingConfiguration.UUID) - return resourceAwsLambdaEventSourceMappingRead(d, meta) } From f0d1193f8f6bb1885f2b0624a2852bc328387c44 Mon Sep 17 00:00:00 2001 From: clint shryock Date: Tue, 5 Jan 2016 10:17:20 -0600 Subject: [PATCH 2/5] provider/aws: Update Lambda create error handling to be more flexible --- builtin/providers/aws/resource_aws_lambda_function.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index 324016455..a45018276 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -157,7 +157,7 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e // IAM profiles 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 // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. - if awsErr.Code() == "InvalidParameterValueException" && strings.Contains(awsErr.Message(), "The role defined for the task cannot be assumed by Lambda.") { + if awsErr.Code() == "InvalidParameterValueException" && strings.Contains(awsErr.Message(), "cannot be assumed by Lambda.") { log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") time.Sleep(2 * time.Second) continue From 6b733a09eb5c6f209d082505927856876a5d1bb0 Mon Sep 17 00:00:00 2001 From: clint shryock Date: Tue, 5 Jan 2016 11:22:57 -0600 Subject: [PATCH 3/5] provider/aws: more retrying with Lambda --- ...esource_aws_lambda_event_source_mapping.go | 17 ++++++++++- .../aws/resource_aws_lambda_function.go | 30 ++++++++++--------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go index 4adb3f044..055c991cc 100644 --- a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go +++ b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go @@ -179,7 +179,22 @@ func resourceAwsLambdaEventSourceMappingUpdate(d *schema.ResourceData, meta inte Enabled: aws.Bool(d.Get("enabled").(bool)), } - _, err := conn.UpdateEventSourceMapping(params) + err := resource.Retry(1*time.Minute, func() error { + _, err := conn.UpdateEventSourceMapping(params) + if err != nil { + if awserr, ok := err.(awserr.Error); ok { + if awserr.Code() == "InvalidParameterValueException" { + // Retryable + return awserr + } + } + // Not retryable + return resource.RetryError{Err: err} + } + // No error + return nil + }) + if err != nil { return fmt.Errorf("Error updating Lambda event source mapping: %s", err) } diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index a45018276..b47a6a5a0 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -5,7 +5,6 @@ import ( "fmt" "io/ioutil" "log" - "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -15,6 +14,7 @@ import ( "errors" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" ) @@ -149,22 +149,24 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e Timeout: aws.Int64(int64(d.Get("timeout").(int))), } - var err error - for i := 0; i < 5; i++ { + // IAM profiles 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 + // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. + err := resource.Retry(1*time.Minute, func() error { _, err = conn.CreateFunction(params) - if awsErr, ok := err.(awserr.Error); ok { - - // IAM profiles 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 - // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. - if awsErr.Code() == "InvalidParameterValueException" && strings.Contains(awsErr.Message(), "cannot be assumed by Lambda.") { - log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") - time.Sleep(2 * time.Second) - continue + if err != nil { + if awserr, ok := err.(awserr.Error); ok { + if awserr.Code() == "InvalidParameterValueException" { + // Retryable + return awserr + } } + // Not retryable + return resource.RetryError{Err: err} } - break - } + // No error + return nil + }) if err != nil { return fmt.Errorf("Error creating Lambda function: %s", err) } From 312f2dd6e329cf7a8691fc21df5c0f808e66bd92 Mon Sep 17 00:00:00 2001 From: clint shryock Date: Tue, 5 Jan 2016 11:27:49 -0600 Subject: [PATCH 4/5] document why we retry in lambda source mapping --- .../aws/resource_aws_lambda_event_source_mapping.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go index 055c991cc..053b2adaf 100644 --- a/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go +++ b/builtin/providers/aws/resource_aws_lambda_event_source_mapping.go @@ -91,6 +91,13 @@ func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta inte Enabled: aws.Bool(d.Get("enabled").(bool)), } + // IAM profiles and roles can take some time to propagate in AWS: + // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console + // Error creating Lambda function: InvalidParameterValueException: The + // function defined for the task cannot be assumed by Lambda. + // + // The role may exist, but the permissions may not have propagated, so we + // retry err := resource.Retry(1*time.Minute, func() error { eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params) if err != nil { From 449ffe027f250a494e4b5f4a16a5bafccf34d2de Mon Sep 17 00:00:00 2001 From: clint shryock Date: Tue, 5 Jan 2016 11:35:21 -0600 Subject: [PATCH 5/5] fix error with undefined err --- builtin/providers/aws/resource_aws_lambda_function.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index b47a6a5a0..4cce32f4d 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -153,7 +153,7 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console // Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda. err := resource.Retry(1*time.Minute, func() error { - _, err = conn.CreateFunction(params) + _, err := conn.CreateFunction(params) if err != nil { if awserr, ok := err.(awserr.Error); ok { if awserr.Code() == "InvalidParameterValueException" {