From 7d98adc70de8aeee77a074cf57bb17497eaa099e Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 1 Jun 2022 13:11:59 +0200 Subject: [PATCH] Tagging fragment - use fragment and remove default empty dict where purge_tags default is True (#1183) Tagging - remove default empty dict where purge_tags default is True Depends-On: ansible-collections/amazon.aws#844 SUMMARY Move modules over to the new tagging fragment Update modules to remove default tags of {} and use None instead, so that purging tags only happens if someone explicitly passes the tags parameter ISSUE TYPE Docs Pull Request Feature Pull Request COMPONENT NAME plugins/modules/ec2_transit_gateway.py plugins/modules/efs.py plugins/modules/eks_fargate_profile.py plugins/modules/elb_target_group.py ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis --- changelogs/fragments/1183-tagging.yml | 6 ++ plugins/modules/ec2_transit_gateway.py | 94 +++++--------------------- plugins/modules/efs.py | 13 ++-- plugins/modules/eks_fargate_profile.py | 28 ++++---- plugins/modules/elb_target_group.py | 30 +++----- 5 files changed, 49 insertions(+), 122 deletions(-) create mode 100644 changelogs/fragments/1183-tagging.yml diff --git a/changelogs/fragments/1183-tagging.yml b/changelogs/fragments/1183-tagging.yml new file mode 100644 index 00000000000..84e0dd722b5 --- /dev/null +++ b/changelogs/fragments/1183-tagging.yml @@ -0,0 +1,6 @@ +minor_changes: +- efs - the default value for ``tags`` has been updated, to remove all tags the ``tags`` parameter must be explicitly set to the empty dict ``{}`` (https://github.com/ansible-collections/community.aws/pull/1183). +- ec2_transit_gateway - the default value for ``tags`` has been updated, to remove all tags the ``tags`` parameter must be explicitly set to the empty dict ``{}`` (https://github.com/ansible-collections/community.aws/pull/1183). +- eks_fargate_profile - the default value for ``tags`` has been updated, to remove all tags the ``tags`` parameter must be explicitly set to the empty dict ``{}`` (https://github.com/ansible-collections/community.aws/pull/1183). +- elb_target_group - explicitly setting the ``tags`` parameter to the empty dict ``{}`` will now remove all tags unles ``purge_tags`` is explicitly set to ``False`` (https://github.com/ansible-collections/community.aws/pull/1183). +- ec2_transit_gateway - code updated to use common ``ensure_ec2_tags`` helper (https://github.com/ansible-collections/community.aws/pull/1183). diff --git a/plugins/modules/ec2_transit_gateway.py b/plugins/modules/ec2_transit_gateway.py index 4237376203b..be1082768fa 100644 --- a/plugins/modules/ec2_transit_gateway.py +++ b/plugins/modules/ec2_transit_gateway.py @@ -44,11 +44,6 @@ - Whether to enable AWS DNS support. default: true type: bool - purge_tags: - description: - - Whether to purge existing tags not included with tags argument. - default: true - type: bool state: description: - C(present) to ensure resource is created. @@ -56,10 +51,6 @@ default: present choices: [ "present", "absent"] type: str - tags: - description: - - A dictionary of resource tags - type: dict transit_gateway_id: description: - The ID of the transit gateway. @@ -80,11 +71,12 @@ default: 300 type: int -author: "Bob Boldin (@BobBoldin)" +author: + - "Bob Boldin (@BobBoldin)" extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 - + - amazon.aws.aws + - amazon.aws.ec2 + - amazon.aws.tags ''' EXAMPLES = ''' @@ -226,15 +218,11 @@ from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from time import sleep, time -from ansible.module_utils._text import to_text -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ( - ansible_dict_to_boto3_tag_list, - ansible_dict_to_boto3_filter_list, - AWSRetry, - boto3_tag_list_to_ansible_dict, - camel_dict_to_snake_dict, - compare_aws_tags -) +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict +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 ensure_ec2_tags class AnsibleEc2Tgw(object): @@ -412,57 +400,6 @@ def delete_tgw(self, tgw_id): return result - def ensure_tags(self, tgw_id, tags, purge_tags): - """ - Ensures tags are applied to the transit gateway. Optionally will remove any - existing tags not in the tags argument if purge_tags is set to true - - :param tgw_id: The AWS id of the transit gateway - :param tags: list of tags to apply to the transit gateway. - :param purge_tags: when true existing tags not in tags parms are removed - :return: true if tags were updated - """ - tags_changed = False - filters = ansible_dict_to_boto3_filter_list({'resource-id': tgw_id}) - try: - cur_tags = self._connection.describe_tags(Filters=filters) - except (ClientError, BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't describe tags") - - to_update, to_delete = compare_aws_tags(boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')), tags, purge_tags) - - if to_update: - try: - if not self._check_mode: - AWSRetry.exponential_backoff()(self._connection.create_tags)( - Resources=[tgw_id], - Tags=ansible_dict_to_boto3_tag_list(to_update) - ) - self._results['changed'] = True - tags_changed = True - except (ClientError, BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't create tags {0} for resource {1}".format( - ansible_dict_to_boto3_tag_list(to_update), tgw_id)) - - if to_delete: - try: - if not self._check_mode: - tags_list = [] - for key in to_delete: - tags_list.append({'Key': key}) - - AWSRetry.exponential_backoff()(self._connection.delete_tags)( - Resources=[tgw_id], - Tags=tags_list - ) - self._results['changed'] = True - tags_changed = True - except (ClientError, BotoCoreError) as e: - self._module.fail_json_aws(e, msg="Couldn't delete tags {0} for resource {1}".format( - ansible_dict_to_boto3_tag_list(to_delete), tgw_id)) - - return tags_changed - def ensure_tgw_present(self, tgw_id=None, description=None): """ Will create a tgw if no match to the tgw_id or description are found @@ -488,10 +425,11 @@ def ensure_tgw_present(self, tgw_id=None, description=None): except (BotoCoreError, ClientError) as e: self._module.fail_json_aws(e, msg='Unable to create Transit Gateway') - if self._module.params.get('tags') != tgw.get('tags'): - stringed_tags_dict = dict((to_text(k), to_text(v)) for k, v in self._module.params.get('tags').items()) - if self.ensure_tags(tgw['transit_gateway_id'], stringed_tags_dict, self._module.params.get('purge_tags')): - self._results['changed'] = True + self._results['changed'] |= ensure_ec2_tags( + self._connection, self._module, tgw['transit_gateway_id'], + tags=self._module.params.get('tags'), + purge_tags=self._module.params.get('purge_tags'), + ) self._results['transit_gateway'] = self.get_matching_tgw(tgw_id=tgw['transit_gateway_id']) @@ -539,7 +477,7 @@ def setup_module_object(): dns_support=dict(type='bool', default='yes'), purge_tags=dict(type='bool', default='yes'), state=dict(default='present', choices=['present', 'absent']), - tags=dict(default=dict(), type='dict'), + tags=dict(type='dict', aliases=['resource_tags']), transit_gateway_id=dict(type='str'), vpn_ecmp_support=dict(type='bool', default='yes'), wait=dict(type='bool', default='yes'), diff --git a/plugins/modules/efs.py b/plugins/modules/efs.py index a67c83be3c7..a78f832d971 100644 --- a/plugins/modules/efs.py +++ b/plugins/modules/efs.py @@ -28,12 +28,6 @@ required if you want to use a non-default CMK. If this parameter is not specified, the default CMK for Amazon EFS is used. The key id can be Key ID, Key ID ARN, Key Alias or Key Alias ARN. type: str - purge_tags: - description: - - If yes, existing tags will be purged from the resource to match exactly what is defined by I(tags) parameter. If the I(tags) parameter - is not set then tags will not be modified. - type: bool - default: true state: description: - Allows to create, search and destroy Amazon EFS file system. @@ -107,8 +101,9 @@ version_added: 2.1.0 extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 + - amazon.aws.aws + - amazon.aws.ec2 + - amazon.aws.tags ''' @@ -725,7 +720,7 @@ def main(): purge_tags=dict(default=True, type='bool'), id=dict(required=False, type='str', default=None), name=dict(required=False, type='str', default=None), - tags=dict(required=False, type="dict", default={}), + tags=dict(required=False, type="dict", aliases=['resource_tags']), targets=dict(required=False, type="list", default=[], elements='dict'), performance_mode=dict(required=False, type='str', choices=["general_purpose", "max_io"], default="general_purpose"), transition_to_ia=dict(required=False, type='str', choices=["None", "7", "14", "30", "60", "90"], default=None), diff --git a/plugins/modules/eks_fargate_profile.py b/plugins/modules/eks_fargate_profile.py index 5ddad654d7f..72164a36fea 100644 --- a/plugins/modules/eks_fargate_profile.py +++ b/plugins/modules/eks_fargate_profile.py @@ -12,8 +12,9 @@ version_added: 4.0.0 short_description: Manage EKS Fargate Profile description: - - Manage EKS Fargate Profile. -author: Tiago Jarra (@tjarra) + - Manage EKS Fargate Profile. +author: + - Tiago Jarra (@tjarra) options: name: description: Name of EKS Fargate Profile. @@ -54,14 +55,6 @@ - present default: present type: str - tags: - description: A dictionary of resource tags. - type: dict - purge_tags: - description: - - Purge existing tags that are not found in the cluster. - type: bool - default: true wait: description: >- Specifies whether the module waits until the profile is created or deleted before moving on. @@ -74,8 +67,9 @@ default: 1200 type: int extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 + - amazon.aws.aws + - amazon.aws.ec2 + - amazon.aws.tags ''' @@ -184,9 +178,13 @@ def validate_tags(client, module, fargate_profile): changed = False + desired_tags = module.params.get('tags') + if desired_tags is None: + return False + try: existing_tags = client.list_tags_for_resource(resourceArn=fargate_profile['fargateProfileArn'])['tags'] - tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, module.params.get('tags'), module.params.get('purge_tags')) + tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, desired_tags, module.params.get('purge_tags')) except(botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to list or compare tags for Fargate Profile %s' % module.params.get('name')) @@ -215,7 +213,7 @@ def create_or_update_fargate_profile(client, module): role_arn = module.params['role_arn'] cluster_name = module.params['cluster_name'] selectors = module.params['selectors'] - tags = module.params['tags'] + tags = module.params['tags'] or {} wait = module.params.get('wait') fargate_profile = get_fargate_profile(client, module, name, cluster_name) @@ -325,7 +323,7 @@ def main(): namespace=dict(type='str'), labels=dict(type='dict', default={}) )), - tags=dict(type='dict', default={}), + tags=dict(type='dict', aliases=['resource_tags']), purge_tags=dict(type='bool', default=True), state=dict(choices=['absent', 'present'], default='present'), wait=dict(default=False, type='bool'), diff --git a/plugins/modules/elb_target_group.py b/plugins/modules/elb_target_group.py index 917e352c75b..c0a71c3c0e5 100644 --- a/plugins/modules/elb_target_group.py +++ b/plugins/modules/elb_target_group.py @@ -12,10 +12,11 @@ version_added: 1.0.0 short_description: Manage a target group for an Application or Network load balancer description: - - Manage an AWS Elastic Load Balancer target group. See - U(https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html) or - U(https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html) for details. -author: "Rob White (@wimnat)" + - Manage an AWS Elastic Load Balancer target group. See + U(https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html) or + U(https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html) for details. +author: + - "Rob White (@wimnat)" options: deregistration_delay_timeout: description: @@ -88,13 +89,6 @@ required: false choices: [ 'http', 'https', 'tcp', 'tls', 'udp', 'tcp_udp', 'HTTP', 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP'] type: str - purge_tags: - description: - - If yes, existing tags will be purged from the resource to match exactly what is defined by I(tags) parameter. If the tag parameter is not set then - tags will not be modified. - required: false - default: yes - type: bool state: description: - Create or destroy the target group. @@ -143,11 +137,6 @@ - Requires the I(health_check_protocol) parameter to be set. required: false type: str - tags: - description: - - A dictionary of one or more tags to assign to the target group. - required: false - type: dict target_type: description: - The type of target that you must specify when registering targets with this target group. The possible values are @@ -208,8 +197,9 @@ default: 200 type: int extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 + - amazon.aws.aws + - amazon.aws.ec2 + - amazon.aws.tags notes: - Once a target group has been created, only its health check can then be modified using subsequent calls @@ -857,7 +847,7 @@ def create_or_update_target_group(connection, module): changed = True # Tags - only need to play with tags if tags parameter has been set to something - if tags: + if tags is not None: # Get tags current_tags = get_target_group_tags(connection, module, target_group['TargetGroupArn']) @@ -931,7 +921,7 @@ def main(): load_balancing_algorithm_type=dict(type='str', choices=['round_robin', 'least_outstanding_requests']), state=dict(required=True, choices=['present', 'absent']), successful_response_codes=dict(), - tags=dict(default={}, type='dict'), + tags=dict(type='dict', aliases=['resource_tags']), target_type=dict(choices=['instance', 'ip', 'lambda', 'alb']), targets=dict(type='list', elements='dict'), unhealthy_threshold_count=dict(type='int'),