-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
resource/aws_sns_topic_subscription: Add configurable DeliveryPolicy #3289
Conversation
`, i, i, policy) | ||
} | ||
|
||
func testAccAWSSNSTopicSubscriptionConfig_deliveryPolicy(i int, policy string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to security restrictions in the accounts I have access to, I'm unable to run this acceptance test. Please let me know whether you prefer to have this deleted or run it in your end. Note this is a copy of one of the existing tests with the addition of delivery_policy
in the SNS subscription
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally require acceptance testing for new enhancements and this one does look pretty good overall. It does need to be updated to a more valid delivery policy JSON though, as AWS is currently returning:
2018/02/08 11:56:37 [DEBUG] [aws-sdk-go] DEBUG: Validate Response sns/SetSubscriptionAttributes failed, not retrying, error InvalidParameter: Invalid parameter: DeliveryPolicy: healthyRetryPolicy.minDelayTarget must be specified
status code: 400, request id: 4d4b2c18-4d55-5c2b-af81-7eeeced101fe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, I forgot the example on the doc is wrong. I'll update this with a valid policy
@bflad I've opened this PR with the changes for the delivery policy picked from the other PR. Cheers |
@ddcprg thanks so much for being flexible with rebasing this PR! Taking a look now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ddcprg this PR is pretty close, thanks for adding the function to centralize the SetSubscriptionAttribute logic. Check out below and let me know if you can adjust the items or if you'd like one of us to finish this up (since I know you can't run the acceptance testing).
--- FAIL: TestAccAWSSNSTopicSubscription_deliveryPolicy (37.48s)
testing.go:513: Step 0 error: Error applying: 1 error(s) occurred:
* aws_sns_topic_subscription.test_subscription: 1 error(s) occurred:
* aws_sns_topic_subscription.test_subscription: Unable to set DeliveryPolicy attribute on subscription
@@ -328,3 +328,18 @@ func obfuscateEndpoint(endpoint string) string { | |||
} | |||
return obfuscatedEndpoint | |||
} | |||
|
|||
func snsSubscriptionAttributeUpdate(snsconn *sns.SNS, tfId string, tfName string, val string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very handy here. Can we update the signature of this function to just take in the expected values?
func snsSubscriptionAttributeUpdate(snsconn *sns.SNS, subscriptionArn, attributeName, attributeValue string) error {
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, done. This syntax is cleaner in fact
_, err := snsconn.SetSubscriptionAttributes(req) | ||
|
||
if err != nil { | ||
return fmt.Errorf("Unable to set %s attribute on subscription", awsAttrName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should definitely return the err
string here too 😄
return fmt.Errorf("Unable to set %s attribute on subscription: %s", attributeName, err)
Otherwise you get this, which isn't so helpful:
=== RUN TestAccAWSSNSTopicSubscription_deliveryPolicy
--- FAIL: TestAccAWSSNSTopicSubscription_deliveryPolicy (37.69s)
testing.go:513: Step 0 error: Error applying: 1 error(s) occurred:
* aws_sns_topic_subscription.test_subscription: 1 error(s) occurred:
* aws_sns_topic_subscription.test_subscription: Unable to set DeliveryPolicy attribute on subscription
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Count on this
@@ -242,6 +242,8 @@ The following arguments are supported: | |||
* `endpoint_auto_confirms` - (Optional) Boolean indicating whether the end point is capable of [auto confirming subscription](http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html#SendMessageToHttp.prepare) e.g., PagerDuty (default is false) | |||
* `confirmation_timeout_in_minutes` - (Optional) Integer indicating number of minutes to wait in retying mode for fetching subscription arn before marking it as failure. Only applicable for http and https protocols (default is 1 minute). | |||
* `raw_message_delivery` - (Optional) Boolean indicating whether or not to enable raw message delivery (the original message is directly passed, not wrapped in JSON with the original message in the message property) (default is false). | |||
* `filter_policy` - (Optional) JSON String with the filter policy that will be used in the subscription to filter messages seen by the target resource. Refer to the SNS docs for more details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!!! I totally missed this yesterday. 😢 Can you please also link to the appropriate documentation for these two policies please? e.g. https://docs.aws.amazon.com/sns/latest/dg/message-filtering.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem. The delivery policy doc is not specific about the format https://docs.aws.amazon.com/sns/latest/dg/DeliveryPolicies.html . There is another page with an example to set this via CLI but is less specific and the policy is incomplete :) https://docs.aws.amazon.com/sns/latest/dg/json-formats.html
`, i, i, policy) | ||
} | ||
|
||
func testAccAWSSNSTopicSubscriptionConfig_deliveryPolicy(i int, policy string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally require acceptance testing for new enhancements and this one does look pretty good overall. It does need to be updated to a more valid delivery policy JSON though, as AWS is currently returning:
2018/02/08 11:56:37 [DEBUG] [aws-sdk-go] DEBUG: Validate Response sns/SetSubscriptionAttributes failed, not retrying, error InvalidParameter: Invalid parameter: DeliveryPolicy: healthyRetryPolicy.minDelayTarget must be specified
status code: 400, request id: 4d4b2c18-4d55-5c2b-af81-7eeeced101fe
} | ||
} | ||
|
||
if d.HasChange("filter_policy") { | ||
_, n := d.GetChange("filter_policy") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: n
here is a specific naming convention as d.GetChange()
returns old, new
😄 (also makes it easier to duplicate the logic if necessary).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense :) I'll change it
if err != nil { | ||
return fmt.Errorf("Unable to set filter policy attribute on subscription: %s", err) | ||
if d.HasChange("delivery_policy") { | ||
_, dp := d.GetChange("delivery_policy") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same note about n
here 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
@bflad no problem, thanks for the fast feedback. I'll tidy up the code and let you know so you guys can run the acceptance tests |
Hey @bflad I've made the requested changes. I'll leave this with you now for the acceptance tests. Cheers |
🙁 oh this is fun, AWS will return a fully populated policy back. I'm not sure there is an easy way to handle the difference here, since guaranteed is a populated boolean attribute.
|
we could unmarshall the response into a map/struct and create a custom assertion |
Something like this:
|
This seems to work, although I'm not sure the full structures of healthyRetryPolicy, sicklyRetryPolicy, and throttlePolicy: type snsTopicSubscriptionDeliveryPolicy struct {
Guaranteed bool `json:"guaranteed,omitempty"`
HealthyRetryPolicy *snsTopicSubscriptionDeliveryPolicyHealthyRetryPolicy `json:"healthyRetryPolicy,omitempty"`
SicklyRetryPolicy *snsTopicSubscriptionDeliveryPolicySicklyRetryPolicy `json:"sicklyRetryPolicy,omitempty"`
ThrottlePolicy *snsTopicSubscriptionDeliveryPolicyThrottlePolicy `json:"throttlePolicy,omitempty"`
}
type snsTopicSubscriptionDeliveryPolicyHealthyRetryPolicy struct {
BackoffFunction string `json:"backoffFunction,omitempty"`
MaxDelayTarget int `json:"maxDelayTarget,omitempty"`
MinDelayTarget int `json:"minDelayTarget,omitempty"`
NumMaxDelayRetries int `json:"numMaxDelayRetries,omitempty"`
NumMinDelayRetries int `json:"numMinDelayRetries,omitempty"`
NumNoDelayRetries int `json:"numNoDelayRetries,omitempty"`
NumRetries int `json:"numRetries,omitempty"`
}
type snsTopicSubscriptionDeliveryPolicySicklyRetryPolicy struct {
BackoffFunction string `json:"backoffFunction,omitempty"`
MaxDelayTarget int `json:"maxDelayTarget,omitempty"`
MinDelayTarget int `json:"minDelayTarget,omitempty"`
NumMaxDelayRetries int `json:"numMaxDelayRetries,omitempty"`
NumMinDelayRetries int `json:"numMinDelayRetries,omitempty"`
NumNoDelayRetries int `json:"numNoDelayRetries,omitempty"`
NumRetries int `json:"numRetries,omitempty"`
}
type snsTopicSubscriptionDeliveryPolicyThrottlePolicy struct {
MaxReceivesPerSecond int `json:"maxReceivesPerSecond,omitempty"`
}
func normalizeSnsTopicSubscriptionDeliveryPolicy(v interface{}) string {
structureNormalizedJson, _ := structure.NormalizeJsonString(v)
var dp snsTopicSubscriptionDeliveryPolicy
err := json.Unmarshal([]byte(structureNormalizedJson), &dp)
if err != nil {
return structureNormalizedJson
}
bytes, _ := json.Marshal(dp)
return string(bytes[:])
}
func TestNormalizeSnsTopicSubscriptionDeliveryPolicy(t *testing.T) {
var testCases = []struct {
Input string
Expected string
}{
{
Input: `{"healthyRetryPolicy":{"minDelayTarget":5,"maxDelayTarget":20,"numRetries":5,"numMaxDelayRetries":null,"numNoDelayRetries":null,"numMinDelayRetries":null,"backoffFunction":null},"sicklyRetryPolicy":null,"throttlePolicy":null,"guaranteed":false}`,
Expected: `{"healthyRetryPolicy":{"maxDelayTarget":20,"minDelayTarget":5,"numRetries":5}}`,
},
{
Input: `{"healthyRetryPolicy":null,"sicklyRetryPolicy":null,"throttlePolicy":null,"guaranteed":true}`,
Expected: `{"guaranteed":true}`,
},
}
for _, tc := range testCases {
actual := normalizeSnsTopicSubscriptionDeliveryPolicy(tc.Input)
if actual != tc.Expected {
t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, tc.Expected)
}
}
}
|
Thanks for that, much more elaborated. It looks complete to me but I'm afraid I can't confirm whether the structures are complete since the structures seem to be barely documented by Amazon. IMO this is good enough for this test :) |
@ddcprg do you have an AWS account with higher than the basic support plan that could ask them for the (full) documentation of these? If we're going to support this functionality, we should probably try to get it right the first time rather than guess. If you don't, that's okay, its going to take me a little bit to get back to this PR myself. |
We do. Anything specific you'd like to ask them apart from the structure of the in and out JSON objects? I'll raise a ticket with them when I'm back in the office next Monday |
I think just knowing all the possible keys/values in the |
@bflad I'm still waiting for AWS support to get back to me with this info. They told me last Monday they were going to get in touch with the development team to get the details and ask them to update update the docs if necessary. |
Hey @bflad it seems like is going to take a while until we can get any feedback from the AWS team. I've just pinged support again and this is what they said:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @ddcprg 👋 Since it doesn't seem like we'll receive full documentation for this, so I'm opting to pull this in with the struct
handling I outlined in #3289 (comment) (except using DiffSuppressFunc
instead of StateFunc
for the attribute). We can iterate as necessary. With code and testing updates:
--- PASS: TestAccAWSSNSTopicSubscription_basic (14.24s)
--- PASS: TestAccAWSSNSTopicSubscription_importBasic (15.24s)
--- PASS: TestAccAWSSNSTopicSubscription_deliveryPolicy (23.04s)
--- PASS: TestAccAWSSNSTopicSubscription_filterPolicy (23.49s)
--- PASS: TestAccAWSSNSTopicSubscription_autoConfirmingEndpoint (42.79s)
--- PASS: TestAccAWSSNSTopicSubscription_autoConfirmingSecuredEndpoint (76.68s)
Hi @bflad yeah, it'll probably take long until we hear from them, thanks for letting me know |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks! |
Fixes #3288