Skip to content

Commit

Permalink
Merge pull request #9553 from terraform-providers/rfd-retry-lambda
Browse files Browse the repository at this point in the history
Final retries for various lambda functions
  • Loading branch information
ryndaniels committed Aug 2, 2019
2 parents bcb9017 + 775fe3f commit dbf2b4f
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 49 deletions.
26 changes: 17 additions & 9 deletions aws/resource_aws_lambda_event_source_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta inte
//
// The role may exist, but the permissions may not have propagated, so we
// retry
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params)
var eventSourceMappingConfiguration *lambda.EventSourceMappingConfiguration
var err error
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
eventSourceMappingConfiguration, err = conn.CreateEventSourceMapping(params)
if err != nil {
if awserr, ok := err.(awserr.Error); ok {
if awserr.Code() == "InvalidParameterValueException" {
Expand All @@ -170,16 +172,18 @@ func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta inte
}
return resource.NonRetryableError(err)
}
// No error
d.Set("uuid", eventSourceMappingConfiguration.UUID)
d.SetId(*eventSourceMappingConfiguration.UUID)
return nil
})

if isResourceTimeoutError(err) {
eventSourceMappingConfiguration, err = conn.CreateEventSourceMapping(params)
}
if err != nil {
return fmt.Errorf("Error creating Lambda event source mapping: %s", err)
}

// No error
d.Set("uuid", eventSourceMappingConfiguration.UUID)
d.SetId(*eventSourceMappingConfiguration.UUID)
return resourceAwsLambdaEventSourceMappingRead(d, meta)
}

Expand All @@ -196,7 +200,7 @@ func resourceAwsLambdaEventSourceMappingRead(d *schema.ResourceData, meta interf

eventSourceMappingConfiguration, err := conn.GetEventSourceMapping(params)
if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "ResourceNotFoundException" {
if isAWSErr(err, "ResourceNotFoundException", "") {
log.Printf("[DEBUG] Lambda event source mapping (%s) not found", d.Id())
d.SetId("")

Expand Down Expand Up @@ -250,7 +254,9 @@ func resourceAwsLambdaEventSourceMappingDelete(d *schema.ResourceData, meta inte
}
return nil
})

if isResourceTimeoutError(err) {
_, err = conn.DeleteEventSourceMapping(params)
}
if err != nil {
return fmt.Errorf("Error deleting Lambda event source mapping: %s", err)
}
Expand Down Expand Up @@ -284,7 +290,9 @@ func resourceAwsLambdaEventSourceMappingUpdate(d *schema.ResourceData, meta inte
}
return nil
})

if isResourceTimeoutError(err) {
_, err = conn.UpdateEventSourceMapping(params)
}
if err != nil {
return fmt.Errorf("Error updating Lambda event source mapping: %s", err)
}
Expand Down
9 changes: 9 additions & 0 deletions aws/resource_aws_lambda_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,9 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
}
return nil
})
if isResourceTimeoutError(err) {
_, err = conn.CreateFunction(params)
}
if err != nil {
return fmt.Errorf("Error creating Lambda function: %s", err)
}
Expand All @@ -460,6 +463,9 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
}
return nil
})
if isResourceTimeoutError(err) {
_, err = conn.PutFunctionConcurrency(concurrencyParams)
}
if err != nil {
return fmt.Errorf("Error setting concurrency for Lambda %s: %s", functionName, err)
}
Expand Down Expand Up @@ -802,6 +808,9 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e
}
return nil
})
if isResourceTimeoutError(err) {
_, err = conn.UpdateFunctionConfiguration(configReq)
}
if err != nil {
return fmt.Errorf("Error modifying Lambda Function Configuration %s: %s", d.Id(), err)
}
Expand Down
114 changes: 74 additions & 40 deletions aws/resource_aws_lambda_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,18 @@ func resourceAwsLambdaPermissionCreate(d *schema.ResourceData, meta interface{})
var err error
out, err = conn.AddPermission(&input)

if isAWSErr(err, lambda.ErrCodeResourceConflictException, "") {
if isAWSErr(err, lambda.ErrCodeResourceConflictException, "") || isAWSErr(err, lambda.ErrCodeResourceNotFoundException, "") {
return resource.RetryableError(err)
}

if isAWSErr(err, lambda.ErrCodeResourceNotFoundException, "") {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})

if isResourceTimeoutError(err) {
out, err = conn.AddPermission(&input)
}
if err != nil {
return fmt.Errorf("Error adding new Lambda Permission for %s: %s", functionName, err)
}
Expand Down Expand Up @@ -181,8 +178,13 @@ func resourceAwsLambdaPermissionCreate(d *schema.ResourceData, meta interface{})
}
return nil
})

return err
if isResourceTimeoutError(err) {
err = resourceAwsLambdaPermissionRead(d, meta)
}
if err != nil {
return fmt.Errorf("Error reading new Lambda permissions: %s", err)
}
return nil
}

func resourceAwsLambdaPermissionRead(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -211,16 +213,23 @@ func resourceAwsLambdaPermissionRead(d *schema.ResourceData, meta interface{}) e
return resource.NonRetryableError(err)
}

policyInBytes := []byte(*out.Policy)
policy := LambdaPolicy{}
err = json.Unmarshal(policyInBytes, &policy)
statement, err = getLambdaPolicyStatement(out, d.Id())
if err != nil {
return resource.NonRetryableError(err)
return resource.RetryableError(err)
}

statement, err = findLambdaPolicyStatementById(&policy, d.Id())
return resource.RetryableError(err)
return nil
})
if isResourceTimeoutError(err) {
out, err = conn.GetPolicy(&input)

if err == nil {
var psErr error
statement, psErr = getLambdaPolicyStatement(out, d.Id())
if psErr != nil {
return psErr
}
}
}

if err != nil {
// Missing whole policy or Lambda function (API error)
Expand All @@ -242,6 +251,10 @@ func resourceAwsLambdaPermissionRead(d *schema.ResourceData, meta interface{}) e
return err
}

if statement == nil {
return fmt.Errorf("No Lambda Permission policy found with ID %s", d.Id())
}

qualifier, err := getQualifierFromLambdaAliasOrVersionArn(statement.Resource)
if err != nil {
log.Printf("[ERR] Error getting Lambda Qualifier: %s", err)
Expand Down Expand Up @@ -316,57 +329,78 @@ func resourceAwsLambdaPermissionDelete(d *schema.ResourceData, meta interface{})
return err
}

params := &lambda.GetPolicyInput{
FunctionName: aws.String(d.Get("function_name").(string)),
}
if v, ok := d.GetOk("qualifier"); ok {
params.Qualifier = aws.String(v.(string))
}
var statement *LambdaPolicyStatement
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
log.Printf("[DEBUG] Checking if Lambda permission %q is deleted", d.Id())

params := &lambda.GetPolicyInput{
FunctionName: aws.String(d.Get("function_name").(string)),
}
if v, ok := d.GetOk("qualifier"); ok {
params.Qualifier = aws.String(v.(string))
}

log.Printf("[DEBUG] Looking for Lambda permission: %s", *params)
resp, err := conn.GetPolicy(params)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "ResourceNotFoundException" {
return nil
}
if isAWSErr(err, "ResourceNotFoundException", "") {
return nil
}
return resource.NonRetryableError(err)
}

if resp.Policy == nil {
return nil
}

policyInBytes := []byte(*resp.Policy)
policy := LambdaPolicy{}
err = json.Unmarshal(policyInBytes, &policy)
statement, err = getLambdaPolicyStatement(resp, d.Id())
if err != nil {
return resource.RetryableError(
fmt.Errorf("Error unmarshalling Lambda policy: %s", err))
return nil
}
return nil
})

_, err = findLambdaPolicyStatementById(&policy, d.Id())
if isResourceTimeoutError(err) {
resp, err := conn.GetPolicy(params)
if isAWSErr(err, "ResourceNotFoundException", "") {
return nil
}
if err != nil {
return fmt.Errorf("Error getting Lambda permission policy: %s", err)
}
if resp.Policy == nil {
return nil
}

log.Printf("[DEBUG] No error when checking if Lambda permission %s is deleted", d.Id())
return nil
})

var psErr error
statement, psErr = getLambdaPolicyStatement(resp, d.Id())
if psErr != nil {
return nil
}
}
if err != nil {
return fmt.Errorf("Failed removing Lambda permission: %s", err)
}
if statement != nil {
return fmt.Errorf("Failed to delete Lambda permission with ID %s", d.Id())
}

log.Printf("[DEBUG] Lambda permission with ID %q removed", d.Id())

return nil
}

func getLambdaPolicyStatement(out *lambda.GetPolicyOutput, statemendId string) (statement *LambdaPolicyStatement, err error) {
policyInBytes := []byte(*out.Policy)
policy := LambdaPolicy{}
err = json.Unmarshal(policyInBytes, &policy)
if err != nil {
return nil, fmt.Errorf("Error unmarshalling Lambda policy: %s", err)
}

statement, psErr := findLambdaPolicyStatementById(&policy, statemendId)
if psErr != nil {
return nil, fmt.Errorf("Error finding Lambda policy statement: %s", psErr)
}
return statement, nil
}

func findLambdaPolicyStatementById(policy *LambdaPolicy, id string) (
*LambdaPolicyStatement, error) {

Expand Down

1 comment on commit dbf2b4f

@harishkumar0403
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h

Please sign in to comment.