Add minimum botocore and boto3 checking to AnsibleAWSModule (#41005)

* Add minimum botocore and boto3 checking to AnsibleAWSModule
This commit is contained in:
Ryan Brown 2018-06-01 18:45:22 -04:00 committed by Sloane Hertel
parent 2daf5f3edb
commit 7f8654d586
2 changed files with 29 additions and 4 deletions

View file

@ -60,11 +60,13 @@ don't need to be wrapped in the backoff decorator.
""" """
import traceback
from functools import wraps from functools import wraps
from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
from ansible.module_utils.ec2 import HAS_BOTO3, camel_dict_to_snake_dict, ec2_argument_spec, boto3_conn, get_aws_connection_info from ansible.module_utils.ec2 import HAS_BOTO3, camel_dict_to_snake_dict, ec2_argument_spec, boto3_conn, get_aws_connection_info
import traceback
# We will also export HAS_BOTO3 so end user modules can use it. # We will also export HAS_BOTO3 so end user modules can use it.
__all__ = ('AnsibleAWSModule', 'HAS_BOTO3',) __all__ = ('AnsibleAWSModule', 'HAS_BOTO3',)
@ -193,6 +195,30 @@ class AnsibleAWSModule(object):
return dict(boto3_version=boto3.__version__, return dict(boto3_version=boto3.__version__,
botocore_version=botocore.__version__) botocore_version=botocore.__version__)
def boto3_at_least(self, desired):
"""Check if the available boto3 version is greater than or equal to a desired version.
Usage:
if module.params.get('assign_ipv6_address') and not module.boto3_at_least('1.4.4'):
# conditionally fail on old boto3 versions if a specific feature is not supported
module.fail_json(msg="Boto3 can't deal with EC2 IPv6 addresses before version 1.4.4.")
"""
existing = self._gather_versions()
return LooseVersion(existing['boto3_version']) >= LooseVersion(desired)
def botocore_at_least(self, desired):
"""Check if the available botocore version is greater than or equal to a desired version.
Usage:
if not module.botocore_at_least('1.2.3'):
module.fail_json(msg='The Serverless Elastic Load Compute Service is not in botocore before v1.2.3')
if not module.botocore_at_least('1.5.3'):
module.warn('Botocore did not include waiters for Service X before 1.5.3. '
'To wait until Service X resources are fully available, update botocore.')
"""
existing = self._gather_versions()
return LooseVersion(existing['botocore_version']) >= LooseVersion(desired)
class _RetryingBotoClientWrapper(object): class _RetryingBotoClientWrapper(object):
__never_wait = ( __never_wait = (

View file

@ -205,7 +205,6 @@ subnet:
import time import time
import traceback import traceback
from distutils.version import LooseVersion
try: try:
import botocore import botocore
@ -255,7 +254,7 @@ def describe_subnets_with_backoff(client, **params):
def waiter_params(module, params, start_time): def waiter_params(module, params, start_time):
if LooseVersion(botocore.__version__) >= "1.7.0": if not module.botocore_at_least("1.7.0"):
remaining_wait_timeout = int(module.params['wait_timeout'] + start_time - time.time()) remaining_wait_timeout = int(module.params['wait_timeout'] + start_time - time.time())
params['WaiterConfig'] = {'Delay': 5, 'MaxAttempts': remaining_wait_timeout // 5} params['WaiterConfig'] = {'Delay': 5, 'MaxAttempts': remaining_wait_timeout // 5}
return params return params
@ -578,7 +577,7 @@ def main():
if module.params.get('assign_instances_ipv6') and not module.params.get('ipv6_cidr'): if module.params.get('assign_instances_ipv6') and not module.params.get('ipv6_cidr'):
module.fail_json(msg="assign_instances_ipv6 is True but ipv6_cidr is None or an empty string") module.fail_json(msg="assign_instances_ipv6 is True but ipv6_cidr is None or an empty string")
if LooseVersion(botocore.__version__) < "1.7.0": if not module.botocore_at_least("1.7.0"):
module.warn("botocore >= 1.7.0 is required to use wait_timeout for custom wait times") module.warn("botocore >= 1.7.0 is required to use wait_timeout for custom wait times")
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)