From 2a3b7456924595e9d6d60cf83c74767e8c0dc165 Mon Sep 17 00:00:00 2001 From: GomathiselviS Date: Mon, 30 Sep 2024 14:41:44 -0400 Subject: [PATCH 1/7] Add support for tansit_gateway_vpc_attachments module --- plugins/module_utils/ec2.py | 50 +++++++++++++++++++++++++++++++++ plugins/module_utils/waiters.py | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index 1b26c2386fa..33d2ee95acb 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1416,6 +1416,56 @@ 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 attachments") +@AWSRetry.jittered_backoff() +def paginated_describe_transit_gateway_vpc_attachments( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Dict[str, Any]: + paginator = client.get_paginator("describe_transit_gateway_vpc_attachments") + return paginator.paginate(**params).build_full_result() + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") +@AWSRetry.jittered_backoff() +def describe_vpc_attachments(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[List[Dict[str, Any]]]: + result = client._paginated_describe_transit_gateway_vpc_attachments(**params) + return result.get("TransitGatewayVpcAttachments", None) + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("create transit gateway vpc attachment") +@AWSRetry.jittered_backoff() +def create_vpc_attachment(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[Dict[str, Any]]: + result = client.create_transit_gateway_vpc_attachment(**params) + return result.get("TransitGatewayVpcAttachment", None) + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("modify transit gateway vpc attachment") +@AWSRetry.jittered_backoff() +def modify_vpc_attachment(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[Dict[str, Any]]: + result = client.modify_transit_gateway_vpc_attachment(**params) + return result.get("TransitGatewayVpcAttachment", None) + +@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("delete transit gateway vpc attachment") +@AWSRetry.jittered_backoff() +def delete_vpc_attachment(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[Dict[str, Any]]: + result = self.client.delete_transit_gateway_vpc_attachment(**params) + return result.get("TransitGatewayVpcAttachment", None) + +def get_tgw_vpc_attachment(client, **params: Any) -> Optional[Dict[str, Any]]: + # Only for use with a single attachment, use describe_vpc_attachments for + # multiple tables. + attachments = client.describe_vpc_attachments(**params) + if not attachments: + return None + + attachment = attachments[0] + return attachment + 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 e3a3621dab6..de6a4d95a46 100644 --- a/plugins/module_utils/waiters.py +++ b/plugins/module_utils/waiters.py @@ -51,6 +51,46 @@ {"matcher": "error", "expected": "InvalidInternetGatewayID.NotFound", "state": "retry"}, ], }, + "TGWVpcAttachmentAvailable": { + "operation": "DescribeTransitGatewayAttachments", + "delay": 5, + "maxAttempts": 120, + "acceptors": [ + { + "expected": "available", + "matcher": "pathAll", + "state": "available", + "argument": "TransitGatewayAttachments[].State", + }, + {"matcher": "error", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, + ], + }, + "TGWVpcAttachmentDeleted": { + "operation": "DescribeTransitGatewayAttachments", + "delay": 5, + "maxAttempts": 120, + "acceptors": [ + { + "expected": "retry", + "matcher": "pathAll", + "state": "deleting", + "argument": "TransitGatewayAttachments[].State", + }, + { + "expected": "success", + "matcher": "pathAll", + "state": "deleted", + "argument": "TransitGatewayAttachments[].State", + }, + { + "expected": "success", + "matcher": "pathAll", + "state": True, + "argument": ""length(TransitGatewayAttachments[]) == `0`", + }, + {"matcher": "success", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, + ], + }, "NetworkInterfaceAttached": { "operation": "DescribeNetworkInterfaces", "delay": 5, @@ -774,6 +814,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_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_vpc_attachments), + ), ("EC2", "network_interface_attached"): lambda ec2: core_waiter.Waiter( "network_interface_attached", ec2_model("NetworkInterfaceAttached"), From d9479122084c1ebfba8a406cebf50614f753e16d Mon Sep 17 00:00:00 2001 From: GomathiselviS Date: Mon, 30 Sep 2024 14:44:49 -0400 Subject: [PATCH 2/7] Add changelog --- changelogs/fragments/add_support_tgw_vpc.yml | 3 ++ plugins/module_utils/ec2.py | 31 +++++++++++++++----- plugins/module_utils/waiters.py | 2 +- 3 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 changelogs/fragments/add_support_tgw_vpc.yml diff --git a/changelogs/fragments/add_support_tgw_vpc.yml b/changelogs/fragments/add_support_tgw_vpc.yml new file mode 100644 index 00000000000..de1c8fcffda --- /dev/null +++ b/changelogs/fragments/add_support_tgw_vpc.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - Add support for transit gateway vpc attachment module. diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index 33d2ee95acb..0c0818563fa 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1424,6 +1424,7 @@ class EC2TransitGatewayVPCAttachmentErrorHandler(AWSErrorHandler): def _is_missing(cls): return is_boto3_error_code("InvalidGatewayID.NotFound") + @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") @AWSRetry.jittered_backoff() def paginated_describe_transit_gateway_vpc_attachments( @@ -1432,29 +1433,42 @@ def paginated_describe_transit_gateway_vpc_attachments( paginator = client.get_paginator("describe_transit_gateway_vpc_attachments") return paginator.paginate(**params).build_full_result() + @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") @AWSRetry.jittered_backoff() -def describe_vpc_attachments(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[List[Dict[str, Any]]]: +def describe_vpc_attachments( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Optional[List[Dict[str, Any]]]: result = client._paginated_describe_transit_gateway_vpc_attachments(**params) return result.get("TransitGatewayVpcAttachments", None) + @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("create transit gateway vpc attachment") @AWSRetry.jittered_backoff() -def create_vpc_attachment(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[Dict[str, Any]]: +def create_vpc_attachment( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Optional[Dict[str, Any]]: result = client.create_transit_gateway_vpc_attachment(**params) return result.get("TransitGatewayVpcAttachment", None) + @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("modify transit gateway vpc attachment") @AWSRetry.jittered_backoff() -def modify_vpc_attachment(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[Dict[str, Any]]: - result = client.modify_transit_gateway_vpc_attachment(**params) - return result.get("TransitGatewayVpcAttachment", None) +def modify_vpc_attachment( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Optional[Dict[str, Any]]: + result = client.modify_transit_gateway_vpc_attachment(**params) + return result.get("TransitGatewayVpcAttachment", None) + @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("delete transit gateway vpc attachment") @AWSRetry.jittered_backoff() -def delete_vpc_attachment(client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]]) -> Optional[Dict[str, Any]]: - result = self.client.delete_transit_gateway_vpc_attachment(**params) - return result.get("TransitGatewayVpcAttachment", None) +def delete_vpc_attachment( + client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] +) -> Optional[Dict[str, Any]]: + result = client.delete_transit_gateway_vpc_attachment(**params) + return result.get("TransitGatewayVpcAttachment", None) + def get_tgw_vpc_attachment(client, **params: Any) -> Optional[Dict[str, Any]]: # Only for use with a single attachment, use describe_vpc_attachments for @@ -1466,6 +1480,7 @@ def get_tgw_vpc_attachment(client, **params: Any) -> Optional[Dict[str, Any]]: attachment = attachments[0] return attachment + 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 de6a4d95a46..15ba4d1af94 100644 --- a/plugins/module_utils/waiters.py +++ b/plugins/module_utils/waiters.py @@ -86,7 +86,7 @@ "expected": "success", "matcher": "pathAll", "state": True, - "argument": ""length(TransitGatewayAttachments[]) == `0`", + "argument": "length(TransitGatewayAttachments[]) == `0`", }, {"matcher": "success", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, ], From 27baafac2a2346784c345679b9197147b75f0941 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Tue, 1 Oct 2024 16:53:54 +0200 Subject: [PATCH 3/7] Fixes Signed-off-by: Alina Buzachis --- plugins/module_utils/ec2.py | 26 +++------------------ plugins/module_utils/waiters.py | 40 +++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 40 deletions(-) diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index 0c0818563fa..f48e1ca0e5c 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1425,22 +1425,13 @@ def _is_missing(cls): return is_boto3_error_code("InvalidGatewayID.NotFound") -@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") -@AWSRetry.jittered_backoff() -def paginated_describe_transit_gateway_vpc_attachments( - client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] -) -> Dict[str, Any]: - paginator = client.get_paginator("describe_transit_gateway_vpc_attachments") - return paginator.paginate(**params).build_full_result() - - @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") @AWSRetry.jittered_backoff() def describe_vpc_attachments( client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] -) -> Optional[List[Dict[str, Any]]]: - result = client._paginated_describe_transit_gateway_vpc_attachments(**params) - return result.get("TransitGatewayVpcAttachments", None) +) -> 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") @@ -1470,17 +1461,6 @@ def delete_vpc_attachment( return result.get("TransitGatewayVpcAttachment", None) -def get_tgw_vpc_attachment(client, **params: Any) -> Optional[Dict[str, Any]]: - # Only for use with a single attachment, use describe_vpc_attachments for - # multiple tables. - attachments = client.describe_vpc_attachments(**params) - if not attachments: - return None - - attachment = attachments[0] - return attachment - - 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 15ba4d1af94..51213617f67 100644 --- a/plugins/module_utils/waiters.py +++ b/plugins/module_utils/waiters.py @@ -52,43 +52,49 @@ ], }, "TGWVpcAttachmentAvailable": { - "operation": "DescribeTransitGatewayAttachments", + "operation": "DescribeTransitGatewayVpcAttachments", "delay": 5, "maxAttempts": 120, "acceptors": [ { "expected": "available", "matcher": "pathAll", - "state": "available", - "argument": "TransitGatewayAttachments[].State", + "state": "success", + "argument": "TransitGatewayVpcAttachments[].State", + }, + { + "state": "retry", + "matcher": "pathAny", + "argument": "TransitGatewayVpcAttachments[].State", + "expected": "pending", }, {"matcher": "error", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, ], }, "TGWVpcAttachmentDeleted": { - "operation": "DescribeTransitGatewayAttachments", + "operation": "DescribeTransitGatewayVpcAttachments", "delay": 5, "maxAttempts": 120, "acceptors": [ { - "expected": "retry", + "state": "retry", "matcher": "pathAll", - "state": "deleting", - "argument": "TransitGatewayAttachments[].State", + "argument": "TransitGatewayVpcAttachments[].State", + "expected": "deleting", }, { - "expected": "success", + "state": "success", + "expected": "deleted", "matcher": "pathAll", - "state": "deleted", - "argument": "TransitGatewayAttachments[].State", + "argument": "TransitGatewayVpcAttachments[].State", }, { - "expected": "success", - "matcher": "pathAll", - "state": True, - "argument": "length(TransitGatewayAttachments[]) == `0`", + "expected": True, + "matcher": "path", + "state": "success", + "argument": "length(TransitGatewayVpcAttachments[]) == `0`", }, - {"matcher": "success", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, + {"matcher": "error", "expected": "InvalidRouteTableID.NotFound", "state": "retry"}, ], }, "NetworkInterfaceAttached": { @@ -817,12 +823,12 @@ def route53_model(name): ("EC2", "transit_gateway_vpc_attachment_available"): lambda ec2: core_waiter.Waiter( "transit_gateway_vpc_attachment_available", ec2_model("TGWVpcAttachmentAvailable"), - core_waiter.NormalizedOperationMethod(ec2.describe_vpc_attachments), + 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_vpc_attachments), + core_waiter.NormalizedOperationMethod(ec2.describe_transit_gateway_vpc_attachments), ), ("EC2", "network_interface_attached"): lambda ec2: core_waiter.Waiter( "network_interface_attached", From 88a97a589db09b966bf8165133efdc0e1039c6b8 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 4 Oct 2024 15:22:18 +0200 Subject: [PATCH 4/7] Update ec2.py --- plugins/module_utils/ec2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index f48e1ca0e5c..58d37a3f0df 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1452,7 +1452,7 @@ def modify_vpc_attachment( return result.get("TransitGatewayVpcAttachment", None) -@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("delete transit gateway vpc attachment") +@EC2TransitGatewayVPCAttachmentErrorHandler.deletion_error_handler("delete transit gateway vpc attachment") @AWSRetry.jittered_backoff() def delete_vpc_attachment( client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] From 6d631cde33d7df612e75b7f143664edc5b2c7c97 Mon Sep 17 00:00:00 2001 From: GomathiselviS Date: Mon, 7 Oct 2024 11:02:18 -0400 Subject: [PATCH 5/7] Update add_support_tgw_vpc.yml --- changelogs/fragments/add_support_tgw_vpc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/add_support_tgw_vpc.yml b/changelogs/fragments/add_support_tgw_vpc.yml index de1c8fcffda..ad448a26c13 100644 --- a/changelogs/fragments/add_support_tgw_vpc.yml +++ b/changelogs/fragments/add_support_tgw_vpc.yml @@ -1,3 +1,3 @@ --- minor_changes: - - Add support for transit gateway vpc attachment module. + - Add support for transit gateway vpc attachment module (https://github.com/ansible-collections/amazon.aws/pull/2314). From cb5b56ef51ff338566a0558fdcc95410877ff51b Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 14 Oct 2024 14:17:18 +0200 Subject: [PATCH 6/7] Modify upon review Signed-off-by: Alina Buzachis --- plugins/module_utils/ec2.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index 58d37a3f0df..90d9e1f0c89 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1427,7 +1427,7 @@ def _is_missing(cls): @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") @AWSRetry.jittered_backoff() -def describe_vpc_attachments( +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") @@ -1436,29 +1436,27 @@ def describe_vpc_attachments( @EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("create transit gateway vpc attachment") @AWSRetry.jittered_backoff() -def create_vpc_attachment( +def create_transit_gateway_vpc_attachment( client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] -) -> Optional[Dict[str, Any]]: - result = client.create_transit_gateway_vpc_attachment(**params) - return result.get("TransitGatewayVpcAttachment", None) +) -> 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_vpc_attachment( +def modify_transit_gateway_vpc_attachment( client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] -) -> Optional[Dict[str, Any]]: - result = client.modify_transit_gateway_vpc_attachment(**params) - return result.get("TransitGatewayVpcAttachment", None) +) -> 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_vpc_attachment( - client, **params: Dict[str, Union[List[str], bool, List[Dict[str, Union[str, List[str]]]]]] -) -> Optional[Dict[str, Any]]: - result = client.delete_transit_gateway_vpc_attachment(**params) - return result.get("TransitGatewayVpcAttachment", None) +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): From 18531d0adc8c1357817012a49594f3cb04fa08bd Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 14 Oct 2024 17:01:34 +0200 Subject: [PATCH 7/7] Update ec2.py --- plugins/module_utils/ec2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/ec2.py b/plugins/module_utils/ec2.py index 90d9e1f0c89..80781d2668e 100644 --- a/plugins/module_utils/ec2.py +++ b/plugins/module_utils/ec2.py @@ -1425,7 +1425,7 @@ def _is_missing(cls): return is_boto3_error_code("InvalidGatewayID.NotFound") -@EC2TransitGatewayVPCAttachmentErrorHandler.common_error_handler("describe transit gateway attachments") +@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]]]]]]