Skip to content

Commit

Permalink
Add ability to remove detached internet gateway
Browse files Browse the repository at this point in the history
Fixes #1669
  • Loading branch information
branic committed Oct 3, 2023
1 parent e515e05 commit 412b2e5
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- Add ability to delete a vpc internet gateway using the id of the gateway
58 changes: 44 additions & 14 deletions plugins/modules/ec2_vpc_igw.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@
- Manage an AWS VPC Internet gateway
author: Robert Estelle (@erydo)
options:
internet_gateway_id:
description:
- The ID of Internet Gateway to manage.
required: false
type: str
vpc_id:
description:
- The VPC ID for the VPC in which to manage the Internet Gateway.
required: true
- The VPC ID for the VPC to attach (when state=present) or that is attached the Internet Gateway to manage.
required: false
type: str
state:
description:
Expand All @@ -25,6 +30,7 @@
choices: [ 'present', 'absent' ]
type: str
notes:
- I(internet_gateway_id) or I(vpc_id) must be supplied. Both can be supplied if managing an existing gateway.
- Support for I(purge_tags) was added in release 1.3.0.
extends_documentation_fragment:
- amazon.aws.common.modules
Expand Down Expand Up @@ -58,6 +64,20 @@
state: absent
vpc_id: vpc-abcdefgh
register: vpc_igw_delete
- name: Delete Internet gateway with gateway id
amazon.aws.ec2_vpc_igw:
state: absent
internet_gateway_id: igw-abcdefgh
register: vpc_igw_delete
- name: Delete Internet gateway ensuring attached VPC is correct
amazon.aws.ec2_vpc_igw:
state: absent
internet_gateway_id: igw-abcdefgh
vpc_id: vpc-abcdefgh
register: vpc_igw_delete
"""

RETURN = r"""
Expand Down Expand Up @@ -117,6 +137,7 @@ def __init__(self, module, results):
self._check_mode = self._module.check_mode

def process(self):
internet_gateway_id = self._module.params.get("internet_gateway_id")
vpc_id = self._module.params.get("vpc_id")
state = self._module.params.get("state", "present")
tags = self._module.params.get("tags")
Expand All @@ -125,7 +146,7 @@ def process(self):
if state == "present":
self.ensure_igw_present(vpc_id, tags, purge_tags)
elif state == "absent":
self.ensure_igw_absent(vpc_id)
self.ensure_igw_absent(vpc_id, internet_gateway_id)

def get_matching_igw(self, vpc_id, gateway_id=None):
"""
Expand All @@ -136,11 +157,11 @@ def get_matching_igw(self, vpc_id, gateway_id=None):
Returns:
igw (dict): dict of igw found, None if none found
"""
filters = ansible_dict_to_boto3_filter_list({"attachment.vpc-id": vpc_id})
try:
# If we know the gateway_id, use it to avoid bugs with using filters
# See https://github.com/ansible-collections/amazon.aws/pull/766
if not gateway_id:
filters = ansible_dict_to_boto3_filter_list({"attachment.vpc-id": vpc_id})
igws = describe_igws_with_backoff(self._connection, Filters=filters)
else:
igws = describe_igws_with_backoff(self._connection, InternetGatewayIds=[gateway_id])
Expand All @@ -163,20 +184,29 @@ def get_igw_info(igw, vpc_id):
"vpc_id": vpc_id,
}

def ensure_igw_absent(self, vpc_id):
igw = self.get_matching_igw(vpc_id)
def ensure_igw_absent(self, vpc_id, igw_id):
igw = self.get_matching_igw(vpc_id, gateway_id=igw_id)
if igw is None:
return self._results

igw_vpc_id = ""

if len(igw["attachments"]) > 0:
igw_vpc_id = igw["attachments"][0]["vpc_id"]

if vpc_id and (igw_vpc_id != vpc_id):
self._module.fail_json(msg=f"Supplied VPC ({vpc_id}) does not match found VPC ({igw_vpc_id}), aborting")

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

try:
self._results["changed"] = True
self._connection.detach_internet_gateway(
aws_retry=True, InternetGatewayId=igw["internet_gateway_id"], VpcId=vpc_id
)
if igw_vpc_id:
self._connection.detach_internet_gateway(
aws_retry=True, InternetGatewayId=igw["internet_gateway_id"], VpcId=igw_vpc_id
)
self._connection.delete_internet_gateway(aws_retry=True, InternetGatewayId=igw["internet_gateway_id"])
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self._module.fail_json_aws(e, msg="Unable to delete Internet Gateway")
Expand Down Expand Up @@ -234,16 +264,16 @@ def ensure_igw_present(self, vpc_id, tags, purge_tags):

def main():
argument_spec = dict(
vpc_id=dict(required=True),
internet_gateway_id=dict(),
vpc_id=dict(),
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,
supports_check_mode=True,
)
required_one_of = [("internet_gateway_id", "vpc_id")]

module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, required_one_of=required_one_of)
results = dict(changed=False)
igw_manager = AnsibleEc2Igw(module=module, results=results)
igw_manager.process()
Expand Down
122 changes: 122 additions & 0 deletions tests/integration/targets/ec2_vpc_igw/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,128 @@
that:
- vpc_igw_delete is not changed

# ============================================================
- name: Create new internet gateway for removal by igw id tests
ec2_vpc_igw:
state: present
vpc_id: '{{ vpc_result.vpc.id }}'
register: new_internet_gateway_result

- name: Test state=absent when supplying only a gateway id (expected chaged=true) - CHECK_MODE
ec2_vpc_igw:
state: absent
internet_gateway_id: '{{ new_internet_gateway_result.gateway_id}}'
register: vpc_igw_delete
check_mode: true

- name: Assert state=absent when supplying only a gateway id (expected chaged=true) - CHECK_MODE
assert:
that:
- vpc_igw_delete is changed

- name: Test state=absent when supplying only a gateway id (expected chaged=true)
ec2_vpc_igw:
state: absent
internet_gateway_id: '{{ new_internet_gateway_result.gateway_id}}'
register: vpc_igw_delete

- name: Assert state=absent when supplying only a gateway id (expected chaged=true)
assert:
that:
- vpc_igw_delete is changed

- name: Fetch removed IGW by ID
ec2_vpc_igw_info:
internet_gateway_ids: '{{ igw_id }}'
register: igw_info
ignore_errors: true

- name: Check IGW does not exist
assert:
that:
# Deliberate choice not to change bevahiour when searching by ID
- igw_info is failed

# ============================================================
- name: Create new internet gateway for removal by igw id and vpc id tests
ec2_vpc_igw:
state: present
vpc_id: '{{ vpc_result.vpc.id }}'
register: new_internet_gateway_result

- name: Test state=absent when supplying a gateway id and vpc id (expected chaged=true) - CHECK_MODE
ec2_vpc_igw:
state: absent
internet_gateway_id: '{{ new_internet_gateway_result.gateway_id}}'
vpc_id: '{{ vpc_result.vpc.id }}'
register: vpc_igw_delete
check_mode: true

- name: Assert state=absent when supplying a gateway id and vpc id (expected chaged=true) - CHECK_MODE
assert:
that:
- vpc_igw_delete is changed

- name: Test state=absent when supplying a gateway id and vpc id (expected chaged=true)
ec2_vpc_igw:
state: absent
internet_gateway_id: '{{ new_internet_gateway_result.gateway_id}}'
vpc_id: '{{ vpc_result.vpc.id }}'
register: vpc_igw_delete

- name: Assert state=absent when supplying a gateway id and vpc id (expected chaged=true)
assert:
that:
- vpc_igw_delete is changed

- name: Fetch removed IGW by ID
ec2_vpc_igw_info:
internet_gateway_ids: '{{ igw_id }}'
register: igw_info
ignore_errors: true

- name: Check IGW does not exist
assert:
that:
# Deliberate choice not to change bevahiour when searching by ID
- igw_info is failed

# ============================================================
- name: Create new internet gateway for removal by igw id and wrong vpc id tests
ec2_vpc_igw:
state: present
vpc_id: '{{ vpc_result.vpc.id }}'
register: new_internet_gateway_result

- name: Test state=absent when supplying a gateway id and wrong vpc id (expected failure) - CHECK_MODE
ec2_vpc_igw:
state: absent
internet_gateway_id: '{{ new_internet_gateway_result.gateway_id}}'
vpc_id: 'vpc-xxxxxxxxx'
register: vpc_igw_delete
check_mode: true
ignore_errors: true

- name: Assert state=absent when supplying a gateway id and wrong vpc id (expected failure) - CHECK_MODE
assert:
that:
- vpc_igw_delete is failed
- vpc_igw_delete.msg is search('Supplied VPC.*does not match found VPC.*')

- name: Test state=absent when supplying a gateway id and wrong vpc id (expected failure)
ec2_vpc_igw:
state: absent
internet_gateway_id: '{{ new_internet_gateway_result.gateway_id}}'
vpc_id: 'vpc-xxxxxxxxx'
register: vpc_igw_delete
ignore_errors: true

- name: Assert state=absent when supplying a gateway id and wrong vpc id (expected failure)
assert:
that:
- vpc_igw_delete is failed
- vpc_igw_delete.msg is search('Supplied VPC.*does not match found VPC.*')

always:
# ============================================================
- name: Tidy up IGW
Expand Down

0 comments on commit 412b2e5

Please sign in to comment.