From 811c4570eebc9cdcd0b287c773b09f758007d0db Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 21 Dec 2017 12:51:05 -0500 Subject: [PATCH 1/2] r/aws_sqs_queue_policy: Add StateChangeConf for create/update, remove missing policy error on read --- aws/resource_aws_sqs_queue_policy.go | 45 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_sqs_queue_policy.go b/aws/resource_aws_sqs_queue_policy.go index 2ec1f37821fb..d81661288ad3 100644 --- a/aws/resource_aws_sqs_queue_policy.go +++ b/aws/resource_aws_sqs_queue_policy.go @@ -3,10 +3,13 @@ package aws import ( "fmt" "log" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/sqs" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" + "github.com/jen20/awspolicyequivalence" ) func resourceAwsSqsQueuePolicy() *schema.Resource { @@ -40,18 +43,51 @@ func resourceAwsSqsQueuePolicy() *schema.Resource { func resourceAwsSqsQueuePolicyUpsert(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).sqsconn + policy := d.Get("policy").(string) url := d.Get("queue_url").(string) _, err := conn.SetQueueAttributes(&sqs.SetQueueAttributesInput{ QueueUrl: aws.String(url), Attributes: aws.StringMap(map[string]string{ - "Policy": d.Get("policy").(string), + "Policy": policy, }), }) if err != nil { return fmt.Errorf("Error updating SQS attributes: %s", err) } + // https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html + // When you change a queue's attributes, the change can take up to 60 seconds + // for most of the attributes to propagate throughout the Amazon SQS system. + wait := resource.StateChangeConf{ + Pending: []string{""}, + Target: []string{"SQS queue policy updated"}, + Timeout: 1 * time.Minute, + MinTimeout: 1 * time.Second, + Refresh: func() (interface{}, string, error) { + out, err := conn.GetQueueAttributes(&sqs.GetQueueAttributesInput{ + QueueUrl: aws.String(url), + AttributeNames: []*string{aws.String("Policy")}, + }) + if err != nil { + return out, "", err + } + queuePolicy, ok := out.Attributes["Policy"] + if ok { + equivalent, err := awspolicy.PoliciesAreEquivalent(*queuePolicy, policy) + if err != nil || !equivalent { + return out, "", nil + } + return out, "SQS queue policy updated", nil + } + return out, "", nil + }, + } + _, err = wait.WaitForState() + if err != nil { + return err + } + d.SetId(url) return resourceAwsSqsQueuePolicyRead(d, meta) @@ -77,11 +113,12 @@ func resourceAwsSqsQueuePolicyRead(d *schema.ResourceData, meta interface{}) err } policy, ok := out.Attributes["Policy"] - if !ok { - return fmt.Errorf("SQS Queue policy not found for %s", d.Id()) + if ok { + d.Set("policy", policy) + } else { + d.Set("policy", "") } - d.Set("policy", policy) d.Set("queue_url", d.Id()) return nil From 91a723ff5046b06081f444331c022aaaa9d888f4 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 18 Jan 2018 14:39:10 -0500 Subject: [PATCH 2/2] resource/aws_sqs_queue_policy: Use resource.Retry instead of resource.StateChangeConf Additionally: * Supplement debug logging * Use sqs.QueueAttributeNamePolicy constant --- aws/resource_aws_sqs_queue_policy.go | 63 +++++++++++++++------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/aws/resource_aws_sqs_queue_policy.go b/aws/resource_aws_sqs_queue_policy.go index d81661288ad3..277afc2e787e 100644 --- a/aws/resource_aws_sqs_queue_policy.go +++ b/aws/resource_aws_sqs_queue_policy.go @@ -46,12 +46,14 @@ func resourceAwsSqsQueuePolicyUpsert(d *schema.ResourceData, meta interface{}) e policy := d.Get("policy").(string) url := d.Get("queue_url").(string) - _, err := conn.SetQueueAttributes(&sqs.SetQueueAttributesInput{ + sqaInput := &sqs.SetQueueAttributesInput{ QueueUrl: aws.String(url), Attributes: aws.StringMap(map[string]string{ - "Policy": policy, + sqs.QueueAttributeNamePolicy: policy, }), - }) + } + log.Printf("[DEBUG] Updating SQS attributes: %s", sqaInput) + _, err := conn.SetQueueAttributes(sqaInput) if err != nil { return fmt.Errorf("Error updating SQS attributes: %s", err) } @@ -59,31 +61,32 @@ func resourceAwsSqsQueuePolicyUpsert(d *schema.ResourceData, meta interface{}) e // https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html // When you change a queue's attributes, the change can take up to 60 seconds // for most of the attributes to propagate throughout the Amazon SQS system. - wait := resource.StateChangeConf{ - Pending: []string{""}, - Target: []string{"SQS queue policy updated"}, - Timeout: 1 * time.Minute, - MinTimeout: 1 * time.Second, - Refresh: func() (interface{}, string, error) { - out, err := conn.GetQueueAttributes(&sqs.GetQueueAttributesInput{ - QueueUrl: aws.String(url), - AttributeNames: []*string{aws.String("Policy")}, - }) - if err != nil { - return out, "", err - } - queuePolicy, ok := out.Attributes["Policy"] - if ok { - equivalent, err := awspolicy.PoliciesAreEquivalent(*queuePolicy, policy) - if err != nil || !equivalent { - return out, "", nil - } - return out, "SQS queue policy updated", nil - } - return out, "", nil - }, + gqaInput := &sqs.GetQueueAttributesInput{ + QueueUrl: aws.String(url), + AttributeNames: []*string{aws.String(sqs.QueueAttributeNamePolicy)}, } - _, err = wait.WaitForState() + notUpdatedError := fmt.Errorf("SQS attribute %s not updated", sqs.QueueAttributeNamePolicy) + err = resource.Retry(1*time.Minute, func() *resource.RetryError { + log.Printf("[DEBUG] Reading SQS attributes: %s", gqaInput) + out, err := conn.GetQueueAttributes(gqaInput) + if err != nil { + return resource.NonRetryableError(err) + } + queuePolicy, ok := out.Attributes[sqs.QueueAttributeNamePolicy] + if !ok { + log.Printf("[DEBUG] SQS attribute %s not found - retrying", sqs.QueueAttributeNamePolicy) + return resource.RetryableError(notUpdatedError) + } + equivalent, err := awspolicy.PoliciesAreEquivalent(*queuePolicy, policy) + if err != nil { + return resource.NonRetryableError(err) + } + if !equivalent { + log.Printf("[DEBUG] SQS attribute %s not updated - retrying", sqs.QueueAttributeNamePolicy) + return resource.RetryableError(notUpdatedError) + } + return nil + }) if err != nil { return err } @@ -98,7 +101,7 @@ func resourceAwsSqsQueuePolicyRead(d *schema.ResourceData, meta interface{}) err out, err := conn.GetQueueAttributes(&sqs.GetQueueAttributesInput{ QueueUrl: aws.String(d.Id()), - AttributeNames: []*string{aws.String("Policy")}, + AttributeNames: []*string{aws.String(sqs.QueueAttributeNamePolicy)}, }) if err != nil { if isAWSErr(err, "AWS.SimpleQueueService.NonExistentQueue", "") { @@ -112,7 +115,7 @@ func resourceAwsSqsQueuePolicyRead(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Received empty response for SQS queue %s", d.Id()) } - policy, ok := out.Attributes["Policy"] + policy, ok := out.Attributes[sqs.QueueAttributeNamePolicy] if ok { d.Set("policy", policy) } else { @@ -131,7 +134,7 @@ func resourceAwsSqsQueuePolicyDelete(d *schema.ResourceData, meta interface{}) e _, err := conn.SetQueueAttributes(&sqs.SetQueueAttributesInput{ QueueUrl: aws.String(d.Id()), Attributes: aws.StringMap(map[string]string{ - "Policy": "", + sqs.QueueAttributeNamePolicy: "", }), }) if err != nil {