Skip to content

Commit

Permalink
Merge pull request #9065 from terraform-providers/rfd-retry-cloudwatch
Browse files Browse the repository at this point in the history
Cleaning up some resource retries for cloudwatch functions
  • Loading branch information
ryndaniels authored Jul 17, 2019
2 parents f513f52 + f6e475b commit d5e098b
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 77 deletions.
58 changes: 35 additions & 23 deletions aws/resource_aws_cloudwatch_event_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,42 +99,35 @@ func resourceAwsCloudWatchEventPermissionCreate(d *schema.ResourceData, meta int
func resourceAwsCloudWatchEventPermissionRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatcheventsconn
input := events.DescribeEventBusInput{}
var policyDoc CloudWatchEventPermissionPolicyDoc
var output *events.DescribeEventBusOutput
var policyStatement *CloudWatchEventPermissionPolicyStatement

// Especially with concurrent PutPermission calls there can be a slight delay
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
log.Printf("[DEBUG] Reading CloudWatch Events bus: %s", input)
debo, err := conn.DescribeEventBus(&input)
output, err := conn.DescribeEventBus(&input)
if err != nil {
return resource.NonRetryableError(fmt.Errorf("Reading CloudWatch Events permission '%s' failed: %s", d.Id(), err.Error()))
}

if debo.Policy == nil {
return resource.RetryableError(&resource.NotFoundError{
Message: fmt.Sprintf("CloudWatch Events permission %q not found"+
"in given results from DescribeEventBus", d.Id()),
LastResponse: debo,
LastRequest: input,
})
}
policyStatement, err = getPolicyStatement(output, d.Id())
return resource.RetryableError(err)
})

err = json.Unmarshal([]byte(*debo.Policy), &policyDoc)
if err != nil {
return resource.NonRetryableError(fmt.Errorf("Reading CloudWatch Events permission '%s' failed: %s", d.Id(), err.Error()))
if isResourceTimeoutError(err) {
output, err = conn.DescribeEventBus(&input)
if output != nil {
policyStatement, err = getPolicyStatement(output, d.Id())
}
}

policyStatement, err = findCloudWatchEventPermissionPolicyStatementByID(&policyDoc, d.Id())
return resource.RetryableError(err)
})
if isResourceNotFoundError(err) {
log.Printf("[WARN] %s", err)
d.SetId("")
return nil
}
if err != nil {
// Missing statement inside valid policy
if nfErr, ok := err.(*resource.NotFoundError); ok {
log.Printf("[WARN] %s", nfErr)
d.SetId("")
return nil
}

return err
}

Expand All @@ -151,7 +144,7 @@ func resourceAwsCloudWatchEventPermissionRead(d *schema.ResourceData, meta inter
principalMap := policyStatement.Principal.(map[string]interface{})
policyARN, err := arn.Parse(principalMap["AWS"].(string))
if err != nil {
return fmt.Errorf("Reading CloudWatch Events permission '%s' failed: %s", d.Id(), err.Error())
return fmt.Errorf("Reading CloudWatch Events permission '%s' failed: %s", d.Id(), err)
}
d.Set("principal", policyARN.AccountID)
}
Expand All @@ -160,6 +153,25 @@ func resourceAwsCloudWatchEventPermissionRead(d *schema.ResourceData, meta inter
return nil
}

func getPolicyStatement(output *events.DescribeEventBusOutput, statementID string) (*CloudWatchEventPermissionPolicyStatement, error) {
var policyDoc CloudWatchEventPermissionPolicyDoc

if output == nil || output.Policy == nil {
return nil, &resource.NotFoundError{
Message: fmt.Sprintf("CloudWatch Events permission %q not found"+
"in given results from DescribeEventBus", statementID),
LastResponse: output,
}
}

err := json.Unmarshal([]byte(*output.Policy), &policyDoc)
if err != nil {
return nil, fmt.Errorf("Reading CloudWatch Events permission '%s' failed: %s", statementID, err)
}

return findCloudWatchEventPermissionPolicyStatementByID(&policyDoc, statementID)
}

func resourceAwsCloudWatchEventPermissionUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatcheventsconn

Expand Down
36 changes: 19 additions & 17 deletions aws/resource_aws_cloudwatch_event_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package aws
import (
"fmt"
"log"
"regexp"
"time"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -99,22 +98,23 @@ func resourceAwsCloudWatchEventRuleCreate(d *schema.ResourceData, meta interface
// IAM Roles take some time to propagate
var out *events.PutRuleOutput
err = resource.Retry(30*time.Second, func() *resource.RetryError {
var err error
out, err = conn.PutRule(input)
pattern := regexp.MustCompile(`cannot be assumed by principal '[a-z]+\.amazonaws\.com'\.$`)

if isAWSErr(err, "ValidationException", "cannot be assumed by principal") {
log.Printf("[DEBUG] Retrying update of CloudWatch Event Rule %q", *input.Name)
return resource.RetryableError(err)
}
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "ValidationException" && pattern.MatchString(awsErr.Message()) {
log.Printf("[DEBUG] Retrying creation of CloudWatch Event Rule %q", *input.Name)
return resource.RetryableError(err)
}
}
return resource.NonRetryableError(err)
}
return nil
})
if isResourceTimeoutError(err) {
_, err = conn.PutRule(input)
}

if err != nil {
return fmt.Errorf("Creating CloudWatch Event Rule failed: %s", err)
return fmt.Errorf("Updating CloudWatch Event Rule failed: %s", err)
}

d.Set("arn", out.RuleArn)
Expand Down Expand Up @@ -197,18 +197,20 @@ func resourceAwsCloudWatchEventRuleUpdate(d *schema.ResourceData, meta interface
// IAM Roles take some time to propagate
err = resource.Retry(30*time.Second, func() *resource.RetryError {
_, err := conn.PutRule(input)
pattern := regexp.MustCompile(`cannot be assumed by principal '[a-z]+\.amazonaws\.com'\.$`)

if isAWSErr(err, "ValidationException", "cannot be assumed by principal") {
log.Printf("[DEBUG] Retrying update of CloudWatch Event Rule %q", *input.Name)
return resource.RetryableError(err)
}
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "ValidationException" && pattern.MatchString(awsErr.Message()) {
log.Printf("[DEBUG] Retrying update of CloudWatch Event Rule %q", *input.Name)
return resource.RetryableError(err)
}
}
return resource.NonRetryableError(err)
}
return nil
})
if isResourceTimeoutError(err) {
_, err = conn.PutRule(input)
}

if err != nil {
return fmt.Errorf("Updating CloudWatch Event Rule failed: %s", err)
}
Expand Down
34 changes: 16 additions & 18 deletions aws/resource_aws_cloudwatch_log_destination.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package aws

import (
"fmt"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
Expand Down Expand Up @@ -64,28 +62,28 @@ func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interfa
TargetArn: aws.String(target_arn),
}

return resource.Retry(3*time.Minute, func() *resource.RetryError {
resp, err := conn.PutDestination(params)
var resp *cloudwatchlogs.PutDestinationOutput
var err error
err = resource.Retry(3*time.Minute, func() *resource.RetryError {
resp, err = conn.PutDestination(params)

if err == nil {
d.SetId(name)
d.Set("arn", *resp.Destination.Arn)
}

awsErr, ok := err.(awserr.Error)
if !ok {
if isAWSErr(err, cloudwatchlogs.ErrCodeInvalidParameterException, "Could not deliver test message to specified") {
return resource.RetryableError(err)
}

if awsErr.Code() == "InvalidParameterException" {
if strings.Contains(awsErr.Message(), "Could not deliver test message to specified") {
return resource.RetryableError(err)
}
if err != nil {
return resource.NonRetryableError(err)
}

return resource.NonRetryableError(err)
return nil
})
if isResourceTimeoutError(err) {
resp, err = conn.PutDestination(params)
}
if err != nil {
return fmt.Errorf("Error putting cloudwatch log destination: %s", err)
}
d.SetId(name)
d.Set("arn", resp.Destination.Arn)
return nil
}

func resourceAwsCloudWatchLogDestinationRead(d *schema.ResourceData, meta interface{}) error {
Expand Down
38 changes: 19 additions & 19 deletions aws/resource_aws_cloudwatch_log_subscription_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,32 +64,32 @@ func resourceAwsCloudwatchLogSubscriptionFilterCreate(d *schema.ResourceData, me
params := getAwsCloudWatchLogsSubscriptionFilterInput(d)
log.Printf("[DEBUG] Creating SubscriptionFilter %#v", params)

return resource.Retry(5*time.Minute, func() *resource.RetryError {
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
_, err := conn.PutSubscriptionFilter(&params)

if err == nil {
d.SetId(cloudwatchLogsSubscriptionFilterId(d.Get("log_group_name").(string)))
log.Printf("[DEBUG] Cloudwatch logs subscription %q created", d.Id())
if isAWSErr(err, cloudwatchlogs.ErrCodeInvalidParameterException, "Could not deliver test message to specified") {
return resource.RetryableError(err)
}

awsErr, ok := err.(awserr.Error)
if !ok {
if isAWSErr(err, cloudwatchlogs.ErrCodeInvalidParameterException, "Could not execute the lambda function") {
return resource.RetryableError(err)
}

if awsErr.Code() == "InvalidParameterException" {
log.Printf("[DEBUG] Caught message: %q, code: %q: Retrying", awsErr.Message(), awsErr.Code())
if strings.Contains(awsErr.Message(), "Could not deliver test message to specified") {
return resource.RetryableError(err)
}
if strings.Contains(awsErr.Message(), "Could not execute the lambda function") {
return resource.RetryableError(err)
}
resource.NonRetryableError(err)
if err != nil {
return resource.NonRetryableError(err)
}

return resource.NonRetryableError(err)
return nil
})

if isResourceTimeoutError(err) {
_, err = conn.PutSubscriptionFilter(&params)
}

if err != nil {
return fmt.Errorf("Error creating Cloudwatch log subscription filter: %s", err)
}

d.SetId(cloudwatchLogsSubscriptionFilterId(d.Get("log_group_name").(string)))
log.Printf("[DEBUG] Cloudwatch logs subscription %q created", d.Id())
return nil
}

func resourceAwsCloudwatchLogSubscriptionFilterUpdate(d *schema.ResourceData, meta interface{}) error {
Expand Down

0 comments on commit d5e098b

Please sign in to comment.