diff --git a/plugins/module_utils/waiters.py b/plugins/module_utils/waiters.py index 9e474ae953f..9e8ff54cde6 100644 --- a/plugins/module_utils/waiters.py +++ b/plugins/module_utils/waiters.py @@ -9,6 +9,8 @@ except ImportError: pass # caught by HAS_BOTO3 +import ansible_collections.amazon.aws.plugins.module_utils.core as aws_core + ec2_data = { "version": 2, @@ -422,6 +424,8 @@ def rds_model(name): def get_waiter(client, waiter_name): + if isinstance(client, aws_core._RetryingBotoClientWrapper): + return get_waiter(client.client, waiter_name) try: return waiters_by_name[(client.__class__.__name__, waiter_name)](client) except KeyError: diff --git a/tests/integration/targets/module_utils_waiter/aliases b/tests/integration/targets/module_utils_waiter/aliases new file mode 100644 index 00000000000..6e3860bee23 --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/aliases @@ -0,0 +1,2 @@ +cloud/aws +shippable/aws/group2 diff --git a/tests/integration/targets/module_utils_waiter/inventory b/tests/integration/targets/module_utils_waiter/inventory new file mode 100644 index 00000000000..5093e8582bc --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/inventory @@ -0,0 +1,6 @@ +[tests] +localhost + +[all:vars] +ansible_connection=local +ansible_python_interpreter="{{ ansible_playbook_python }}" diff --git a/tests/integration/targets/module_utils_waiter/main.yml b/tests/integration/targets/module_utils_waiter/main.yml new file mode 100644 index 00000000000..4edc363774e --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/main.yml @@ -0,0 +1,7 @@ +- hosts: all + gather_facts: no + collections: + - amazon.aws + roles: + # Test the behaviour of module_utils.core.AnsibleAWSModule.client (boto3) + - 'get_waiter' diff --git a/tests/integration/targets/module_utils_waiter/meta/main.yml b/tests/integration/targets/module_utils_waiter/meta/main.yml new file mode 100644 index 00000000000..1f64f1169a9 --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_tests + - setup_ec2 diff --git a/tests/integration/targets/module_utils_waiter/roles/get_waiter/library/example_module.py b/tests/integration/targets/module_utils_waiter/roles/get_waiter/library/example_module.py new file mode 100644 index 00000000000..bcbb4204684 --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/roles/get_waiter/library/example_module.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# Copyright (c) 2017 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# A bare-minimum Ansible Module based on AnsibleAWSModule used for testing some +# of the core behaviour around AWS/Boto3 connection details + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +try: + from botocore.exceptions import BotoCoreError, ClientError +except ImportError: + pass # Handled by AnsibleAWSModule + +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.waiters import get_waiter + + +def main(): + argument_spec = dict( + client=dict(required=True, type='str'), + waiter_name=dict(required=True, type='str'), + with_decorator=dict(required=False, type='bool', default=False), + ) + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True, + ) + + decorator = None + if module.params.get('with_decorator'): + decorator = AWSRetry.jittered_backoff() + + client = module.client(module.params.get('client'), retry_decorator=decorator) + waiter = get_waiter(client, module.params.get('waiter_name')) + + module.exit_json(changed=False, waiter_attributes=dir(waiter)) + + +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/module_utils_waiter/roles/get_waiter/meta/main.yml b/tests/integration/targets/module_utils_waiter/roles/get_waiter/meta/main.yml new file mode 100644 index 00000000000..77589cc2b48 --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/roles/get_waiter/meta/main.yml @@ -0,0 +1,5 @@ +dependencies: + - prepare_tests + - setup_ec2 +collections: + - amazon.aws diff --git a/tests/integration/targets/module_utils_waiter/roles/get_waiter/tasks/main.yml b/tests/integration/targets/module_utils_waiter/roles/get_waiter/tasks/main.yml new file mode 100644 index 00000000000..466d9584e24 --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/roles/get_waiter/tasks/main.yml @@ -0,0 +1,36 @@ +--- +- module_defaults: + example_module: + region: '{{ aws_region }}' + access_key: '{{ aws_access_key }}' + secret_key: '{{ aws_secret_key }}' + security_token: '{{ security_token | default(omit) }}' + block: + - name: 'Attempt to get a waiter (no retry decorator)' + example_module: + client: 'ec2' + waiter_name: 'internet_gateway_exists' + register: test_no_decorator + + - assert: + that: + - test_no_decorator is succeeded + # Standard methods on a boto3 wrapper + - '"wait" in test_no_decorator.waiter_attributes' + - '"name" in test_no_decorator.waiter_attributes' + - '"config" in test_no_decorator.waiter_attributes' + + - name: 'Attempt to get a waiter (with decorator)' + example_module: + client: 'ec2' + waiter_name: 'internet_gateway_exists' + with_decorator: True + register: test_with_decorator + + - assert: + that: + - test_with_decorator is succeeded + # Standard methods on a boto3 wrapper + - '"wait" in test_with_decorator.waiter_attributes' + - '"name" in test_with_decorator.waiter_attributes' + - '"config" in test_with_decorator.waiter_attributes' diff --git a/tests/integration/targets/module_utils_waiter/runme.sh b/tests/integration/targets/module_utils_waiter/runme.sh new file mode 100755 index 00000000000..78a6f6dbedd --- /dev/null +++ b/tests/integration/targets/module_utils_waiter/runme.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -eux + +ANSIBLE_ROLES_PATH="../" +export ANSIBLE_ROLES_PATH + +ansible-playbook main.yml -i inventory "$@"