Skip to content

Commit

Permalink
[PR #972/1795e49f backport][stable-5] sns_topic - Add tags and purge_…
Browse files Browse the repository at this point in the history
…tags options (#1688)

[PR #972/1795e49f backport][stable-5] sns_topic - Add tags and purge_tags options

This is a backport of PR #972 as merged into main (1795e49).
SUMMARY

sns_topic - Add tags and purge_tags options
Closes #964

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

sns_topic

Reviewed-by: Mark Chappell <None>
  • Loading branch information
patchback[bot] committed Feb 1, 2023
1 parent 68c0ac4 commit 4e93bd1
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 12 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/972-sns_topic-add_tags.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- sns_topic - add support for ``tags`` and ``purge_tags`` (https://github.com/ansible-collections/community.aws/pull/972).
45 changes: 44 additions & 1 deletion plugins/module_utils/sns.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import compare_aws_tags


@AWSRetry.jittered_backoff()
Expand Down Expand Up @@ -87,6 +91,16 @@ def canonicalize_endpoint(protocol, endpoint):
return endpoint


def get_tags(client, module, topic_arn):
try:
return boto3_tag_list_to_ansible_dict(client.list_tags_for_resource(ResourceArn=topic_arn)['Tags'])
except is_boto3_error_code('AuthorizationError'):
module.warn("Permission denied accessing tags")
return {}
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg="Couldn't obtain topic tags")


def get_info(connection, module, topic_arn):
name = module.params.get('name')
topic_type = module.params.get('topic_type')
Expand Down Expand Up @@ -121,5 +135,34 @@ def get_info(connection, module, topic_arn):
info.update(camel_dict_to_snake_dict(connection.get_topic_attributes(TopicArn=topic_arn)['Attributes']))
info['delivery_policy'] = info.pop('effective_delivery_policy')
info['subscriptions'] = [camel_dict_to_snake_dict(sub) for sub in list_topic_subscriptions(connection, module, topic_arn)]

info["tags"] = get_tags(connection, module, topic_arn)
return info


def update_tags(client, module, topic_arn):

if module.params.get('tags') is None:
return False

existing_tags = get_tags(client, module, topic_arn)
to_update, to_delete = compare_aws_tags(existing_tags, module.params['tags'], module.params['purge_tags'])

if not bool(to_delete or to_update):
return False

if module.check_mode:
return True

if to_update:
try:
client.tag_resource(ResourceArn=topic_arn,
Tags=ansible_dict_to_boto3_tag_list(to_update))
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg="Couldn't add tags to topic")
if to_delete:
try:
client.untag_resource(ResourceArn=topic_arn, TagKeys=to_delete)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg="Couldn't remove tags from topic")

return True
30 changes: 24 additions & 6 deletions plugins/modules/sns_topic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
short_description: Manages AWS SNS topics and subscriptions
version_added: 1.0.0
description:
- The M(community.aws.sns_topic) module allows you to create, delete, and manage subscriptions for AWS SNS topics.
- As of 2.6, this module can be use to subscribe and unsubscribe to topics outside of your AWS account.
- The M(community.aws.sns_topic) module allows you to create, delete, and manage subscriptions for AWS SNS topics.
author:
- "Joel Thompson (@joelthompson)"
- "Fernando Jose Pando (@nand0p)"
Expand Down Expand Up @@ -149,10 +148,13 @@
Blame Amazon."
default: true
type: bool
notes:
- Support for I(tags) and I(purge_tags) was added in release 5.3.0.
extends_documentation_fragment:
- amazon.aws.aws
- amazon.aws.ec2
- amazon.aws.boto3
- amazon.aws.aws
- amazon.aws.ec2
- amazon.aws.tags
- amazon.aws.boto3
'''

EXAMPLES = r"""
Expand Down Expand Up @@ -328,12 +330,14 @@
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.core import scrub_none_parameters
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import compare_policies
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list
from ansible_collections.community.aws.plugins.module_utils.sns import list_topics
from ansible_collections.community.aws.plugins.module_utils.sns import topic_arn_lookup
from ansible_collections.community.aws.plugins.module_utils.sns import compare_delivery_policies
from ansible_collections.community.aws.plugins.module_utils.sns import list_topic_subscriptions
from ansible_collections.community.aws.plugins.module_utils.sns import canonicalize_endpoint
from ansible_collections.community.aws.plugins.module_utils.sns import get_info
from ansible_collections.community.aws.plugins.module_utils.sns import update_tags


class SnsTopicManager(object):
Expand All @@ -349,6 +353,8 @@ def __init__(self,
delivery_policy,
subscriptions,
purge_subscriptions,
tags,
purge_tags,
check_mode):

self.connection = module.client('sns')
Expand All @@ -371,6 +377,8 @@ def __init__(self,
self.topic_deleted = False
self.topic_arn = None
self.attributes_set = []
self.tags = tags
self.purge_tags = purge_tags

def _create_topic(self):
attributes = {}
Expand All @@ -383,6 +391,9 @@ def _create_topic(self):
if not self.name.endswith('.fifo'):
self.name = self.name + '.fifo'

if self.tags:
tags = ansible_dict_to_boto3_tag_list(self.tags)

if not self.check_mode:
try:
response = self.connection.create_topic(Name=self.name,
Expand Down Expand Up @@ -542,12 +553,13 @@ def ensure_ok(self):
elif self.display_name or self.policy or self.delivery_policy:
self.module.fail_json(msg="Cannot set display name, policy or delivery policy for SNS topics not owned by this account")
changed |= self._set_topic_subs()

self._init_desired_subscription_attributes()
if self.topic_arn in list_topics(self.connection, self.module):
changed |= self._set_topic_subs_attributes()
elif any(self.desired_subscription_attributes.values()):
self.module.fail_json(msg="Cannot set subscription attributes for SNS topics not owned by this account")
# Check tagging
changed |= update_tags(self.connection, self.module, self.topic_arn)

return changed

Expand Down Expand Up @@ -600,6 +612,8 @@ def main():
delivery_policy=dict(type='dict', options=delivery_args),
subscriptions=dict(default=[], type='list', elements='dict'),
purge_subscriptions=dict(type='bool', default=True),
tags=dict(type='dict', aliases=['resource_tags']),
purge_tags=dict(type='bool', default=True),
)

module = AnsibleAWSModule(argument_spec=argument_spec,
Expand All @@ -614,6 +628,8 @@ def main():
subscriptions = module.params.get('subscriptions')
purge_subscriptions = module.params.get('purge_subscriptions')
check_mode = module.check_mode
tags = module.params.get('tags')
purge_tags = module.params.get('purge_tags')

sns_topic = SnsTopicManager(module,
name,
Expand All @@ -624,6 +640,8 @@ def main():
delivery_policy,
subscriptions,
purge_subscriptions,
tags,
purge_tags,
check_mode)

if state == 'present':
Expand Down
170 changes: 165 additions & 5 deletions tests/integration/targets/sns_topic/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
create_instance_profile: false
managed_policies:
- 'arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess'
wait: True
register: iam_role

- name: pause if role was created
pause:
seconds: 10
when: iam_role is changed

- name: list all the topics (check_mode)
sns_topic_info:
check_mode: true
Expand Down Expand Up @@ -428,6 +424,170 @@
- third_party_deletion is failed
- third_party_topic.sns_topic.subscriptions|length == third_party_deletion_facts.sns_topic.subscriptions|length

# Test tags
- name: create standard SNS topic
sns_topic:
name: '{{ sns_topic_topic_name }}'
display_name: My topic name
register: sns_topic_create

- name: assert that creation worked
assert:
that:
- sns_topic_create.changed

- name: set sns_arn fact
set_fact:
sns_arn: '{{ sns_topic_create.sns_arn }}'

- name: Add tags to topic - CHECK_MODE
sns_topic:
name: '{{ sns_topic_topic_name }}'
tags:
tag_one: '{{ tiny_prefix }} One'
"Tag Two": 'two {{ tiny_prefix }}'
check_mode: true
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Add tags to topic
sns_topic:
name: '{{ sns_topic_topic_name }}'
tags:
tag_one: '{{ tiny_prefix }} One'
"Tag Two": 'two {{ tiny_prefix }}'
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Add tags to topic to verify idempotency - CHECK_MODE
sns_topic:
name: '{{ sns_topic_topic_name }}'
tags:
tag_one: '{{ tiny_prefix }} One'
"Tag Two": 'two {{ tiny_prefix }}'
check_mode: true
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is not changed

- name: Add tags to topic to verify idempotency
sns_topic:
name: '{{ sns_topic_topic_name }}'
tags:
tag_one: '{{ tiny_prefix }} One'
"Tag Two": 'two {{ tiny_prefix }}'
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is not changed

- name: Update (add/remove) tags - CHECK_MODE
sns_topic:
name: '{{ sns_topic_topic_name }}'
tags:
tag_three: '{{ tiny_prefix }} Three'
"Tag Two": 'two {{ tiny_prefix }}'
check_mode: true
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Update tags to verify idempotency
sns_topic:
name: '{{ sns_topic_topic_name }}'
tags:
tag_three: '{{ tiny_prefix }} Three'
"Tag Two": 'two {{ tiny_prefix }}'
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Update tags without purge - CHECK_MODE
sns_topic:
name: '{{ sns_topic_topic_name }}'
purge_tags: no
tags:
tag_one: '{{ tiny_prefix }} One'
check_mode: true
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Update tags without purge
sns_topic:
name: '{{ sns_topic_topic_name }}'
purge_tags: no
tags:
tag_one: '{{ tiny_prefix }} One'
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Remove all the tags - CHECK_MODE
sns_topic:
name: '{{ sns_topic_topic_name }}'
purge_tags: yes
tags: {}
check_mode: true
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Remove all the tags
sns_topic:
name: '{{ sns_topic_topic_name }}'
purge_tags: yes
tags: {}
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Update with CamelCase tags
sns_topic:
name: '{{ sns_topic_topic_name }}'
purge_tags: no
tags:
"lowercase spaced": 'hello cruel world'
"Title Case": 'Hello Cruel World'
CamelCase: 'SimpleCamelCase'
snake_case: 'simple_snake_case'
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is changed

- name: Do not specify any tag to ensure previous tags are not removed
sns_topic:
name: '{{ sns_topic_topic_name }}'
purge_tags: no
register: sns_topic_tags

- assert:
that:
- sns_topic_tags is not changed

always:

- name: announce teardown start
Expand Down

0 comments on commit 4e93bd1

Please sign in to comment.