Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(module/vpc-cagw): Add Carrier Gateway modules #1353

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c19c9e8
feat(module/vpc-cagw): Add Carrier Gateway modules
mtulio Jul 12, 2022
73c816a
Update plugins/modules/ec2_vpc_cagw.py
mtulio Jul 13, 2022
2a2a0c3
Apply suggestions from code review
mtulio Jul 13, 2022
ebabe78
Update plugins/modules/ec2_vpc_cagw.py
mtulio Jul 13, 2022
3466927
feat(module/vpc-cagw): renaming modules to ec2_carrier_gateway*
mtulio Jul 14, 2022
aba622a
feat(module/ec2-cagw): add integration tests
mtulio Jul 14, 2022
89193c3
feat(module/ec2-cagw): setting vpc_id as required on the docs
mtulio Jul 19, 2022
4edb501
feat(module/ec2-cagw): remove convert_tags dep
mtulio Jul 19, 2022
f3d5d4f
feat(module/ec2-cagw): CI compliant
mtulio Jul 19, 2022
e3aa342
feat(module/ec2-cagw): revertig requires_one_of
mtulio Jul 19, 2022
2749ff3
feat(module/ec2-cagw): fix E127
mtulio Jul 19, 2022
eca4bc9
fix(module/ec2-cagw/tests): correct alias w/ prefix mod name
mtulio Jul 29, 2022
d309518
fix(module/ec2-cagw/tests): remove tests with second vpc
mtulio Jul 29, 2022
83541ec
fix(module/ec2-cagw/tests): add requires_one_of
mtulio Jul 29, 2022
b0b0dd1
fix(module/ec2-cagw/tests): improve the opt-in requirement err
mtulio Jul 29, 2022
67809fc
fix(module/ec2-cagw/tests): add check_mode=true
mtulio Oct 8, 2022
53a2eeb
fix(module/ec2-cagw/tests): filter args on doc spec
mtulio Dec 28, 2022
5eab234
Update plugins/modules/ec2_carrier_gateway.py
mtulio Mar 30, 2023
c437922
headers
tremble Mar 30, 2023
11afa8f
black
tremble Mar 30, 2023
fea9e9e
Update imports
tremble Mar 30, 2023
3616de5
fix cgw deletion in integration test
tremble Mar 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 261 additions & 0 deletions plugins/modules/ec2_carrier_gateway.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

DOCUMENTATION = r"""
---
module: ec2_carrier_gateway
version_added: 6.0.0
short_description: Manage an AWS VPC Carrier gateway
description:
- Manage an AWS VPC Carrier gateway.
author:
- "Marco Braga (@mtulio)"
options:
vpc_id:
description:
- The VPC ID for the VPC in which to manage the Carrier Gateway.
required: true
type: str
carrier_gateway_id:
description:
- The Carrier Gateway ID to manage the Carrier Gateway.
required: false
type: str
state:
description:
- Create or terminate the Carrier Gateway.
default: present
choices: [ 'present', 'absent' ]
type: str
extends_documentation_fragment:
- amazon.aws.common.modules
- amazon.aws.region.modules
- amazon.aws.tags
- amazon.aws.boto3
"""

EXAMPLES = r"""
# Note: These examples do not set authentication details, see the AWS Guide for details.

# Ensure that the VPC has an Carrier Gateway.
# The Carrier Gateway ID can be accessed via {{cagw.carrier_gateway_id}} for use in setting up Route tables etc.
- name: Create Carrier gateway
community.aws.ec2_carrier_gateway:
vpc_id: vpc-abcdefgh
state: present
register: cagw

- name: Create Carrier gateway with tags
community.aws.ec2_carrier_gateway:
vpc_id: vpc-abcdefgh
state: present
tags:
Tag1: tag1
Tag2: tag2
register: cagw

- name: Delete Carrier gateway
community.aws.ec2_carrier_gateway:
vpc_id: vpc-abcdefgh
carrier_gateway_id: "cagw-123"
state: absent
register: vpc_cagw_delete
"""

RETURN = r"""
changed:
description: If any changes have been made to the Carrier Gateway.
type: bool
returned: always
sample:
changed: false
carrier_gateway_id:
description: The unique identifier for the Carrier Gateway.
type: str
returned: I(state=present)
sample:
carrier_gateway_id: "cagw-XXXXXXXX"
tags:
description: The tags associated the Carrier Gateway.
type: dict
returned: I(state=present)
sample:
tags:
"Ansible": "Test"
vpc_id:
description: The VPC ID associated with the Carrier Gateway.
type: str
returned: I(state=present)
sample:
vpc_id: "vpc-XXXXXXXX"
"""

try:
import botocore
except ImportError:
pass # caught by AnsibleAWSModule

from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict

from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_message
from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ensure_ec2_tags
from ansible_collections.amazon.aws.plugins.module_utils.tagging import boto3_tag_list_to_ansible_dict
from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list

from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule


@AWSRetry.jittered_backoff(retries=10, delay=10)
def describe_cagws_with_backoff(connection, **params):
paginator = connection.get_paginator("describe_carrier_gateways")
return paginator.paginate(**params).build_full_result()["CarrierGateways"]


class AnsibleEc2Cagw:
def __init__(self, module, results):
self._module = module
self._results = results
self._connection = self._module.client("ec2", retry_decorator=AWSRetry.jittered_backoff())
self._check_mode = self._module.check_mode

def process(self):
vpc_id = self._module.params.get("vpc_id")
state = self._module.params.get("state", "present")
tags = self._module.params.get("tags")
purge_tags = self._module.params.get("purge_tags")

if state == "present":
self.ensure_cagw_present(vpc_id, tags, purge_tags)
elif state == "absent":
self.ensure_cagw_absent(vpc_id)

def get_matching_cagw(self, vpc_id, carrier_gateway_id=None):
"""
Returns the carrier gateway found.
Parameters:
vpc_id (str): VPC ID
carrier_gateway_id (str): Carrier Gateway ID, if specified
Returns:
cagw (dict): dict of cagw found, None if none found
"""
filters = ansible_dict_to_boto3_filter_list({"vpc-id": vpc_id})
try:
if not carrier_gateway_id:
cagws = describe_cagws_with_backoff(
self._connection,
Filters=filters,
)
else:
cagws = describe_cagws_with_backoff(
self._connection,
CarrierGatewayIds=[carrier_gateway_id],
)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self._module.fail_json_aws(e)

cagw = None
if len(cagws) > 1:
self._module.fail_json(
msg=f"EC2 returned more than one Carrier Gateway for VPC {vpc_id}, aborting"
)
elif cagws:
cagw = camel_dict_to_snake_dict(cagws[0])

return cagw

@staticmethod
def get_cagw_info(cagw, vpc_id):
return {
"carrier_gateway_id": cagw["carrier_gateway_id"],
"tags": boto3_tag_list_to_ansible_dict(cagw["tags"]),
"vpc_id": vpc_id,
}

def ensure_cagw_absent(self, vpc_id):
cagw = self.get_matching_cagw(vpc_id)
if cagw is None:
return self._results

if self._check_mode:
self._results["changed"] = True
return self._results

try:
self._results["changed"] = True
self._connection.delete_carrier_gateway(
aws_retry=True,
CarrierGatewayId=cagw["carrier_gateway_id"],
)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self._module.fail_json_aws(e, msg="Unable to delete Carrier Gateway")

return self._results

def ensure_cagw_present(self, vpc_id, tags, purge_tags):
cagw = self.get_matching_cagw(vpc_id)

if cagw is None:
if self._check_mode:
self._results["changed"] = True
self._results["carrier_gateway_id"] = None
return self._results

try:
response = self._connection.create_carrier_gateway(VpcId=vpc_id, aws_retry=True)
cagw = camel_dict_to_snake_dict(response["CarrierGateway"])
self._results["changed"] = True
except is_boto3_error_message("You must be opted into a wavelength zone to create a carrier gateway.") as e:
self._module.fail_json(msg="You must be opted into a wavelength zone to create a carrier gateway")
except botocore.exceptions.WaiterError as e:
self._module.fail_json_aws(e, msg="No Carrier Gateway exists.")
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self._module.fail_json_aws(e, msg="Unable to create Carrier Gateway")

# Modify tags
self._results["changed"] |= ensure_ec2_tags(
self._connection,
self._module,
cagw["carrier_gateway_id"],
resource_type="carrier-gateway",
tags=tags,
purge_tags=purge_tags,
retry_codes="InvalidCarrierGatewayID.NotFound",
)

# Update cagw
cagw = self.get_matching_cagw(vpc_id, carrier_gateway_id=cagw["carrier_gateway_id"])
cagw_info = self.get_cagw_info(cagw, vpc_id)
self._results.update(cagw_info)

return self._results


def main():
argument_spec = dict(
carrier_gateway_id=dict(required=False),
vpc_id=dict(required=True),
state=dict(default="present", choices=["present", "absent"]),
tags=dict(required=False, type="dict", aliases=["resource_tags"]),
purge_tags=dict(default=True, type="bool"),
)

module = AnsibleAWSModule(
argument_spec=argument_spec,
required_one_of=[["vpc_id", "carrier_gateway_id"]],
supports_check_mode=True,
)
results = dict(
changed=False,
)
cagw_manager = AnsibleEc2Cagw(module=module, results=results)
cagw_manager.process()

module.exit_json(**results)


if __name__ == "__main__":
main()
Loading