Skip to content

Commit

Permalink
Merge pull request #22194 from hashicorp/b-sqs-policy-diffs
Browse files Browse the repository at this point in the history
sqs: Fix diffs with policies
  • Loading branch information
YakDriver authored Dec 14, 2021
2 parents f64456c + ae6715d commit 37f313b
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 115 deletions.
15 changes: 15 additions & 0 deletions .changelog/22194.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```release-note:bug
resource/aws_sqs_queue: Fix erroneous diffs in `policy` when no changes made or policies are equivalent
```

```release-note:bug
resource/aws_sqs_queue_policy: Fix erroneous diffs in `policy` when no changes made or policies are equivalent
```

```release-note:bug
resource/aws_sqs_queue: Fix "error reading, empty result" and various eventual consistency errors
```

```release-note:bug
resource/aws_sqs_queue_policy: Fix "error reading, empty result" and various eventual consistency errors
```
54 changes: 50 additions & 4 deletions internal/service/sqs/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ var (
Computed: true,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: verify.SuppressEquivalentPolicyDiffs,
StateFunc: func(v interface{}) string {
json, _ := structure.NormalizeJsonString(v)
return json
},
},

"receive_wait_time_seconds": {
Expand Down Expand Up @@ -216,6 +220,14 @@ func resourceQueueCreate(d *schema.ResourceData, meta interface{}) error {
return err
}

policy, err := structure.NormalizeJsonString(attributes[sqs.QueueAttributeNamePolicy])

if err != nil {
return fmt.Errorf("policy (%s) is invalid JSON: %w", attributes[sqs.QueueAttributeNamePolicy], err)
}

attributes[sqs.QueueAttributeNamePolicy] = policy

input.Attributes = aws.StringMap(attributes)

// Tag-on-create is currently only supported in AWS Commercial
Expand Down Expand Up @@ -272,7 +284,9 @@ func resourceQueueRead(d *schema.ResourceData, meta interface{}) error {
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig

output, err := FindQueueAttributesByURL(conn, d.Id())
outputRaw, err := tfresource.RetryWhenNotFound(queueReadTimeout, func() (interface{}, error) {
return FindQueueAttributesByURL(conn, d.Id())
})

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] SQS Queue (%s) not found, removing from state", d.Id())
Expand All @@ -290,6 +304,8 @@ func resourceQueueRead(d *schema.ResourceData, meta interface{}) error {
return err
}

output := outputRaw.(map[string]string)

err = sqsQueueAttributeMap.ApiAttributesToResourceData(output, d)

if err != nil {
Expand All @@ -309,15 +325,45 @@ func resourceQueueRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("url", d.Id())

tags, err := ListTags(conn, d.Id())
policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), output[sqs.QueueAttributeNamePolicy])

if err != nil {
return err
}

d.Set("policy", policyToSet)

var tags tftags.KeyValueTags

err = resource.Retry(queueTagsTimeout, func() *resource.RetryError {
var err error

tags, err = ListTags(conn, d.Id())

if tfawserr.ErrCodeEquals(err, sqs.ErrCodeQueueDoesNotExist) {
return resource.RetryableError(err)
}

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

return nil
})

if tfresource.TimedOut(err) {
tags, err = ListTags(conn, d.Id())
}

if err != nil {
// Non-standard partitions (e.g. US Gov) and some local development
// solutions do not yet support this API call. Depending on the
// implementation it may return InvalidAction or AWS.SimpleQueueService.UnsupportedOperation
if !tfawserr.ErrCodeEquals(err, ErrCodeInvalidAction) && !tfawserr.ErrCodeEquals(err, sqs.ErrCodeUnsupportedOperation) {
return fmt.Errorf("error listing tags for SQS Queue (%s): %w", d.Id(), err)
if tfawserr.ErrCodeEquals(err, ErrCodeInvalidAction) || tfawserr.ErrCodeEquals(err, sqs.ErrCodeUnsupportedOperation) {
return nil
}

return fmt.Errorf("error listing tags for SQS Queue (%s): %w", d.Id(), err)
}

tags = tags.IgnoreAWS().IgnoreConfig(ignoreTagsConfig)
Expand Down
29 changes: 25 additions & 4 deletions internal/service/sqs/queue_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/aws/aws-sdk-go/service/sqs"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
Expand Down Expand Up @@ -39,6 +40,10 @@ func ResourceQueuePolicy() *schema.Resource {
Required: true,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: verify.SuppressEquivalentPolicyDiffs,
StateFunc: func(v interface{}) string {
json, _ := structure.NormalizeJsonString(v)
return json
},
},

"queue_url": {
Expand All @@ -53,17 +58,24 @@ func ResourceQueuePolicy() *schema.Resource {
func resourceQueuePolicyUpsert(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).SQSConn

policy, err := structure.NormalizeJsonString(d.Get("policy").(string))

if err != nil {
return fmt.Errorf("policy (%s) is invalid JSON: %w", d.Get("policy").(string), err)
}

policyAttributes := map[string]string{
sqs.QueueAttributeNamePolicy: d.Get("policy").(string),
sqs.QueueAttributeNamePolicy: policy,
}

url := d.Get("queue_url").(string)
input := &sqs.SetQueueAttributesInput{
Attributes: aws.StringMap(policyAttributes),
QueueUrl: aws.String(url),
}

log.Printf("[DEBUG] Setting SQS Queue Policy: %s", input)
_, err := conn.SetQueueAttributes(input)
_, err = conn.SetQueueAttributes(input)

if err != nil {
return fmt.Errorf("error setting SQS Queue Policy (%s): %w", url, err)
Expand All @@ -83,7 +95,9 @@ func resourceQueuePolicyUpsert(d *schema.ResourceData, meta interface{}) error {
func resourceQueuePolicyRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).SQSConn

policy, err := FindQueuePolicyByURL(conn, d.Id())
outputRaw, err := tfresource.RetryWhenNotFound(queuePolicyReadTimeout, func() (interface{}, error) {
return FindQueuePolicyByURL(conn, d.Id())
})

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] SQS Queue Policy (%s) not found, removing from state", d.Id())
Expand All @@ -95,7 +109,14 @@ func resourceQueuePolicyRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("error reading SQS Queue Policy (%s): %w", d.Id(), err)
}

d.Set("policy", policy)
policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), outputRaw.(string))

if err != nil {
return err
}

d.Set("policy", policyToSet)

d.Set("queue_url", d.Id())

return nil
Expand Down
Loading

0 comments on commit 37f313b

Please sign in to comment.