Skip to content

Commit

Permalink
Big Black PR (ansible-collections#1784)
Browse files Browse the repository at this point in the history
* 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: ansible-collections/community.aws@2c4575c
  • Loading branch information
tremble authored and alinabuzachis committed Oct 23, 2024
1 parent ac45143 commit 6b84c40
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 133 deletions.
169 changes: 95 additions & 74 deletions plugins/module_utils/transitgateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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):
Expand All @@ -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 = []

Expand All @@ -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()
Expand All @@ -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])
Expand All @@ -140,55 +160,55 @@ 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):
if value is None:
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)
Expand All @@ -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):
Expand All @@ -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]

Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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

Expand All @@ -315,17 +337,16 @@ 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()

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)
Expand Down
Loading

0 comments on commit 6b84c40

Please sign in to comment.