From a571d9952e9099de007c71fa897b008c4382df0e Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Fri, 1 Apr 2022 14:17:50 -0400 Subject: [PATCH 1/3] add manual waiter for nonetype error --- plugins/modules/ec2_vpc_igw.py | 38 +++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/plugins/modules/ec2_vpc_igw.py b/plugins/modules/ec2_vpc_igw.py index 4982cf2b9eb..071b58c65f7 100644 --- a/plugins/modules/ec2_vpc_igw.py +++ b/plugins/modules/ec2_vpc_igw.py @@ -110,6 +110,9 @@ from ..module_utils.ec2 import ensure_ec2_tags from ..module_utils.ec2 import ansible_dict_to_boto3_filter_list from ..module_utils.tagging import boto3_tag_list_to_ansible_dict +from time import sleep +from time import time +from random import randint @AWSRetry.jittered_backoff(retries=10, delay=10) @@ -156,6 +159,31 @@ def get_matching_igw(self, vpc_id): return igw + def wait_for_igw(self, vpc_id): + """ + Waits for existing igw to be returned via describe_internet_gateways + in get_matching_igw with exponential backoff + :param vpc_id: VPC's ID + :return igw: igw found + """ + max_backoff = 64 + timeout = 3000 + failure_counter = 0 + start_time = time() + + while True: + if time() - start_time >= timeout: + self._module.fail_json(msg='Error finding Internet Gateway in VPC {0} - please check the AWS console'.format(vpc_id)) + try: + igw = self.get_matching_igw(vpc_id) + if igw: + return igw + sleep_time = min(2 ** failure_counter + randint(1, 1000) / 1000, max_backoff) + sleep(sleep_time) + failure_counter += 1 + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + self._module.fail_json_aws(e, msg='Failure while waiting for status update') + @staticmethod def get_igw_info(igw, vpc_id): return { @@ -221,12 +249,20 @@ def ensure_igw_present(self, vpc_id, tags, purge_tags): except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg='Unable to create Internet Gateway') + # Ensure we can get igw object prior to modifying tags + igw = self.wait_for_igw(vpc_id) + # Modify tags - self._results['changed'] |= ensure_ec2_tags( + tags_changed = ensure_ec2_tags( self._connection, self._module, igw['internet_gateway_id'], resource_type='internet-gateway', tags=tags, purge_tags=purge_tags, retry_codes='InvalidInternetGatewayID.NotFound' ) + self._results['changed'] |= tags_changed + + # Wait for igw again if tags were modified to be safe + if tags_changed: + igw = self.wait_for_igw(vpc_id) # Update igw igw = self.get_matching_igw(vpc_id) From e3ed7c3c43046e8d6f309c1a47f130901e0a7fea Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Fri, 1 Apr 2022 14:21:55 -0400 Subject: [PATCH 2/3] added changelog --- .../766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml diff --git a/changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml b/changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml new file mode 100644 index 00000000000..7be002e1a5e --- /dev/null +++ b/changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml @@ -0,0 +1,2 @@ +bugfixes: + - ec2_vpc_igw - add manual waiter to fix 'NoneType' object is not subscriptable error (https://github.com/ansible-collections/amazon.aws/pull/766). From ce48e8ca461579a447c03a73b67986f185f5e222 Mon Sep 17 00:00:00 2001 From: Joseph Torcasso Date: Wed, 20 Apr 2022 13:36:18 -0400 Subject: [PATCH 3/3] search for igw using InternetGatewayIds rather than filters --- ...pc_igw-fix-nonetype-with-manual-waiter.yml | 2 - ...igw-use-InternetGatewayIds-not-filters.yml | 2 + plugins/modules/ec2_vpc_igw.py | 57 ++++++------------- 3 files changed, 19 insertions(+), 42 deletions(-) delete mode 100644 changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml create mode 100644 changelogs/fragments/766-ec2_vpc_igw-use-InternetGatewayIds-not-filters.yml diff --git a/changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml b/changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml deleted file mode 100644 index 7be002e1a5e..00000000000 --- a/changelogs/fragments/766-ec2_vpc_igw-fix-nonetype-with-manual-waiter.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - ec2_vpc_igw - add manual waiter to fix 'NoneType' object is not subscriptable error (https://github.com/ansible-collections/amazon.aws/pull/766). diff --git a/changelogs/fragments/766-ec2_vpc_igw-use-InternetGatewayIds-not-filters.yml b/changelogs/fragments/766-ec2_vpc_igw-use-InternetGatewayIds-not-filters.yml new file mode 100644 index 00000000000..7f00abec457 --- /dev/null +++ b/changelogs/fragments/766-ec2_vpc_igw-use-InternetGatewayIds-not-filters.yml @@ -0,0 +1,2 @@ +bugfixes: + - ec2_vpc_igw - use gateway_id rather than filters to paginate if possible to fix 'NoneType' object is not subscriptable error (https://github.com/ansible-collections/amazon.aws/pull/766). diff --git a/plugins/modules/ec2_vpc_igw.py b/plugins/modules/ec2_vpc_igw.py index 071b58c65f7..b59a1c2d68c 100644 --- a/plugins/modules/ec2_vpc_igw.py +++ b/plugins/modules/ec2_vpc_igw.py @@ -110,9 +110,6 @@ from ..module_utils.ec2 import ensure_ec2_tags from ..module_utils.ec2 import ansible_dict_to_boto3_filter_list from ..module_utils.tagging import boto3_tag_list_to_ansible_dict -from time import sleep -from time import time -from random import randint @AWSRetry.jittered_backoff(retries=10, delay=10) @@ -142,10 +139,23 @@ def process(self): elif state == 'absent': self.ensure_igw_absent(vpc_id) - def get_matching_igw(self, vpc_id): + def get_matching_igw(self, vpc_id, gateway_id=None): + ''' + Returns the internet gateway found. + Parameters: + vpc_id (str): VPC ID + gateway_id (str): Internet Gateway ID, if specified + Returns: + igw (dict): dict of igw found, None if none found + ''' filters = ansible_dict_to_boto3_filter_list({'attachment.vpc-id': vpc_id}) try: - igws = describe_igws_with_backoff(self._connection, Filters=filters) + # 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: + igws = describe_igws_with_backoff(self._connection, Filters=filters) + else: + igws = describe_igws_with_backoff(self._connection, InternetGatewayIds=[gateway_id]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e) @@ -159,31 +169,6 @@ def get_matching_igw(self, vpc_id): return igw - def wait_for_igw(self, vpc_id): - """ - Waits for existing igw to be returned via describe_internet_gateways - in get_matching_igw with exponential backoff - :param vpc_id: VPC's ID - :return igw: igw found - """ - max_backoff = 64 - timeout = 3000 - failure_counter = 0 - start_time = time() - - while True: - if time() - start_time >= timeout: - self._module.fail_json(msg='Error finding Internet Gateway in VPC {0} - please check the AWS console'.format(vpc_id)) - try: - igw = self.get_matching_igw(vpc_id) - if igw: - return igw - sleep_time = min(2 ** failure_counter + randint(1, 1000) / 1000, max_backoff) - sleep(sleep_time) - failure_counter += 1 - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self._module.fail_json_aws(e, msg='Failure while waiting for status update') - @staticmethod def get_igw_info(igw, vpc_id): return { @@ -249,23 +234,15 @@ def ensure_igw_present(self, vpc_id, tags, purge_tags): except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg='Unable to create Internet Gateway') - # Ensure we can get igw object prior to modifying tags - igw = self.wait_for_igw(vpc_id) - # Modify tags - tags_changed = ensure_ec2_tags( + self._results['changed'] |= ensure_ec2_tags( self._connection, self._module, igw['internet_gateway_id'], resource_type='internet-gateway', tags=tags, purge_tags=purge_tags, retry_codes='InvalidInternetGatewayID.NotFound' ) - self._results['changed'] |= tags_changed - - # Wait for igw again if tags were modified to be safe - if tags_changed: - igw = self.wait_for_igw(vpc_id) # Update igw - igw = self.get_matching_igw(vpc_id) + igw = self.get_matching_igw(vpc_id, gateway_id=igw['internet_gateway_id']) igw_info = self.get_igw_info(igw, vpc_id) self._results.update(igw_info)