From d91bd2f029045d85273130a69c8ad28da5ffde6c Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Wed, 26 Apr 2023 19:26:07 +0200 Subject: [PATCH] Big Black PR (#1784) * Black prep * Black * changelog * Fix pylint unused-import in tests * Split SSM connection plugin changes * disable glue tests - bucket's missing * Disable s3_logging and s3_sync tests This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/2c4575c248776c65d66b06cd60fa09b0dae1cd6f --- plugins/module_utils/transitgateway.py | 169 +++++++++-------- plugins/modules/ec2_vpc_vgw.py | 252 +++++++++++++------------ plugins/modules/ec2_vpc_vgw_info.py | 30 +-- 3 files changed, 240 insertions(+), 211 deletions(-) diff --git a/plugins/module_utils/transitgateway.py b/plugins/module_utils/transitgateway.py index fff2ce63ffe..5f0e934d1f2 100644 --- a/plugins/module_utils/transitgateway.py +++ b/plugins/module_utils/transitgateway.py @@ -21,21 +21,43 @@ def _waiter_model_data(self): # split the TGW waiters so we can keep them close to everything else. tgw_data = dict( tgw_attachment_available=dict( - operation='DescribeTransitGatewayAttachments', - delay=5, maxAttempts=120, + operation="DescribeTransitGatewayAttachments", + delay=5, + maxAttempts=120, acceptors=[ - dict(state='success', matcher='pathAll', expected='available', argument='TransitGatewayAttachments[].State'), - ] + dict( + state="success", + matcher="pathAll", + expected="available", + argument="TransitGatewayAttachments[].State", + ), + ], ), tgw_attachment_deleted=dict( - operation='DescribeTransitGatewayAttachments', - delay=5, maxAttempts=120, + operation="DescribeTransitGatewayAttachments", + delay=5, + maxAttempts=120, acceptors=[ - dict(state='retry', matcher='pathAll', expected='deleting', argument='TransitGatewayAttachments[].State'), - dict(state='success', matcher='pathAll', expected='deleted', argument='TransitGatewayAttachments[].State'), - dict(state='success', matcher='path', expected=True, argument='length(TransitGatewayAttachments[]) == `0`'), - dict(state='success', matcher='error', expected='InvalidRouteTableID.NotFound'), - ] + dict( + state="retry", + matcher="pathAll", + expected="deleting", + argument="TransitGatewayAttachments[].State", + ), + dict( + state="success", + matcher="pathAll", + expected="deleted", + argument="TransitGatewayAttachments[].State", + ), + dict( + state="success", + matcher="path", + expected=True, + argument="length(TransitGatewayAttachments[]) == `0`", + ), + dict(state="success", matcher="error", expected="InvalidRouteTableID.NotFound"), + ], ), ) data.update(tgw_data) @@ -51,40 +73,40 @@ def __init__(self, module, **kwargs): # retry - retries the full fetch, but better than simply giving up. @AWSRetry.jittered_backoff() def _paginated_describe_transit_gateway_vpc_attachments(self, **params): - paginator = self.client.get_paginator('describe_transit_gateway_vpc_attachments') + paginator = self.client.get_paginator("describe_transit_gateway_vpc_attachments") return paginator.paginate(**params).build_full_result() - @Boto3Mixin.aws_error_handler('describe transit gateway attachments') + @Boto3Mixin.aws_error_handler("describe transit gateway attachments") def _describe_vpc_attachments(self, **params): result = self._paginated_describe_transit_gateway_vpc_attachments(**params) - return result.get('TransitGatewayVpcAttachments', None) + return result.get("TransitGatewayVpcAttachments", None) - @Boto3Mixin.aws_error_handler('create transit gateway attachment') + @Boto3Mixin.aws_error_handler("create transit gateway attachment") def _create_vpc_attachment(self, **params): result = self.client.create_transit_gateway_vpc_attachment(aws_retry=True, **params) - return result.get('TransitGatewayVpcAttachment', None) + return result.get("TransitGatewayVpcAttachment", None) - @Boto3Mixin.aws_error_handler('modify transit gateway attachment') + @Boto3Mixin.aws_error_handler("modify transit gateway attachment") def _modify_vpc_attachment(self, **params): result = self.client.modify_transit_gateway_vpc_attachment(aws_retry=True, **params) - return result.get('TransitGatewayVpcAttachment', None) + return result.get("TransitGatewayVpcAttachment", None) - @Boto3Mixin.aws_error_handler('delete transit gateway attachment') + @Boto3Mixin.aws_error_handler("delete transit gateway attachment") def _delete_vpc_attachment(self, **params): try: result = self.client.delete_transit_gateway_vpc_attachment(aws_retry=True, **params) - except is_boto3_error_code('ResourceNotFoundException'): + except is_boto3_error_code("ResourceNotFoundException"): return None - return result.get('TransitGatewayVpcAttachment', None) + return result.get("TransitGatewayVpcAttachment", None) - @Boto3Mixin.aws_error_handler('transit gateway attachment to finish deleting') + @Boto3Mixin.aws_error_handler("transit gateway attachment to finish deleting") def _wait_tgw_attachment_deleted(self, **params): - waiter = self.tgw_waiter_factory.get_waiter('tgw_attachment_deleted') + waiter = self.tgw_waiter_factory.get_waiter("tgw_attachment_deleted") waiter.wait(**params) - @Boto3Mixin.aws_error_handler('transit gateway attachment to become available') + @Boto3Mixin.aws_error_handler("transit gateway attachment to become available") def _wait_tgw_attachment_available(self, **params): - waiter = self.tgw_waiter_factory.get_waiter('tgw_attachment_available') + waiter = self.tgw_waiter_factory.get_waiter("tgw_attachment_available") waiter.wait(**params) def _normalize_tgw_attachment(self, rtb): @@ -103,11 +125,10 @@ def _get_tgw_vpc_attachment(self, **params): class BaseTGWManager(BaseEc2Manager): - - @Boto3Mixin.aws_error_handler('connect to AWS') - def _create_client(self, client_name='ec2'): - if client_name == 'ec2': - error_codes = ['IncorrectState'] + @Boto3Mixin.aws_error_handler("connect to AWS") + def _create_client(self, client_name="ec2"): + if client_name == "ec2": + error_codes = ["IncorrectState"] else: error_codes = [] @@ -119,8 +140,7 @@ def _create_client(self, client_name='ec2'): class TransitGatewayVpcAttachmentManager(TGWAttachmentBoto3Mixin, BaseTGWManager): - - TAG_RESOURCE_TYPE = 'transit-gateway-attachment' + TAG_RESOURCE_TYPE = "transit-gateway-attachment" def __init__(self, module, id=None): self._subnet_updates = dict() @@ -131,7 +151,7 @@ def _get_id_params(self, id=None, id_list=False): id = self.resource_id if not id: # Users should never see this, but let's cover ourself - self.module.fail_json(msg='Attachment identifier parameter missing') + self.module.fail_json(msg="Attachment identifier parameter missing") if id_list: return dict(TransitGatewayAttachmentIds=[id]) @@ -140,18 +160,18 @@ def _get_id_params(self, id=None, id_list=False): def _extra_error_output(self): output = super(TransitGatewayVpcAttachmentManager, self)._extra_error_output() if self.resource_id: - output['TransitGatewayAttachmentId'] = self.resource_id + output["TransitGatewayAttachmentId"] = self.resource_id return output def _filter_immutable_resource_attributes(self, resource): resource = super(TransitGatewayVpcAttachmentManager, self)._filter_immutable_resource_attributes(resource) - resource.pop('TransitGatewayId', None) - resource.pop('VpcId', None) - resource.pop('VpcOwnerId', None) - resource.pop('State', None) - resource.pop('SubnetIds', None) - resource.pop('CreationTime', None) - resource.pop('Tags', None) + resource.pop("TransitGatewayId", None) + resource.pop("VpcId", None) + resource.pop("VpcOwnerId", None) + resource.pop("State", None) + resource.pop("SubnetIds", None) + resource.pop("CreationTime", None) + resource.pop("Tags", None) return resource def _set_option(self, name, value): @@ -159,36 +179,36 @@ def _set_option(self, name, value): return False # For now VPC Attachment options are all enable/disable if value: - value = 'enable' + value = "enable" else: - value = 'disable' + value = "disable" - options = deepcopy(self._preupdate_resource.get('Options', dict())) - options.update(self._resource_updates.get('Options', dict())) + options = deepcopy(self._preupdate_resource.get("Options", dict())) + options.update(self._resource_updates.get("Options", dict())) options[name] = value - return self._set_resource_value('Options', options) + return self._set_resource_value("Options", options) def set_dns_support(self, value): - return self._set_option('DnsSupport', value) + return self._set_option("DnsSupport", value) def set_ipv6_support(self, value): - return self._set_option('Ipv6Support', value) + return self._set_option("Ipv6Support", value) def set_appliance_mode_support(self, value): - return self._set_option('ApplianceModeSupport', value) + return self._set_option("ApplianceModeSupport", value) def set_transit_gateway(self, tgw_id): - return self._set_resource_value('TransitGatewayId', tgw_id) + return self._set_resource_value("TransitGatewayId", tgw_id) def set_vpc(self, vpc_id): - return self._set_resource_value('VpcId', vpc_id) + return self._set_resource_value("VpcId", vpc_id) def set_subnets(self, subnets=None, purge=True): if subnets is None: return False - current_subnets = set(self._preupdate_resource.get('SubnetIds', [])) + current_subnets = set(self._preupdate_resource.get("SubnetIds", [])) desired_subnets = set(subnets) if not purge: desired_subnets = desired_subnets.union(current_subnets) @@ -197,21 +217,23 @@ def set_subnets(self, subnets=None, purge=True): # information we 'know'. subnet_details = self._describe_subnets(SubnetIds=list(desired_subnets)) vpc_id = self.subnets_to_vpc(desired_subnets, subnet_details) - self._set_resource_value('VpcId', vpc_id, immutable=True) + self._set_resource_value("VpcId", vpc_id, immutable=True) # Only one subnet per-AZ is permitted - azs = [s.get('AvailabilityZoneId') for s in subnet_details] + azs = [s.get("AvailabilityZoneId") for s in subnet_details] if len(azs) != len(set(azs)): self.module.fail_json( - msg='Only one attachment subnet per availability zone may be set.', - availability_zones=azs, subnets=subnet_details) + msg="Only one attachment subnet per availability zone may be set.", + availability_zones=azs, + subnets=subnet_details, + ) subnets_to_add = list(desired_subnets.difference(current_subnets)) subnets_to_remove = list(current_subnets.difference(desired_subnets)) if not subnets_to_remove and not subnets_to_add: return False self._subnet_updates = dict(add=subnets_to_add, remove=subnets_to_remove) - self._set_resource_value('SubnetIds', list(desired_subnets)) + self._set_resource_value("SubnetIds", list(desired_subnets)) return True def subnets_to_vpc(self, subnets, subnet_details=None): @@ -221,11 +243,13 @@ def subnets_to_vpc(self, subnets, subnet_details=None): if subnet_details is None: subnet_details = self._describe_subnets(SubnetIds=list(subnets)) - vpcs = [s.get('VpcId') for s in subnet_details] + vpcs = [s.get("VpcId") for s in subnet_details] if len(set(vpcs)) > 1: self.module.fail_json( - msg='Attachment subnets may only be in one VPC, multiple VPCs found', - vpcs=list(set(vpcs)), subnets=subnet_details) + msg="Attachment subnets may only be in one VPC, multiple VPCs found", + vpcs=list(set(vpcs)), + subnets=subnet_details, + ) return vpcs[0] @@ -248,26 +272,25 @@ def _do_create_resource(self): params = self._merge_resource_changes(filter_immutable=False, creation=True) response = self._create_vpc_attachment(**params) if response: - self.resource_id = response.get('TransitGatewayAttachmentId', None) + self.resource_id = response.get("TransitGatewayAttachmentId", None) return response def _do_update_resource(self): - if self._preupdate_resource.get('State', None) == 'pending': + if self._preupdate_resource.get("State", None) == "pending": # Resources generally don't like it if you try to update before creation # is complete. If things are in a 'pending' state they'll often throw # exceptions. self._wait_for_creation() - elif self._preupdate_resource.get('State', None) == 'deleting': - self.module.fail_json(msg='Deletion in progress, unable to update', - route_tables=[self.original_resource]) + elif self._preupdate_resource.get("State", None) == "deleting": + self.module.fail_json(msg="Deletion in progress, unable to update", route_tables=[self.original_resource]) updates = self._filter_immutable_resource_attributes(self._resource_updates) - subnets_to_add = self._subnet_updates.get('add', []) - subnets_to_remove = self._subnet_updates.get('remove', []) + subnets_to_add = self._subnet_updates.get("add", []) + subnets_to_remove = self._subnet_updates.get("remove", []) if subnets_to_add: - updates['AddSubnetIds'] = subnets_to_add + updates["AddSubnetIds"] = subnets_to_add if subnets_to_remove: - updates['RemoveSubnetIds'] = subnets_to_remove + updates["RemoveSubnetIds"] = subnets_to_remove if not updates: return False @@ -283,7 +306,6 @@ def get_resource(self): return self.get_attachment() def delete(self, id=None): - if id: id_params = self._get_id_params(id=id, id_list=True) result = self._get_tgw_vpc_attachment(**id_params) @@ -295,7 +317,7 @@ def delete(self, id=None): if not result: return False - if result.get('State') == 'deleting': + if result.get("State") == "deleting": self._wait_for_deletion() return False @@ -315,9 +337,9 @@ def delete(self, id=None): def list(self, filters=None, id=None): params = dict() if id: - params['TransitGatewayAttachmentIds'] = [id] + params["TransitGatewayAttachmentIds"] = [id] if filters: - params['Filters'] = ansible_dict_to_boto3_filter_list(filters) + params["Filters"] = ansible_dict_to_boto3_filter_list(filters) attachments = self._describe_vpc_attachments(**params) if not attachments: return list() @@ -325,7 +347,6 @@ def list(self, filters=None, id=None): return [self._normalize_tgw_attachment(a) for a in attachments] def get_attachment(self, id=None): - # RouteTable needs a list, Association/Propagation needs a single ID id_params = self._get_id_params(id=id, id_list=True) id_param = self._get_id_params(id=id, id_list=False) diff --git a/plugins/modules/ec2_vpc_vgw.py b/plugins/modules/ec2_vpc_vgw.py index 74aab4a077c..e59fe25839c 100644 --- a/plugins/modules/ec2_vpc_vgw.py +++ b/plugins/modules/ec2_vpc_vgw.py @@ -155,11 +155,14 @@ class VGWRetry(AWSRetry): @staticmethod def status_code_from_exception(error): - return (error.response['Error']['Code'], error.response['Error']['Message'],) + return ( + error.response["Error"]["Code"], + error.response["Error"]["Message"], + ) @staticmethod def found(response_code, catch_extra_error_codes=None): - retry_on = ['The maximum number of mutating objects has been reached.'] + retry_on = ["The maximum number of mutating objects has been reached."] if catch_extra_error_codes: retry_on.extend(catch_extra_error_codes) @@ -179,37 +182,37 @@ def get_vgw_info(vgws): for vgw in vgws: vgw_info = { - 'id': vgw['VpnGatewayId'], - 'type': vgw['Type'], - 'state': vgw['State'], - 'vpc_id': None, - 'tags': dict() + "id": vgw["VpnGatewayId"], + "type": vgw["Type"], + "state": vgw["State"], + "vpc_id": None, + "tags": dict(), } - if vgw['Tags']: - vgw_info['tags'] = boto3_tag_list_to_ansible_dict(vgw['Tags']) + if vgw["Tags"]: + vgw_info["tags"] = boto3_tag_list_to_ansible_dict(vgw["Tags"]) - if len(vgw['VpcAttachments']) != 0 and vgw['VpcAttachments'][0]['State'] == 'attached': - vgw_info['vpc_id'] = vgw['VpcAttachments'][0]['VpcId'] + if len(vgw["VpcAttachments"]) != 0 and vgw["VpcAttachments"][0]["State"] == "attached": + vgw_info["vpc_id"] = vgw["VpcAttachments"][0]["VpcId"] return vgw_info def wait_for_status(client, module, vpn_gateway_id, status): polling_increment_secs = 15 - max_retries = (module.params.get('wait_timeout') // polling_increment_secs) + max_retries = module.params.get("wait_timeout") // polling_increment_secs status_achieved = False for x in range(0, max_retries): try: response = find_vgw(client, module, vpn_gateway_id) - if response[0]['VpcAttachments'][0]['State'] == status: + if response[0]["VpcAttachments"][0]["State"] == status: status_achieved = True break else: time.sleep(polling_increment_secs) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failure while waiting for status update') + module.fail_json_aws(e, msg="Failure while waiting for status update") result = response return status_achieved, result @@ -217,22 +220,21 @@ def wait_for_status(client, module, vpn_gateway_id, status): def attach_vgw(client, module, vpn_gateway_id): params = dict() - params['VpcId'] = module.params.get('vpc_id') + params["VpcId"] = module.params.get("vpc_id") try: # Immediately after a detachment, the EC2 API sometimes will report the VpnGateways[0].State # as available several seconds before actually permitting a new attachment. # So we catch and retry that error. See https://github.com/ansible/ansible/issues/53185 - response = VGWRetry.jittered_backoff(retries=5, - catch_extra_error_codes=['InvalidParameterValue'] - )(client.attach_vpn_gateway)(VpnGatewayId=vpn_gateway_id, - VpcId=params['VpcId']) + response = VGWRetry.jittered_backoff(retries=5, catch_extra_error_codes=["InvalidParameterValue"])( + client.attach_vpn_gateway + )(VpnGatewayId=vpn_gateway_id, VpcId=params["VpcId"]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to attach VPC') + module.fail_json_aws(e, msg="Failed to attach VPC") - status_achieved, vgw = wait_for_status(client, module, [vpn_gateway_id], 'attached') + status_achieved, vgw = wait_for_status(client, module, [vpn_gateway_id], "attached") if not status_achieved: - module.fail_json(msg='Error waiting for vpc to attach to vgw - please check the AWS console') + module.fail_json(msg="Error waiting for vpc to attach to vgw - please check the AWS console") result = response return result @@ -240,19 +242,19 @@ def attach_vgw(client, module, vpn_gateway_id): def detach_vgw(client, module, vpn_gateway_id, vpc_id=None): params = dict() - params['VpcId'] = module.params.get('vpc_id') + params["VpcId"] = module.params.get("vpc_id") try: if vpc_id: response = client.detach_vpn_gateway(VpnGatewayId=vpn_gateway_id, VpcId=vpc_id, aws_retry=True) else: - response = client.detach_vpn_gateway(VpnGatewayId=vpn_gateway_id, VpcId=params['VpcId'], aws_retry=True) + response = client.detach_vpn_gateway(VpnGatewayId=vpn_gateway_id, VpcId=params["VpcId"], aws_retry=True) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, 'Failed to detach gateway') + module.fail_json_aws(e, "Failed to detach gateway") - status_achieved, vgw = wait_for_status(client, module, [vpn_gateway_id], 'detached') + status_achieved, vgw = wait_for_status(client, module, [vpn_gateway_id], "detached") if not status_achieved: - module.fail_json(msg='Error waiting for vpc to detach from vgw - please check the AWS console') + module.fail_json(msg="Error waiting for vpc to detach from vgw - please check the AWS console") result = response return result @@ -260,37 +262,37 @@ def detach_vgw(client, module, vpn_gateway_id, vpc_id=None): def create_vgw(client, module): params = dict() - params['Type'] = module.params.get('type') - tags = module.params.get('tags') or {} - tags['Name'] = module.params.get('name') - params['TagSpecifications'] = boto3_tag_specifications(tags, ['vpn-gateway']) - if module.params.get('asn'): - params['AmazonSideAsn'] = module.params.get('asn') + params["Type"] = module.params.get("type") + tags = module.params.get("tags") or {} + tags["Name"] = module.params.get("name") + params["TagSpecifications"] = boto3_tag_specifications(tags, ["vpn-gateway"]) + if module.params.get("asn"): + params["AmazonSideAsn"] = module.params.get("asn") try: response = client.create_vpn_gateway(aws_retry=True, **params) - get_waiter( - client, 'vpn_gateway_exists' - ).wait( - VpnGatewayIds=[response['VpnGateway']['VpnGatewayId']] - ) + get_waiter(client, "vpn_gateway_exists").wait(VpnGatewayIds=[response["VpnGateway"]["VpnGatewayId"]]) except botocore.exceptions.WaiterError as e: - module.fail_json_aws(e, msg="Failed to wait for Vpn Gateway {0} to be available".format(response['VpnGateway']['VpnGatewayId'])) - except is_boto3_error_code('VpnGatewayLimitExceeded') as e: + module.fail_json_aws( + e, msg="Failed to wait for Vpn Gateway {0} to be available".format(response["VpnGateway"]["VpnGatewayId"]) + ) + except is_boto3_error_code("VpnGatewayLimitExceeded") as e: module.fail_json_aws(e, msg="Too many VPN gateways exist in this account.") - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except - module.fail_json_aws(e, msg='Failed to create gateway') + except ( + botocore.exceptions.ClientError, + botocore.exceptions.BotoCoreError, + ) as e: # pylint: disable=duplicate-except + module.fail_json_aws(e, msg="Failed to create gateway") result = response return result def delete_vgw(client, module, vpn_gateway_id): - try: response = client.delete_vpn_gateway(VpnGatewayId=vpn_gateway_id, aws_retry=True) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to delete gateway') + module.fail_json_aws(e, msg="Failed to delete gateway") # return the deleted VpnGatewayId as this is not included in the above response result = vpn_gateway_id @@ -299,13 +301,13 @@ def delete_vgw(client, module, vpn_gateway_id): def find_vpc(client, module): params = dict() - params['vpc_id'] = module.params.get('vpc_id') + params["vpc_id"] = module.params.get("vpc_id") - if params['vpc_id']: + if params["vpc_id"]: try: - response = client.describe_vpcs(VpcIds=[params['vpc_id']], aws_retry=True) + response = client.describe_vpcs(VpcIds=[params["vpc_id"]], aws_retry=True) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to describe VPC') + module.fail_json_aws(e, msg="Failed to describe VPC") result = response return result @@ -314,66 +316,68 @@ def find_vpc(client, module): def find_vgw(client, module, vpn_gateway_id=None): params = dict() if vpn_gateway_id: - params['VpnGatewayIds'] = vpn_gateway_id + params["VpnGatewayIds"] = vpn_gateway_id else: - params['Filters'] = [ - {'Name': 'type', 'Values': [module.params.get('type')]}, - {'Name': 'tag:Name', 'Values': [module.params.get('name')]}, + params["Filters"] = [ + {"Name": "type", "Values": [module.params.get("type")]}, + {"Name": "tag:Name", "Values": [module.params.get("name")]}, ] - if module.params.get('state') == 'present': - params['Filters'].append({'Name': 'state', 'Values': ['pending', 'available']}) + if module.params.get("state") == "present": + params["Filters"].append({"Name": "state", "Values": ["pending", "available"]}) try: response = client.describe_vpn_gateways(aws_retry=True, **params) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to describe gateway using filters') + module.fail_json_aws(e, msg="Failed to describe gateway using filters") - return sorted(response['VpnGateways'], key=lambda k: k['VpnGatewayId']) + return sorted(response["VpnGateways"], key=lambda k: k["VpnGatewayId"]) def ensure_vgw_present(client, module): - # If an existing vgw name and type matches our args, then a match is considered to have been # found and we will not create another vgw. changed = False params = dict() result = dict() - params['Name'] = module.params.get('name') - params['VpcId'] = module.params.get('vpc_id') - params['Type'] = module.params.get('type') - params['Tags'] = module.params.get('tags') - params['VpnGatewayIds'] = module.params.get('vpn_gateway_id') + params["Name"] = module.params.get("name") + params["VpcId"] = module.params.get("vpc_id") + params["Type"] = module.params.get("type") + params["Tags"] = module.params.get("tags") + params["VpnGatewayIds"] = module.params.get("vpn_gateway_id") # check that the vpc_id exists. If not, an exception is thrown - if params['VpcId']: + if params["VpcId"]: vpc = find_vpc(client, module) # check if a gateway matching our module args already exists existing_vgw = find_vgw(client, module) if existing_vgw != []: - vpn_gateway_id = existing_vgw[0]['VpnGatewayId'] - desired_tags = module.params.get('tags') - purge_tags = module.params.get('purge_tags') + vpn_gateway_id = existing_vgw[0]["VpnGatewayId"] + desired_tags = module.params.get("tags") + purge_tags = module.params.get("purge_tags") if desired_tags is None: desired_tags = dict() purge_tags = False - tags = dict(Name=module.params.get('name')) + tags = dict(Name=module.params.get("name")) tags.update(desired_tags) - changed = ensure_ec2_tags(client, module, vpn_gateway_id, resource_type='vpn-gateway', - tags=tags, purge_tags=purge_tags) + changed = ensure_ec2_tags( + client, module, vpn_gateway_id, resource_type="vpn-gateway", tags=tags, purge_tags=purge_tags + ) # if a vpc_id was provided, check if it exists and if it's attached - if params['VpcId']: - - current_vpc_attachments = existing_vgw[0]['VpcAttachments'] - - if current_vpc_attachments != [] and current_vpc_attachments[0]['State'] == 'attached': - if current_vpc_attachments[0]['VpcId'] != params['VpcId'] or current_vpc_attachments[0]['State'] != 'attached': + if params["VpcId"]: + current_vpc_attachments = existing_vgw[0]["VpcAttachments"] + + if current_vpc_attachments != [] and current_vpc_attachments[0]["State"] == "attached": + if ( + current_vpc_attachments[0]["VpcId"] != params["VpcId"] + or current_vpc_attachments[0]["State"] != "attached" + ): # detach the existing vpc from the virtual gateway - vpc_to_detach = current_vpc_attachments[0]['VpcId'] + vpc_to_detach = current_vpc_attachments[0]["VpcId"] detach_vgw(client, module, vpn_gateway_id, vpc_to_detach) - get_waiter(client, 'vpn_gateway_detached').wait(VpnGatewayIds=[vpn_gateway_id]) + get_waiter(client, "vpn_gateway_detached").wait(VpnGatewayIds=[vpn_gateway_id]) attached_vgw = attach_vgw(client, module, vpn_gateway_id) changed = True else: @@ -385,10 +389,10 @@ def ensure_vgw_present(client, module): else: existing_vgw = find_vgw(client, module, [vpn_gateway_id]) - if existing_vgw[0]['VpcAttachments'] != []: - if existing_vgw[0]['VpcAttachments'][0]['State'] == 'attached': + if existing_vgw[0]["VpcAttachments"] != []: + if existing_vgw[0]["VpcAttachments"][0]["State"] == "attached": # detach the vpc from the vgw - vpc_to_detach = existing_vgw[0]['VpcAttachments'][0]['VpcId'] + vpc_to_detach = existing_vgw[0]["VpcAttachments"][0]["VpcId"] detach_vgw(client, module, vpn_gateway_id, vpc_to_detach) changed = True @@ -396,10 +400,10 @@ def ensure_vgw_present(client, module): # create a new vgw new_vgw = create_vgw(client, module) changed = True - vpn_gateway_id = new_vgw['VpnGateway']['VpnGatewayId'] + vpn_gateway_id = new_vgw["VpnGateway"]["VpnGatewayId"] # if a vpc-id was supplied, attempt to attach it to the vgw - if params['VpcId']: + if params["VpcId"]: attached_vgw = attach_vgw(client, module, vpn_gateway_id) changed = True @@ -410,45 +414,46 @@ def ensure_vgw_present(client, module): def ensure_vgw_absent(client, module): - # If an existing vgw name and type matches our args, then a match is considered to have been # found and we will take steps to delete it. changed = False params = dict() result = dict() - params['Name'] = module.params.get('name') - params['VpcId'] = module.params.get('vpc_id') - params['Type'] = module.params.get('type') - params['Tags'] = module.params.get('tags') - params['VpnGatewayIds'] = module.params.get('vpn_gateway_id') + params["Name"] = module.params.get("name") + params["VpcId"] = module.params.get("vpc_id") + params["Type"] = module.params.get("type") + params["Tags"] = module.params.get("tags") + params["VpnGatewayIds"] = module.params.get("vpn_gateway_id") # check if a gateway matching our module args already exists - if params['VpnGatewayIds']: - existing_vgw_with_id = find_vgw(client, module, [params['VpnGatewayIds']]) - if existing_vgw_with_id != [] and existing_vgw_with_id[0]['State'] != 'deleted': + if params["VpnGatewayIds"]: + existing_vgw_with_id = find_vgw(client, module, [params["VpnGatewayIds"]]) + if existing_vgw_with_id != [] and existing_vgw_with_id[0]["State"] != "deleted": existing_vgw = existing_vgw_with_id - if existing_vgw[0]['VpcAttachments'] != [] and existing_vgw[0]['VpcAttachments'][0]['State'] == 'attached': - if params['VpcId']: - if params['VpcId'] != existing_vgw[0]['VpcAttachments'][0]['VpcId']: - module.fail_json(msg='The vpc-id provided does not match the vpc-id currently attached - please check the AWS console') + if existing_vgw[0]["VpcAttachments"] != [] and existing_vgw[0]["VpcAttachments"][0]["State"] == "attached": + if params["VpcId"]: + if params["VpcId"] != existing_vgw[0]["VpcAttachments"][0]["VpcId"]: + module.fail_json( + msg="The vpc-id provided does not match the vpc-id currently attached - please check the AWS console" + ) else: # detach the vpc from the vgw - detach_vgw(client, module, params['VpnGatewayIds'], params['VpcId']) - deleted_vgw = delete_vgw(client, module, params['VpnGatewayIds']) + detach_vgw(client, module, params["VpnGatewayIds"], params["VpcId"]) + deleted_vgw = delete_vgw(client, module, params["VpnGatewayIds"]) changed = True else: # attempt to detach any attached vpcs - vpc_to_detach = existing_vgw[0]['VpcAttachments'][0]['VpcId'] - detach_vgw(client, module, params['VpnGatewayIds'], vpc_to_detach) - deleted_vgw = delete_vgw(client, module, params['VpnGatewayIds']) + vpc_to_detach = existing_vgw[0]["VpcAttachments"][0]["VpcId"] + detach_vgw(client, module, params["VpnGatewayIds"], vpc_to_detach) + deleted_vgw = delete_vgw(client, module, params["VpnGatewayIds"]) changed = True else: # no vpc's are attached so attempt to delete the vgw - deleted_vgw = delete_vgw(client, module, params['VpnGatewayIds']) + deleted_vgw = delete_vgw(client, module, params["VpnGatewayIds"]) changed = True else: @@ -457,20 +462,22 @@ def ensure_vgw_absent(client, module): else: # Check that a name and type argument has been supplied if no vgw-id - if not module.params.get('name') or not module.params.get('type'): - module.fail_json(msg='A name and type is required when no vgw-id and a status of \'absent\' is supplied') + if not module.params.get("name") or not module.params.get("type"): + module.fail_json(msg="A name and type is required when no vgw-id and a status of 'absent' is supplied") existing_vgw = find_vgw(client, module) - if existing_vgw != [] and existing_vgw[0]['State'] != 'deleted': - vpn_gateway_id = existing_vgw[0]['VpnGatewayId'] - if existing_vgw[0]['VpcAttachments'] != [] and existing_vgw[0]['VpcAttachments'][0]['State'] == 'attached': - if params['VpcId']: - if params['VpcId'] != existing_vgw[0]['VpcAttachments'][0]['VpcId']: - module.fail_json(msg='The vpc-id provided does not match the vpc-id currently attached - please check the AWS console') + if existing_vgw != [] and existing_vgw[0]["State"] != "deleted": + vpn_gateway_id = existing_vgw[0]["VpnGatewayId"] + if existing_vgw[0]["VpcAttachments"] != [] and existing_vgw[0]["VpcAttachments"][0]["State"] == "attached": + if params["VpcId"]: + if params["VpcId"] != existing_vgw[0]["VpcAttachments"][0]["VpcId"]: + module.fail_json( + msg="The vpc-id provided does not match the vpc-id currently attached - please check the AWS console" + ) else: # detach the vpc from the vgw - detach_vgw(client, module, vpn_gateway_id, params['VpcId']) + detach_vgw(client, module, vpn_gateway_id, params["VpcId"]) # now that the vpc has been detached, delete the vgw deleted_vgw = delete_vgw(client, module, vpn_gateway_id) @@ -478,7 +485,7 @@ def ensure_vgw_absent(client, module): else: # attempt to detach any attached vpcs - vpc_to_detach = existing_vgw[0]['VpcAttachments'][0]['VpcId'] + vpc_to_detach = existing_vgw[0]["VpcAttachments"][0]["VpcId"] detach_vgw(client, module, vpn_gateway_id, vpc_to_detach) changed = True @@ -500,29 +507,28 @@ def ensure_vgw_absent(client, module): def main(): argument_spec = dict( - state=dict(default='present', choices=['present', 'absent']), + state=dict(default="present", choices=["present", "absent"]), name=dict(), vpn_gateway_id=dict(), vpc_id=dict(), - asn=dict(type='int'), - wait_timeout=dict(type='int', default=320), - type=dict(default='ipsec.1', choices=['ipsec.1']), - tags=dict(default=None, required=False, type='dict', aliases=['resource_tags']), - purge_tags=dict(default=True, type='bool'), + asn=dict(type="int"), + wait_timeout=dict(type="int", default=320), + type=dict(default="ipsec.1", choices=["ipsec.1"]), + tags=dict(default=None, required=False, type="dict", aliases=["resource_tags"]), + purge_tags=dict(default=True, type="bool"), ) - module = AnsibleAWSModule(argument_spec=argument_spec, - required_if=[['state', 'present', ['name']]]) + module = AnsibleAWSModule(argument_spec=argument_spec, required_if=[["state", "present", ["name"]]]) - state = module.params.get('state').lower() + state = module.params.get("state").lower() - client = module.client('ec2', retry_decorator=VGWRetry.jittered_backoff(retries=10)) + client = module.client("ec2", retry_decorator=VGWRetry.jittered_backoff(retries=10)) - if state == 'present': + if state == "present": (changed, results) = ensure_vgw_present(client, module) else: (changed, results) = ensure_vgw_absent(client, module) module.exit_json(changed=changed, vgw=results) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/plugins/modules/ec2_vpc_vgw_info.py b/plugins/modules/ec2_vpc_vgw_info.py index c729b2fa5b8..d8bfcc78ecb 100644 --- a/plugins/modules/ec2_vpc_vgw_info.py +++ b/plugins/modules/ec2_vpc_vgw_info.py @@ -135,13 +135,13 @@ def get_virtual_gateway_info(virtual_gateway): - tags = virtual_gateway.get('Tags', []) + tags = virtual_gateway.get("Tags", []) resource_tags = boto3_tag_list_to_ansible_dict(tags) virtual_gateway_info = dict( - VpnGatewayId=virtual_gateway['VpnGatewayId'], - State=virtual_gateway['State'], - Type=virtual_gateway['Type'], - VpcAttachments=virtual_gateway['VpcAttachments'], + VpnGatewayId=virtual_gateway["VpnGatewayId"], + State=virtual_gateway["State"], + Type=virtual_gateway["Type"], + VpcAttachments=virtual_gateway["VpcAttachments"], Tags=tags, ResourceTags=resource_tags, ) @@ -151,32 +151,34 @@ def get_virtual_gateway_info(virtual_gateway): def list_virtual_gateways(client, module): params = dict() - params['Filters'] = ansible_dict_to_boto3_filter_list(module.params.get('filters')) + params["Filters"] = ansible_dict_to_boto3_filter_list(module.params.get("filters")) if module.params.get("vpn_gateway_ids"): - params['VpnGatewayIds'] = module.params.get("vpn_gateway_ids") + params["VpnGatewayIds"] = module.params.get("vpn_gateway_ids") try: all_virtual_gateways = client.describe_vpn_gateways(**params) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to list gateways") - return [camel_dict_to_snake_dict(get_virtual_gateway_info(vgw), ignore_list=['ResourceTags']) - for vgw in all_virtual_gateways['VpnGateways']] + return [ + camel_dict_to_snake_dict(get_virtual_gateway_info(vgw), ignore_list=["ResourceTags"]) + for vgw in all_virtual_gateways["VpnGateways"] + ] def main(): argument_spec = dict( - filters=dict(type='dict', default=dict()), - vpn_gateway_ids=dict(type='list', default=None, elements='str'), + filters=dict(type="dict", default=dict()), + vpn_gateway_ids=dict(type="list", default=None, elements="str"), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) try: - connection = module.client('ec2') + connection = module.client("ec2") except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to connect to AWS') + module.fail_json_aws(e, msg="Failed to connect to AWS") # call your function here results = list_virtual_gateways(connection, module) @@ -184,5 +186,5 @@ def main(): module.exit_json(virtual_gateways=results) -if __name__ == '__main__': +if __name__ == "__main__": main()