Added support for http/https endpoints that auto confirms SNS topic subscription.
http and https SNS topic subscription endpoints require confirmation to set a valid arn otherwise arn would be set to "pending confirmation". If the endpoints auto confirm then arn is set asynchronously but if we try to create another subscription with same parameters then api returns "pending subscription" as arn but does not create another a duplicate subscription. In order to solve this we should be fetching the subscription list for the topic and identify the subscription with same parameters i.e., protocol, topic_arn, endpoint and extract the subscription arn. Following changes were made to support the http/https endpoints that auto confirms 1. Added 3 extra parameters i.e., 1. endpoint_auto_confirms -> boolean indicates if end points auto confirms 2. max_fetch_retries -> number of times to fetch subscription list for the topic to get the subscription arn 3. fetch_retry_delay -> delay b/w fetch subscription list call as the confirmation is done asynchronously. With these parameters help added support http and https protocol based endpoints that auto confirm. 2. Update website doc appropriately
This commit is contained in:
parent
176a99348a
commit
9d125944c0
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/sns"
|
||||
"time"
|
||||
)
|
||||
|
||||
const awsSNSPendingConfirmationMessage = "pending confirmation"
|
||||
|
@ -27,7 +28,7 @@ func resourceAwsSnsTopicSubscription() *schema.Resource {
|
|||
ForceNew: false,
|
||||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
forbidden := []string{"email", "sms", "http"}
|
||||
forbidden := []string{"email", "sms"}
|
||||
for _, f := range forbidden {
|
||||
if strings.Contains(value, f) {
|
||||
errors = append(
|
||||
|
@ -44,6 +45,24 @@ func resourceAwsSnsTopicSubscription() *schema.Resource {
|
|||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
"endpoint_auto_confirms": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
Default: false,
|
||||
},
|
||||
"max_fetch_retries": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
Default: 3,
|
||||
},
|
||||
"fetch_retry_delay": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
Default: 1,
|
||||
},
|
||||
"topic_arn": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
|
@ -178,6 +197,13 @@ func subscribeToSNSTopic(d *schema.ResourceData, snsconn *sns.SNS) (output *sns.
|
|||
protocol := d.Get("protocol").(string)
|
||||
endpoint := d.Get("endpoint").(string)
|
||||
topic_arn := d.Get("topic_arn").(string)
|
||||
endpoint_auto_confirms := d.Get("endpoint_auto_confirms").(bool)
|
||||
max_fetch_retries := d.Get("max_fetch_retries").(int)
|
||||
fetch_retry_delay := time.Duration(d.Get("fetch_retry_delay").(int))
|
||||
|
||||
if strings.Contains(protocol, "http") && !endpoint_auto_confirms {
|
||||
return nil, fmt.Errorf("Protocol http/https is only supported for endpoints which auto confirms!")
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] SNS create topic subscription: %s (%s) @ '%s'", endpoint, protocol, topic_arn)
|
||||
|
||||
|
@ -192,6 +218,64 @@ func subscribeToSNSTopic(d *schema.ResourceData, snsconn *sns.SNS) (output *sns.
|
|||
return nil, fmt.Errorf("Error creating SNS topic: %s", err)
|
||||
}
|
||||
|
||||
if strings.Contains(protocol, "http") && (output.SubscriptionArn == nil || *output.SubscriptionArn == awsSNSPendingConfirmationMessage) {
|
||||
|
||||
log.Printf("[DEBUG] SNS create topic subscritpion is pending so fetching the subscription list for topic : %s (%s) @ '%s'", endpoint, protocol, topic_arn)
|
||||
|
||||
for i := 0; i < max_fetch_retries && output.SubscriptionArn != nil && *output.SubscriptionArn == awsSNSPendingConfirmationMessage; i++ {
|
||||
|
||||
subscription, err := findSubscriptionByNonID(d, snsconn)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error fetching subscriptions for SNS topic %s: %s", topic_arn, err)
|
||||
}
|
||||
|
||||
if subscription != nil {
|
||||
output.SubscriptionArn = subscription.SubscriptionArn
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * fetch_retry_delay)
|
||||
}
|
||||
|
||||
if output.SubscriptionArn == nil || *output.SubscriptionArn == awsSNSPendingConfirmationMessage {
|
||||
return nil, fmt.Errorf("Endpoint (%s) did not autoconfirm the subscription for topic %s", endpoint, topic_arn)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Created new subscription!")
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// finds a subscription using protocol, endpoint and topic_arn (which is a key in sns subscription)
|
||||
func findSubscriptionByNonID(d *schema.ResourceData, snsconn *sns.SNS) (*sns.Subscription, error) {
|
||||
protocol := d.Get("protocol").(string)
|
||||
endpoint := d.Get("endpoint").(string)
|
||||
topic_arn := d.Get("topic_arn").(string)
|
||||
|
||||
req := &sns.ListSubscriptionsByTopicInput{
|
||||
TopicArn: aws.String(topic_arn),
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
res, err := snsconn.ListSubscriptionsByTopic(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error fetching subscripitions for topic %s : %s", topic_arn, err)
|
||||
}
|
||||
|
||||
for _, subscription := range res.Subscriptions {
|
||||
if *subscription.Endpoint == endpoint && *subscription.Protocol == protocol && *subscription.TopicArn == topic_arn {
|
||||
return subscription, nil
|
||||
}
|
||||
}
|
||||
|
||||
// if there are more than 100 subscriptions then go to the next 100 otherwise return nil
|
||||
if res.NextToken != nil {
|
||||
req.NextToken = res.NextToken
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,11 @@ resource "aws_sns_topic_subscription" "user_updates_sqs_target" {
|
|||
The following arguments are supported:
|
||||
|
||||
* `topic_arn` - (Required) The ARN of the SNS topic to subscribe to
|
||||
* `protocol` - (Required) The protocol to use. The possible values for this are: `sqs`, `lambda`, or `application`. (`email`, `http`, `https`, `sms`, are options but unsupported, see below)
|
||||
* `protocol` - (Required) The protocol to use. The possible values for this are: `sqs`, `lambda`, `application`. (`http` or `https` are partially supported, see below) (`email`, `sms`, are options but unsupported, see below).
|
||||
* `endpoint` - (Required) The endpoint to send data to, the contents will vary with the protocol. (see below for more information)
|
||||
* `endpoint_auto_confirms` - (Optional) Boolean indicating whether the end point is capable of auto confirming subscription (default is false)
|
||||
* `max_fetch_retries` - (Optional) Integer indicating number of times the subscriptions list for a topic to be fetched to get the subscription arn for auto confirming end points.
|
||||
* `fetch_retry_delay` - (Optional) Integer indicating number of seconds to sleep before re-fetching the subscription list for the topic.
|
||||
* `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).
|
||||
|
||||
### Protocols supported
|
||||
|
@ -61,12 +64,15 @@ Supported SNS protocols include:
|
|||
* `sqs` -- delivery of JSON-encoded message to an Amazon SQS queue
|
||||
* `application` -- delivery of JSON-encoded message to an EndpointArn for a mobile app and device
|
||||
|
||||
Partially supported SNS protocols include:
|
||||
|
||||
* `http` -- delivery of JSON-encoded messages via HTTP. Supported only for the end points that auto confirms the subscription.
|
||||
* `https` -- delivery of JSON-encoded messages via HTTPS. Supported only for the end points that auto confirms the subscription.
|
||||
|
||||
Unsupported protocols include the following:
|
||||
|
||||
* `email` -- delivery of message via SMTP
|
||||
* `email-json` -- delivery of JSON-encoded message via SMTP
|
||||
* `http` -- delivery via HTTP
|
||||
* `http(s)` -- delivery via HTTPS
|
||||
* `sms` -- delivery text message
|
||||
|
||||
These are unsupported because the endpoint needs to be authorized and does not
|
||||
|
|
Loading…
Reference in New Issue