Allow SNS topics to be created without subscriptions. Also added better error handling around boto calls.
This commit is contained in:
parent
b51efc51bc
commit
ce9aed9c52
1 changed files with 52 additions and 23 deletions
|
@ -132,8 +132,8 @@ import json
|
||||||
import re
|
import re
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import boto
|
|
||||||
import boto.sns
|
import boto.sns
|
||||||
|
from boto.exception import BotoServerError
|
||||||
HAS_BOTO = True
|
HAS_BOTO = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_BOTO = False
|
HAS_BOTO = False
|
||||||
|
@ -146,12 +146,15 @@ def canonicalize_endpoint(protocol, endpoint):
|
||||||
return endpoint
|
return endpoint
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_topics(connection, module):
|
||||||
def get_all_topics(connection):
|
|
||||||
next_token = None
|
next_token = None
|
||||||
topics = []
|
topics = []
|
||||||
while True:
|
while True:
|
||||||
|
try:
|
||||||
response = connection.get_all_topics(next_token)
|
response = connection.get_all_topics(next_token)
|
||||||
|
except BotoServerError, e:
|
||||||
|
module.fail_json(msg=e.message)
|
||||||
|
|
||||||
topics.extend(response['ListTopicsResponse']['ListTopicsResult']['Topics'])
|
topics.extend(response['ListTopicsResponse']['ListTopicsResult']['Topics'])
|
||||||
next_token = \
|
next_token = \
|
||||||
response['ListTopicsResponse']['ListTopicsResult']['NextToken']
|
response['ListTopicsResponse']['ListTopicsResult']['NextToken']
|
||||||
|
@ -160,15 +163,16 @@ def get_all_topics(connection):
|
||||||
return [t['TopicArn'] for t in topics]
|
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
|
# 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
|
lookup_topic = ':%s' % short_topic
|
||||||
for topic in all_topics:
|
for topic in all_topics:
|
||||||
if topic.endswith(lookup_topic):
|
if topic.endswith(lookup_topic):
|
||||||
return topic
|
return topic
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argument_spec = ec2_argument_spec()
|
argument_spec = ec2_argument_spec()
|
||||||
argument_spec.update(
|
argument_spec.update(
|
||||||
|
@ -179,7 +183,7 @@ def main():
|
||||||
display_name=dict(type='str', required=False),
|
display_name=dict(type='str', required=False),
|
||||||
policy=dict(type='dict', required=False),
|
policy=dict(type='dict', required=False),
|
||||||
delivery_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),
|
purge_subscriptions=dict(type='bool', default=True),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -214,7 +218,7 @@ def main():
|
||||||
|
|
||||||
# topics cannot contain ':', so thats the decider
|
# topics cannot contain ':', so thats the decider
|
||||||
if ':' in name:
|
if ':' in name:
|
||||||
all_topics = get_all_topics(connection)
|
all_topics = get_all_topics(connection, module)
|
||||||
if name in all_topics:
|
if name in all_topics:
|
||||||
arn_topic = name
|
arn_topic = name
|
||||||
elif state == 'absent':
|
elif state == 'absent':
|
||||||
|
@ -223,7 +227,7 @@ def main():
|
||||||
module.fail_json(msg="specified an ARN for a topic but it doesn't"
|
module.fail_json(msg="specified an ARN for a topic but it doesn't"
|
||||||
" exist")
|
" exist")
|
||||||
else:
|
else:
|
||||||
arn_topic = arn_topic_lookup(connection, name)
|
arn_topic = arn_topic_lookup(connection, name, module)
|
||||||
if not arn_topic:
|
if not arn_topic:
|
||||||
if state == 'absent':
|
if state == 'absent':
|
||||||
module.exit_json(changed=False)
|
module.exit_json(changed=False)
|
||||||
|
@ -234,15 +238,22 @@ def main():
|
||||||
|
|
||||||
changed=True
|
changed=True
|
||||||
topic_created = True
|
topic_created = True
|
||||||
|
try:
|
||||||
connection.create_topic(name)
|
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:
|
while not arn_topic:
|
||||||
time.sleep(3)
|
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 arn_topic and state == "absent":
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
|
try:
|
||||||
connection.delete_topic(arn_topic)
|
connection.delete_topic(arn_topic)
|
||||||
|
except BotoServerError, e:
|
||||||
|
module.fail_json(msg=e.message)
|
||||||
|
|
||||||
module.exit_json(changed=True)
|
module.exit_json(changed=True)
|
||||||
|
|
||||||
topic_attributes = connection.get_topic_attributes(arn_topic) \
|
topic_attributes = connection.get_topic_attributes(arn_topic) \
|
||||||
|
@ -252,30 +263,40 @@ def main():
|
||||||
changed = True
|
changed = True
|
||||||
attributes_set.append('display_name')
|
attributes_set.append('display_name')
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
connection.set_topic_attributes(arn_topic, 'DisplayName',
|
try:
|
||||||
display_name)
|
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']):
|
if policy and policy != json.loads(topic_attributes['policy']):
|
||||||
changed = True
|
changed = True
|
||||||
attributes_set.append('policy')
|
attributes_set.append('policy')
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
connection.set_topic_attributes(arn_topic, 'Policy',
|
try:
|
||||||
json.dumps(policy))
|
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 \
|
if delivery_policy and ('DeliveryPolicy' not in topic_attributes or \
|
||||||
delivery_policy != json.loads(topic_attributes['DeliveryPolicy'])):
|
delivery_policy != json.loads(topic_attributes['DeliveryPolicy'])):
|
||||||
changed = True
|
changed = True
|
||||||
attributes_set.append('delivery_policy')
|
attributes_set.append('delivery_policy')
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
connection.set_topic_attributes(arn_topic, 'DeliveryPolicy',
|
try:
|
||||||
json.dumps(delivery_policy))
|
connection.set_topic_attributes(arn_topic, 'DeliveryPolicy',json.dumps(delivery_policy))
|
||||||
|
except BotoServerError, e:
|
||||||
|
module.fail_json(msg=e.message)
|
||||||
|
|
||||||
|
|
||||||
next_token = None
|
next_token = None
|
||||||
aws_subscriptions = []
|
aws_subscriptions = []
|
||||||
while True:
|
while True:
|
||||||
|
try:
|
||||||
response = connection.get_all_subscriptions_by_topic(arn_topic,
|
response = connection.get_all_subscriptions_by_topic(arn_topic,
|
||||||
next_token)
|
next_token)
|
||||||
|
except BotoServerError, e:
|
||||||
|
module.fail_json(msg=e.message)
|
||||||
|
|
||||||
aws_subscriptions.extend(response['ListSubscriptionsByTopicResponse'] \
|
aws_subscriptions.extend(response['ListSubscriptionsByTopicResponse'] \
|
||||||
['ListSubscriptionsByTopicResult']['Subscriptions'])
|
['ListSubscriptionsByTopicResult']['Subscriptions'])
|
||||||
next_token = response['ListSubscriptionsByTopicResponse'] \
|
next_token = response['ListSubscriptionsByTopicResponse'] \
|
||||||
|
@ -286,6 +307,7 @@ def main():
|
||||||
desired_subscriptions = [(sub['protocol'],
|
desired_subscriptions = [(sub['protocol'],
|
||||||
canonicalize_endpoint(sub['protocol'], sub['endpoint'])) for sub in
|
canonicalize_endpoint(sub['protocol'], sub['endpoint'])) for sub in
|
||||||
subscriptions]
|
subscriptions]
|
||||||
|
|
||||||
aws_subscriptions_list = []
|
aws_subscriptions_list = []
|
||||||
|
|
||||||
for sub in aws_subscriptions:
|
for sub in aws_subscriptions:
|
||||||
|
@ -296,14 +318,20 @@ def main():
|
||||||
changed = True
|
changed = True
|
||||||
subscriptions_deleted.append(sub_key)
|
subscriptions_deleted.append(sub_key)
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
|
try:
|
||||||
connection.unsubscribe(sub['SubscriptionArn'])
|
connection.unsubscribe(sub['SubscriptionArn'])
|
||||||
|
except BotoServerError, e:
|
||||||
|
module.fail_json(msg=e.message)
|
||||||
|
|
||||||
for (protocol, endpoint) in desired_subscriptions:
|
for (protocol, endpoint) in desired_subscriptions:
|
||||||
if (protocol, endpoint) not in aws_subscriptions_list:
|
if (protocol, endpoint) not in aws_subscriptions_list:
|
||||||
changed = True
|
changed = True
|
||||||
subscriptions_added.append(sub)
|
subscriptions_added.append(sub)
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
|
try:
|
||||||
connection.subscribe(arn_topic, protocol, endpoint)
|
connection.subscribe(arn_topic, protocol, endpoint)
|
||||||
|
except BotoServerError, e:
|
||||||
|
module.fail_json(msg=e.message)
|
||||||
|
|
||||||
module.exit_json(changed=changed, topic_created=topic_created,
|
module.exit_json(changed=changed, topic_created=topic_created,
|
||||||
attributes_set=attributes_set,
|
attributes_set=attributes_set,
|
||||||
|
@ -313,4 +341,5 @@ def main():
|
||||||
from ansible.module_utils.basic import *
|
from ansible.module_utils.basic import *
|
||||||
from ansible.module_utils.ec2 import *
|
from ansible.module_utils.ec2 import *
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in a new issue