Allow SNS topics to be created without subscriptions. Also added better error handling around boto calls.

This commit is contained in:
Rob White 2016-02-01 21:21:00 +11:00
parent b51efc51bc
commit ce9aed9c52

View file

@ -132,8 +132,8 @@ import json
import re
try:
import boto
import boto.sns
from boto.exception import BotoServerError
HAS_BOTO = True
except ImportError:
HAS_BOTO = False
@ -146,12 +146,15 @@ def canonicalize_endpoint(protocol, endpoint):
return endpoint
def get_all_topics(connection):
def get_all_topics(connection, module):
next_token = None
topics = []
while True:
try:
response = connection.get_all_topics(next_token)
except BotoServerError, e:
module.fail_json(msg=e.message)
topics.extend(response['ListTopicsResponse']['ListTopicsResult']['Topics'])
next_token = \
response['ListTopicsResponse']['ListTopicsResult']['NextToken']
@ -160,15 +163,16 @@ def get_all_topics(connection):
return [t['TopicArn'] for t in topics]
def arn_topic_lookup(connection, short_topic):
def arn_topic_lookup(connection, short_topic, module):
# topic names cannot have colons, so this captures the full topic name
all_topics = get_all_topics(connection)
all_topics = get_all_topics(connection, module)
lookup_topic = ':%s' % short_topic
for topic in all_topics:
if topic.endswith(lookup_topic):
return topic
return None
def main():
argument_spec = ec2_argument_spec()
argument_spec.update(
@ -179,7 +183,7 @@ def main():
display_name=dict(type='str', required=False),
policy=dict(type='dict', required=False),
delivery_policy=dict(type='dict', required=False),
subscriptions=dict(type='list', required=False),
subscriptions=dict(default=[], type='list', required=False),
purge_subscriptions=dict(type='bool', default=True),
)
)
@ -214,7 +218,7 @@ def main():
# topics cannot contain ':', so thats the decider
if ':' in name:
all_topics = get_all_topics(connection)
all_topics = get_all_topics(connection, module)
if name in all_topics:
arn_topic = name
elif state == 'absent':
@ -223,7 +227,7 @@ def main():
module.fail_json(msg="specified an ARN for a topic but it doesn't"
" exist")
else:
arn_topic = arn_topic_lookup(connection, name)
arn_topic = arn_topic_lookup(connection, name, module)
if not arn_topic:
if state == 'absent':
module.exit_json(changed=False)
@ -234,15 +238,22 @@ def main():
changed=True
topic_created = True
try:
connection.create_topic(name)
arn_topic = arn_topic_lookup(connection, name)
except BotoServerError, e:
module.fail_json(msg=e.message)
arn_topic = arn_topic_lookup(connection, name, module)
while not arn_topic:
time.sleep(3)
arn_topic = arn_topic_lookup(connection, name)
arn_topic = arn_topic_lookup(connection, name, module)
if arn_topic and state == "absent":
if not check_mode:
try:
connection.delete_topic(arn_topic)
except BotoServerError, e:
module.fail_json(msg=e.message)
module.exit_json(changed=True)
topic_attributes = connection.get_topic_attributes(arn_topic) \
@ -252,30 +263,40 @@ def main():
changed = True
attributes_set.append('display_name')
if not check_mode:
connection.set_topic_attributes(arn_topic, 'DisplayName',
display_name)
try:
connection.set_topic_attributes(arn_topic, 'DisplayName', display_name)
except BotoServerError, e:
module.fail_json(msg=e.message)
if policy and policy != json.loads(topic_attributes['policy']):
changed = True
attributes_set.append('policy')
if not check_mode:
connection.set_topic_attributes(arn_topic, 'Policy',
json.dumps(policy))
try:
connection.set_topic_attributes(arn_topic, 'Policy', json.dumps(policy))
except BotoServerError, e:
module.fail_json(msg=e.message)
if delivery_policy and ('DeliveryPolicy' not in topic_attributes or \
delivery_policy != json.loads(topic_attributes['DeliveryPolicy'])):
changed = True
attributes_set.append('delivery_policy')
if not check_mode:
connection.set_topic_attributes(arn_topic, 'DeliveryPolicy',
json.dumps(delivery_policy))
try:
connection.set_topic_attributes(arn_topic, 'DeliveryPolicy',json.dumps(delivery_policy))
except BotoServerError, e:
module.fail_json(msg=e.message)
next_token = None
aws_subscriptions = []
while True:
try:
response = connection.get_all_subscriptions_by_topic(arn_topic,
next_token)
except BotoServerError, e:
module.fail_json(msg=e.message)
aws_subscriptions.extend(response['ListSubscriptionsByTopicResponse'] \
['ListSubscriptionsByTopicResult']['Subscriptions'])
next_token = response['ListSubscriptionsByTopicResponse'] \
@ -286,6 +307,7 @@ def main():
desired_subscriptions = [(sub['protocol'],
canonicalize_endpoint(sub['protocol'], sub['endpoint'])) for sub in
subscriptions]
aws_subscriptions_list = []
for sub in aws_subscriptions:
@ -296,14 +318,20 @@ def main():
changed = True
subscriptions_deleted.append(sub_key)
if not check_mode:
try:
connection.unsubscribe(sub['SubscriptionArn'])
except BotoServerError, e:
module.fail_json(msg=e.message)
for (protocol, endpoint) in desired_subscriptions:
if (protocol, endpoint) not in aws_subscriptions_list:
changed = True
subscriptions_added.append(sub)
if not check_mode:
try:
connection.subscribe(arn_topic, protocol, endpoint)
except BotoServerError, e:
module.fail_json(msg=e.message)
module.exit_json(changed=changed, topic_created=topic_created,
attributes_set=attributes_set,
@ -313,4 +341,5 @@ def main():
from ansible.module_utils.basic import *
from ansible.module_utils.ec2 import *
main()
if __name__ == '__main__':
main()