diff --git a/changelogs/fragments/add_support_tgw_vpc.yml b/changelogs/fragments/add_support_tgw_vpc.yml new file mode 100644 index 0000000000..ad448a26c1 --- /dev/null +++ b/changelogs/fragments/add_support_tgw_vpc.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - Add support for transit gateway vpc attachment module (https://github.com/ansible-collections/amazon.aws/pull/2314). diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index e488984649..c68c96f8f5 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1520,6 +1520,49 @@ def get_sg_id(sg): return sec_group_id_list +# EC2 Transit Gateway VPC Attachment Error handler +class EC2TransitGatewayVPCAttachmentErrorHandler(AWSErrorHandler): + _CUSTOM_EXCEPTION = AnsibleEC2Error + + @classmethod + def _is_missing(cls): + return is_boto3_error_code("InvalidGatewayID.NotFound") + + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway vpc attachments") +@AWSRetry.jittered_backoff() +def describe_transit_gateway_vpc_attachments( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> List: + paginator = client.get_paginator("describe_transit_gateway_vpc_attachments") + return paginator.paginate(**params).build_full_result()["TransitGatewayVpcAttachments"] + + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("create transit gateway vpc attachment") +@AWSRetry.jittered_backoff() +def create_transit_gateway_vpc_attachment( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Dict[str, Any]: + return client.create_transit_gateway_vpc_attachment(**params)["TransitGatewayVpcAttachment"] + + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("modify transit gateway vpc attachment") +@AWSRetry.jittered_backoff() +def modify_transit_gateway_vpc_attachment( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Dict[str, Any]: + return client.modify_transit_gateway_vpc_attachment(**params)["TransitGatewayVpcAttachment"] + + +@EC2TransitGatewayVPCAttachmentErrorHandler.deletion_error_handler("delete transit gateway vpc attachment") +@AWSRetry.jittered_backoff() +def delete_transit_gateway_vpc_attachment(client, transit_gateway_attachment_id: str) -> bool: + client.delete_transit_gateway_vpc_attachment(TransitGatewayAttachmentId=transit_gateway_attachment_id)[ + "TransitGatewayVpcAttachment" + ] + return True + + def add_ec2_tags(client, module, resource_id, tags_to_set, retry_codes=None): """ Sets Tags on an EC2 resource. diff --git a/plugins/module_utils/waiters.py b/plugins/module_utils/waiters.py index e3a3621dab..51213617f6 100644 --- a/plugins/module_utils/waiters.py +++ b/plugins/module_utils/waiters.py @@ -51,6 +51,52 @@ {"matcher": "error", "expected": "InvalidInternetGatewayID.NotFound", "state": "retry"}, ], }, + "TGWVpcAttachmentAvailable": { + "operation": "DescribeTransitGatewayVpcAttachments", + "delay": 5, + "maxAttempts": 120, + "acceptors": [ + { + "expected": "available", + "matcher": "pathAll", + "state": "success", + "argument": "TransitGatewayVpcAttachments[].State", + }, + { + "state": "retry", + "matcher": "pathAny", + "argument": "TransitGatewayVpcAttachments[].State", + "expected": "pending", + }, + {"matcher": "error", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, + ], + }, + "TGWVpcAttachmentDeleted": { + "operation": "DescribeTransitGatewayVpcAttachments", + "delay": 5, + "maxAttempts": 120, + "acceptors": [ + { + "state": "retry", + "matcher": "pathAll", + "argument": "TransitGatewayVpcAttachments[].State", + "expected": "deleting", + }, + { + "state": "success", + "expected": "deleted", + "matcher": "pathAll", + "argument": "TransitGatewayVpcAttachments[].State", + }, + { + "expected": True, + "matcher": "path", + "state": "success", + "argument": "length(TransitGatewayVpcAttachments[]) == `0`", + }, + {"matcher": "error", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, + ], + }, "NetworkInterfaceAttached": { "operation": "DescribeNetworkInterfaces", "delay": 5, @@ -774,6 +820,16 @@ def route53_model(name): ec2_model("InternetGatewayAttached"), core_waiter.NormalizedOperationMethod(ec2.describe_internet_gateways), ), + ("EC2", "transit_gateway_vpc_attachment_available"): lambda ec2: core_waiter.Waiter( + "transit_gateway_vpc_attachment_available", + ec2_model("TGWVpcAttachmentAvailable"), + core_waiter.NormalizedOperationMethod(ec2.describe_transit_gateway_vpc_attachments), + ), + ("EC2", "transit_gateway_vpc_attachment_deleted"): lambda ec2: core_waiter.Waiter( + "transit_gateway_vpc_attachment_deleted", + ec2_model("TGWVpcAttachmentDeleted"), + core_waiter.NormalizedOperationMethod(ec2.describe_transit_gateway_vpc_attachments), + ), ("EC2", "network_interface_attached"): lambda ec2: core_waiter.Waiter( "network_interface_attached", ec2_model("NetworkInterfaceAttached"),