Migrate a batch of AWS modules to AnsibleAWSModule (1) (#67191)

* Move various Amazon modules over to AnsibleAWSModule

* Remove HAS_BOTO3 logic, it's handled by AnsibleAWSModule

* Simplify argument_spec handling ec2_argument_spec is automatically added by AnsibleAWSModule

* Cleanup boto3 error handling using fail_json_aws

* Migrate simple cases from boto3_conn to module.client()

* Migrate batch modules over to module.client()

* Migrate EFS module over to module.client()

* Comment cleanup

* Use deprecated_aliases in argument_spec rather than custom code

* Cleanup unused imports

* Make use of module.region

* Deprecate batch.AWSConnection it's now dead code
This commit is contained in:
Mark Chappell 2020-02-24 20:01:14 +01:00 committed by GitHub
parent 7b792e0a53
commit f520238d60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 268 additions and 489 deletions

View file

@ -47,6 +47,9 @@ class AWSConnection(object):
def __init__(self, ansible_obj, resources, boto3=True): def __init__(self, ansible_obj, resources, boto3=True):
ansible_obj.deprecate("The 'ansible.module_utils.aws.batch.AWSConnection' class is deprecated please use 'AnsibleAWSModule.client()'",
version='2.14')
self.region, self.endpoint, aws_connect_kwargs = get_aws_connection_info(ansible_obj, boto3=boto3) self.region, self.endpoint, aws_connect_kwargs = get_aws_connection_info(ansible_obj, boto3=boto3)
self.resource_client = dict() self.resource_client = dict()

View file

@ -70,43 +70,25 @@ availability_zones:
]" ]"
''' '''
from ansible.module_utils.aws.core import AnsibleAWSModule
import traceback from ansible.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict
from ansible.module_utils._text import to_native
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import get_aws_connection_info, ec2_argument_spec, boto3_conn
from ansible.module_utils.ec2 import ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict, HAS_BOTO3
try: try:
from botocore.exceptions import ClientError, BotoCoreError from botocore.exceptions import ClientError, BotoCoreError
except ImportError: except ImportError:
pass # will be detected by imported HAS_BOTO3 pass # Handled by AnsibleAWSModule
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( filters=dict(default={}, type='dict')
dict(
filters=dict(default={}, type='dict')
)
) )
module = AnsibleModule(argument_spec=argument_spec) module = AnsibleAWSModule(argument_spec=argument_spec)
if module._name == 'aws_az_facts': if module._name == 'aws_az_facts':
module.deprecate("The 'aws_az_facts' module has been renamed to 'aws_az_info'", version='2.14') module.deprecate("The 'aws_az_facts' module has been renamed to 'aws_az_info'", version='2.14')
if not HAS_BOTO3: connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff())
module.fail_json(msg='boto3 required for this module')
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)
connection = boto3_conn(
module,
conn_type='client',
resource='ec2',
region=region,
endpoint=ec2_url,
**aws_connect_params
)
# Replace filter key underscores with dashes, for compatibility # Replace filter key underscores with dashes, for compatibility
sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items()) sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items())
@ -115,12 +97,8 @@ def main():
availability_zones = connection.describe_availability_zones( availability_zones = connection.describe_availability_zones(
Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) Filters=ansible_dict_to_boto3_filter_list(sanitized_filters)
) )
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg="Unable to describe availability zones: {0}".format(to_native(e)), module.fail_json_aws(e, msg="Unable to describe availability zones.")
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except BotoCoreError as e:
module.fail_json(msg="Unable to describe availability zones: {0}".format(to_native(e)),
exception=traceback.format_exc())
# Turn the boto3 result into ansible_friendly_snaked_names # Turn the boto3 result into ansible_friendly_snaked_names
snaked_availability_zones = [camel_dict_to_snake_dict(az) for az in availability_zones['AvailabilityZones']] snaked_availability_zones = [camel_dict_to_snake_dict(az) for az in availability_zones['AvailabilityZones']]

View file

@ -231,18 +231,14 @@ output:
type: dict type: dict
''' '''
from ansible.module_utils._text import to_native from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.aws.batch import AWSConnection
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import ec2_argument_spec, HAS_BOTO3
from ansible.module_utils.ec2 import snake_dict_to_camel_dict, camel_dict_to_snake_dict from ansible.module_utils.ec2 import snake_dict_to_camel_dict, camel_dict_to_snake_dict
import re import re
import traceback
try: try:
from botocore.exceptions import ClientError, ParamValidationError, MissingParametersError from botocore.exceptions import ClientError, BotoCoreError
except ImportError: except ImportError:
pass # Handled by HAS_BOTO3 pass # Handled by AnsibleAWSModule
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
@ -263,12 +259,11 @@ def set_api_params(module, module_params):
return snake_dict_to_camel_dict(api_params) return snake_dict_to_camel_dict(api_params)
def validate_params(module, aws): def validate_params(module):
""" """
Performs basic parameter validation. Performs basic parameter validation.
:param module: :param module:
:param aws:
:return: :return:
""" """
@ -294,9 +289,9 @@ def validate_params(module, aws):
# #
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
def get_current_compute_environment(module, connection): def get_current_compute_environment(module, client):
try: try:
environments = connection.client().describe_compute_environments( environments = client.describe_compute_environments(
computeEnvironments=[module.params['compute_environment_name']] computeEnvironments=[module.params['compute_environment_name']]
) )
if len(environments['computeEnvironments']) > 0: if len(environments['computeEnvironments']) > 0:
@ -307,16 +302,15 @@ def get_current_compute_environment(module, connection):
return None return None
def create_compute_environment(module, aws): def create_compute_environment(module, client):
""" """
Adds a Batch compute environment Adds a Batch compute environment
:param module: :param module:
:param aws: :param client:
:return: :return:
""" """
client = aws.client('batch')
changed = False changed = False
# set API parameters # set API parameters
@ -344,23 +338,21 @@ def create_compute_environment(module, aws):
if not module.check_mode: if not module.check_mode:
client.create_compute_environment(**api_params) client.create_compute_environment(**api_params)
changed = True changed = True
except (ClientError, ParamValidationError, MissingParametersError) as e: except (ClientError, BotoCoreError) as e:
module.fail_json(msg='Error creating compute environment: {0}'.format(to_native(e)), module.fail_json_aws(e, msg='Error creating compute environment')
exception=traceback.format_exc())
return changed return changed
def remove_compute_environment(module, aws): def remove_compute_environment(module, client):
""" """
Remove a Batch compute environment Remove a Batch compute environment
:param module: :param module:
:param aws: :param client:
:return: :return:
""" """
client = aws.client('batch')
changed = False changed = False
# set API parameters # set API parameters
@ -370,13 +362,12 @@ def remove_compute_environment(module, aws):
if not module.check_mode: if not module.check_mode:
client.delete_compute_environment(**api_params) client.delete_compute_environment(**api_params)
changed = True changed = True
except (ClientError, ParamValidationError, MissingParametersError) as e: except (ClientError, BotoCoreError) as e:
module.fail_json(msg='Error removing compute environment: {0}'.format(to_native(e)), module.fail_json_aws(e, msg='Error removing compute environment')
exception=traceback.format_exc())
return changed return changed
def manage_state(module, aws): def manage_state(module, client):
changed = False changed = False
current_state = 'absent' current_state = 'absent'
state = module.params['state'] state = module.params['state']
@ -392,7 +383,7 @@ def manage_state(module, aws):
check_mode = module.check_mode check_mode = module.check_mode
# check if the compute environment exists # check if the compute environment exists
current_compute_environment = get_current_compute_environment(module, aws) current_compute_environment = get_current_compute_environment(module, client)
response = current_compute_environment response = current_compute_environment
if current_compute_environment: if current_compute_environment:
current_state = 'present' current_state = 'present'
@ -423,27 +414,26 @@ def manage_state(module, aws):
if updates: if updates:
try: try:
if not check_mode: if not check_mode:
update_env_response = aws.client().update_compute_environment(**compute_kwargs) update_env_response = client.update_compute_environment(**compute_kwargs)
if not update_env_response: if not update_env_response:
module.fail_json(msg='Unable to get compute environment information after creating') module.fail_json(msg='Unable to get compute environment information after creating')
changed = True changed = True
action_taken = "updated" action_taken = "updated"
except (ParamValidationError, ClientError) as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg="Unable to update environment: {0}".format(to_native(e)), module.fail_json_aws(e, msg="Unable to update environment.")
exception=traceback.format_exc())
else: else:
# Create Batch Compute Environment # Create Batch Compute Environment
changed = create_compute_environment(module, aws) changed = create_compute_environment(module, client)
# Describe compute environment # Describe compute environment
action_taken = 'added' action_taken = 'added'
response = get_current_compute_environment(module, aws) response = get_current_compute_environment(module, client)
if not response: if not response:
module.fail_json(msg='Unable to get compute environment information after creating') module.fail_json(msg='Unable to get compute environment information after creating')
else: else:
if current_state == 'present': if current_state == 'present':
# remove the compute environment # remove the compute environment
changed = remove_compute_environment(module, aws) changed = remove_compute_environment(module, client)
action_taken = 'deleted' action_taken = 'deleted'
return dict(changed=changed, batch_compute_environment_action=action_taken, response=response) return dict(changed=changed, batch_compute_environment_action=action_taken, response=response)
@ -461,45 +451,37 @@ def main():
:return dict: changed, batch_compute_environment_action, response :return dict: changed, batch_compute_environment_action, response
""" """
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( state=dict(default='present', choices=['present', 'absent']),
dict( compute_environment_name=dict(required=True),
state=dict(default='present', choices=['present', 'absent']), type=dict(required=True, choices=['MANAGED', 'UNMANAGED']),
compute_environment_name=dict(required=True), compute_environment_state=dict(required=False, default='ENABLED', choices=['ENABLED', 'DISABLED']),
type=dict(required=True, choices=['MANAGED', 'UNMANAGED']), service_role=dict(required=True),
compute_environment_state=dict(required=False, default='ENABLED', choices=['ENABLED', 'DISABLED']), compute_resource_type=dict(required=True, choices=['EC2', 'SPOT']),
service_role=dict(required=True), minv_cpus=dict(type='int', required=True),
compute_resource_type=dict(required=True, choices=['EC2', 'SPOT']), maxv_cpus=dict(type='int', required=True),
minv_cpus=dict(type='int', required=True), desiredv_cpus=dict(type='int'),
maxv_cpus=dict(type='int', required=True), instance_types=dict(type='list', required=True),
desiredv_cpus=dict(type='int'), image_id=dict(),
instance_types=dict(type='list', required=True), subnets=dict(type='list', required=True),
image_id=dict(), security_group_ids=dict(type='list', required=True),
subnets=dict(type='list', required=True), ec2_key_pair=dict(),
security_group_ids=dict(type='list', required=True), instance_role=dict(required=True),
ec2_key_pair=dict(), tags=dict(type='dict'),
instance_role=dict(required=True), bid_percentage=dict(type='int'),
tags=dict(type='dict'), spot_iam_fleet_role=dict(),
bid_percentage=dict(type='int'),
spot_iam_fleet_role=dict(),
region=dict(aliases=['aws_region', 'ec2_region'])
)
) )
module = AnsibleModule( module = AnsibleAWSModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True supports_check_mode=True
) )
# validate dependencies client = module.client('batch')
if not HAS_BOTO3:
module.fail_json(msg='boto3 is required for this module.')
aws = AWSConnection(module, ['batch']) validate_params(module)
validate_params(module, aws) results = manage_state(module, client)
results = manage_state(module, aws)
module.exit_json(**camel_dict_to_snake_dict(results, ignore_list=['Tags'])) module.exit_json(**camel_dict_to_snake_dict(results, ignore_list=['Tags']))

View file

@ -226,18 +226,14 @@ output:
type: dict type: dict
''' '''
from ansible.module_utils._text import to_native from ansible.module_utils.aws.batch import cc, set_api_params
from ansible.module_utils.aws.batch import AWSConnection, cc, set_api_params from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import ec2_argument_spec, HAS_BOTO3
from ansible.module_utils.ec2 import camel_dict_to_snake_dict from ansible.module_utils.ec2 import camel_dict_to_snake_dict
import traceback
try: try:
from botocore.exceptions import ClientError, ParamValidationError, MissingParametersError from botocore.exceptions import ClientError, BotoCoreError
except ImportError: except ImportError:
pass # Handled by HAS_BOTO3 pass # Handled by AnsibleAWSModule
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
@ -251,12 +247,12 @@ except ImportError:
# logger.setLevel(logging.DEBUG) # logger.setLevel(logging.DEBUG)
def validate_params(module, aws): def validate_params(module, batch_client):
""" """
Performs basic parameter validation. Performs basic parameter validation.
:param module: :param module:
:param aws: :param batch_client:
:return: :return:
""" """
return return
@ -268,9 +264,9 @@ def validate_params(module, aws):
# #
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
def get_current_job_definition(module, connection): def get_current_job_definition(module, batch_client):
try: try:
environments = connection.client().describe_job_definitions( environments = batch_client.describe_job_definitions(
jobDefinitionName=module.params['job_definition_name'] jobDefinitionName=module.params['job_definition_name']
) )
if len(environments['jobDefinitions']) > 0: if len(environments['jobDefinitions']) > 0:
@ -283,16 +279,15 @@ def get_current_job_definition(module, connection):
return None return None
def create_job_definition(module, aws): def create_job_definition(module, batch_client):
""" """
Adds a Batch job definition Adds a Batch job definition
:param module: :param module:
:param aws: :param batch_client:
:return: :return:
""" """
client = aws.client('batch')
changed = False changed = False
# set API parameters # set API parameters
@ -305,11 +300,10 @@ def create_job_definition(module, aws):
try: try:
if not module.check_mode: if not module.check_mode:
client.register_job_definition(**api_params) batch_client.register_job_definition(**api_params)
changed = True changed = True
except (ClientError, ParamValidationError, MissingParametersError) as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg='Error registering job definition: {0}'.format(to_native(e)), module.fail_json_aws(e, msg='Error registering job definition')
exception=traceback.format_exc())
return changed return changed
@ -334,25 +328,23 @@ def get_compute_environment_order_list(module):
return compute_environment_order_list return compute_environment_order_list
def remove_job_definition(module, aws): def remove_job_definition(module, batch_client):
""" """
Remove a Batch job definition Remove a Batch job definition
:param module: :param module:
:param aws: :param batch_client:
:return: :return:
""" """
client = aws.client('batch')
changed = False changed = False
try: try:
if not module.check_mode: if not module.check_mode:
client.deregister_job_definition(jobDefinition=module.params['job_definition_arn']) batch_client.deregister_job_definition(jobDefinition=module.params['job_definition_arn'])
changed = True changed = True
except (ClientError, ParamValidationError, MissingParametersError) as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg='Error removing job definition: {0}'.format(to_native(e)), module.fail_json_aws(e, msg='Error removing job definition')
exception=traceback.format_exc())
return changed return changed
@ -377,7 +369,7 @@ def job_definition_equal(module, current_definition):
return equal return equal
def manage_state(module, aws): def manage_state(module, batch_client):
changed = False changed = False
current_state = 'absent' current_state = 'absent'
state = module.params['state'] state = module.params['state']
@ -388,7 +380,7 @@ def manage_state(module, aws):
check_mode = module.check_mode check_mode = module.check_mode
# check if the job definition exists # check if the job definition exists
current_job_definition = get_current_job_definition(module, aws) current_job_definition = get_current_job_definition(module, batch_client)
if current_job_definition: if current_job_definition:
current_state = 'present' current_state = 'present'
@ -396,21 +388,21 @@ def manage_state(module, aws):
if current_state == 'present': if current_state == 'present':
# check if definition has changed and register a new version if necessary # check if definition has changed and register a new version if necessary
if not job_definition_equal(module, current_job_definition): if not job_definition_equal(module, current_job_definition):
create_job_definition(module, aws) create_job_definition(module, batch_client)
action_taken = 'updated with new version' action_taken = 'updated with new version'
changed = True changed = True
else: else:
# Create Job definition # Create Job definition
changed = create_job_definition(module, aws) changed = create_job_definition(module, batch_client)
action_taken = 'added' action_taken = 'added'
response = get_current_job_definition(module, aws) response = get_current_job_definition(module, batch_client)
if not response: if not response:
module.fail_json(msg='Unable to get job definition information after creating/updating') module.fail_json(msg='Unable to get job definition information after creating/updating')
else: else:
if current_state == 'present': if current_state == 'present':
# remove the Job definition # remove the Job definition
changed = remove_job_definition(module, aws) changed = remove_job_definition(module, batch_client)
action_taken = 'deregistered' action_taken = 'deregistered'
return dict(changed=changed, batch_job_definition_action=action_taken, response=response) return dict(changed=changed, batch_job_definition_action=action_taken, response=response)
@ -428,45 +420,37 @@ def main():
:return dict: ansible facts :return dict: ansible facts
""" """
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( state=dict(required=False, default='present', choices=['present', 'absent']),
dict( job_definition_name=dict(required=True),
state=dict(required=False, default='present', choices=['present', 'absent']), job_definition_arn=dict(),
job_definition_name=dict(required=True), type=dict(required=True),
job_definition_arn=dict(), parameters=dict(type='dict'),
type=dict(required=True), image=dict(required=True),
parameters=dict(type='dict'), vcpus=dict(type='int', required=True),
image=dict(required=True), memory=dict(type='int', required=True),
vcpus=dict(type='int', required=True), command=dict(type='list', default=[]),
memory=dict(type='int', required=True), job_role_arn=dict(),
command=dict(type='list', default=[]), volumes=dict(type='list', default=[]),
job_role_arn=dict(), environment=dict(type='list', default=[]),
volumes=dict(type='list', default=[]), mount_points=dict(type='list', default=[]),
environment=dict(type='list', default=[]), readonly_root_filesystem=dict(),
mount_points=dict(type='list', default=[]), privileged=dict(),
readonly_root_filesystem=dict(), ulimits=dict(type='list', default=[]),
privileged=dict(), user=dict(),
ulimits=dict(type='list', default=[]), attempts=dict(type='int')
user=dict(),
attempts=dict(type='int'),
region=dict(aliases=['aws_region', 'ec2_region'])
)
) )
module = AnsibleModule( module = AnsibleAWSModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True supports_check_mode=True
) )
# validate dependencies batch_client = module.client('batch')
if not HAS_BOTO3:
module.fail_json(msg='boto3 is required for this module.')
aws = AWSConnection(module, ['batch']) validate_params(module, batch_client)
validate_params(module, aws) results = manage_state(module, batch_client)
results = manage_state(module, aws)
module.exit_json(**camel_dict_to_snake_dict(results)) module.exit_json(**camel_dict_to_snake_dict(results))

View file

@ -114,19 +114,14 @@ output:
type: dict type: dict
''' '''
from ansible.module_utils._text import to_native from ansible.module_utils.aws.batch import set_api_params
from ansible.module_utils.aws.batch import AWSConnection, cc, set_api_params from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import ec2_argument_spec, get_aws_connection_info, boto3_conn, HAS_BOTO3
from ansible.module_utils.ec2 import camel_dict_to_snake_dict from ansible.module_utils.ec2 import camel_dict_to_snake_dict
import re
import traceback
try: try:
from botocore.exceptions import ClientError, ParamValidationError, MissingParametersError from botocore.exceptions import BotoCoreError, ClientError
except ImportError: except ImportError:
pass # Handled by HAS_BOTO3 pass # Handled by AnsibleAWSModule
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
# #
@ -135,13 +130,11 @@ except ImportError:
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
def validate_params(module, aws): def validate_params(module):
""" """
Performs basic parameter validation. Performs basic parameter validation.
:param module: :param module:
:param aws:
:return:
""" """
return return
@ -152,9 +145,9 @@ def validate_params(module, aws):
# #
# --------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------
def get_current_job_queue(module, connection): def get_current_job_queue(module, client):
try: try:
environments = connection.client().describe_job_queues( environments = client.describe_job_queues(
jobQueues=[module.params['job_queue_name']] jobQueues=[module.params['job_queue_name']]
) )
return environments['jobQueues'][0] if len(environments['jobQueues']) > 0 else None return environments['jobQueues'][0] if len(environments['jobQueues']) > 0 else None
@ -162,16 +155,15 @@ def get_current_job_queue(module, connection):
return None return None
def create_job_queue(module, aws): def create_job_queue(module, client):
""" """
Adds a Batch job queue Adds a Batch job queue
:param module: :param module:
:param aws: :param client:
:return: :return:
""" """
client = aws.client('batch')
changed = False changed = False
# set API parameters # set API parameters
@ -187,9 +179,8 @@ def create_job_queue(module, aws):
if not module.check_mode: if not module.check_mode:
client.create_job_queue(**api_params) client.create_job_queue(**api_params)
changed = True changed = True
except (ClientError, ParamValidationError, MissingParametersError) as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg='Error creating compute environment: {0}'.format(to_native(e)), module.fail_json_aws(e, msg='Error creating compute environment')
exception=traceback.format_exc())
return changed return changed
@ -201,16 +192,15 @@ def get_compute_environment_order_list(module):
return compute_environment_order_list return compute_environment_order_list
def remove_job_queue(module, aws): def remove_job_queue(module, client):
""" """
Remove a Batch job queue Remove a Batch job queue
:param module: :param module:
:param aws: :param client:
:return: :return:
""" """
client = aws.client('batch')
changed = False changed = False
# set API parameters # set API parameters
@ -220,13 +210,12 @@ def remove_job_queue(module, aws):
if not module.check_mode: if not module.check_mode:
client.delete_job_queue(**api_params) client.delete_job_queue(**api_params)
changed = True changed = True
except (ClientError, ParamValidationError, MissingParametersError) as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg='Error removing job queue: {0}'.format(to_native(e)), module.fail_json_aws(e, msg='Error removing job queue')
exception=traceback.format_exc())
return changed return changed
def manage_state(module, aws): def manage_state(module, client):
changed = False changed = False
current_state = 'absent' current_state = 'absent'
state = module.params['state'] state = module.params['state']
@ -239,7 +228,7 @@ def manage_state(module, aws):
check_mode = module.check_mode check_mode = module.check_mode
# check if the job queue exists # check if the job queue exists
current_job_queue = get_current_job_queue(module, aws) current_job_queue = get_current_job_queue(module, client)
if current_job_queue: if current_job_queue:
current_state = 'present' current_state = 'present'
@ -265,26 +254,25 @@ def manage_state(module, aws):
if updates: if updates:
try: try:
if not check_mode: if not check_mode:
aws.client().update_job_queue(**job_kwargs) client.update_job_queue(**job_kwargs)
changed = True changed = True
action_taken = "updated" action_taken = "updated"
except (ParamValidationError, ClientError) as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg="Unable to update job queue: {0}".format(to_native(e)), module.fail_json_aws(e, msg="Unable to update job queue")
exception=traceback.format_exc())
else: else:
# Create Job Queue # Create Job Queue
changed = create_job_queue(module, aws) changed = create_job_queue(module, client)
action_taken = 'added' action_taken = 'added'
# Describe job queue # Describe job queue
response = get_current_job_queue(module, aws) response = get_current_job_queue(module, client)
if not response: if not response:
module.fail_json(msg='Unable to get job queue information after creating/updating') module.fail_json(msg='Unable to get job queue information after creating/updating')
else: else:
if current_state == 'present': if current_state == 'present':
# remove the Job Queue # remove the Job Queue
changed = remove_job_queue(module, aws) changed = remove_job_queue(module, client)
action_taken = 'deleted' action_taken = 'deleted'
return dict(changed=changed, batch_job_queue_action=action_taken, response=response) return dict(changed=changed, batch_job_queue_action=action_taken, response=response)
@ -302,32 +290,24 @@ def main():
:return dict: changed, batch_job_queue_action, response :return dict: changed, batch_job_queue_action, response
""" """
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( state=dict(required=False, default='present', choices=['present', 'absent']),
dict( job_queue_name=dict(required=True),
state=dict(required=False, default='present', choices=['present', 'absent']), job_queue_state=dict(required=False, default='ENABLED', choices=['ENABLED', 'DISABLED']),
job_queue_name=dict(required=True), priority=dict(type='int', required=True),
job_queue_state=dict(required=False, default='ENABLED', choices=['ENABLED', 'DISABLED']), compute_environment_order=dict(type='list', required=True),
priority=dict(type='int', required=True),
compute_environment_order=dict(type='list', required=True),
region=dict(aliases=['aws_region', 'ec2_region'])
)
) )
module = AnsibleModule( module = AnsibleAWSModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True supports_check_mode=True
) )
# validate dependencies client = module.client('batch')
if not HAS_BOTO3:
module.fail_json(msg='boto3 is required for this module.')
aws = AWSConnection(module, ['batch']) validate_params(module)
validate_params(module, aws) results = manage_state(module, client)
results = manage_state(module, aws)
module.exit_json(**camel_dict_to_snake_dict(results)) module.exit_json(**camel_dict_to_snake_dict(results))

View file

@ -59,43 +59,25 @@ regions:
}]" }]"
''' '''
from ansible.module_utils.aws.core import AnsibleAWSModule
import traceback from ansible.module_utils.ec2 import AWSRetry, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict
from ansible.module_utils._text import to_native
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import get_aws_connection_info, ec2_argument_spec, boto3_conn
from ansible.module_utils.ec2 import ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict, HAS_BOTO3
try: try:
from botocore.exceptions import ClientError, BotoCoreError from botocore.exceptions import ClientError, BotoCoreError
except ImportError: except ImportError:
pass # will be detected by imported HAS_BOTO3 pass # Handled by AnsibleAWSModule
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( filters=dict(default={}, type='dict')
dict(
filters=dict(default={}, type='dict')
)
) )
module = AnsibleModule(argument_spec=argument_spec) module = AnsibleAWSModule(argument_spec=argument_spec)
if module._name == 'aws_region_facts': if module._name == 'aws_region_facts':
module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", version='2.13') module.deprecate("The 'aws_region_facts' module has been renamed to 'aws_region_info'", version='2.13')
if not HAS_BOTO3: connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff())
module.fail_json(msg='boto3 required for this module')
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)
connection = boto3_conn(
module,
conn_type='client',
resource='ec2',
region=region,
endpoint=ec2_url,
**aws_connect_params
)
# Replace filter key underscores with dashes, for compatibility # Replace filter key underscores with dashes, for compatibility
sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items()) sanitized_filters = dict((k.replace('_', '-'), v) for k, v in module.params.get('filters').items())
@ -104,13 +86,8 @@ def main():
regions = connection.describe_regions( regions = connection.describe_regions(
Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) Filters=ansible_dict_to_boto3_filter_list(sanitized_filters)
) )
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg="Unable to describe regions: {0}".format(to_native(e)), module.fail_json_aws(e, msg="Unable to describe regions.")
exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response))
except BotoCoreError as e:
module.fail_json(msg="Unable to describe regions: {0}".format(to_native(e)),
exception=traceback.format_exc())
module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions['Regions']]) module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions['Regions']])

View file

@ -99,15 +99,10 @@ rules:
try: try:
from botocore.exceptions import ClientError, BotoCoreError from botocore.exceptions import ClientError, BotoCoreError
except Exception: except Exception:
# handled by HAS_BOTO3 check in main pass # Handled by AnsibleAWSModule
pass
import traceback from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import snake_dict_to_camel_dict, compare_policies
from ansible.module_utils._text import to_native
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import (HAS_BOTO3, boto3_conn, ec2_argument_spec, get_aws_connection_info,
camel_dict_to_snake_dict, snake_dict_to_camel_dict, compare_policies)
def create_or_update_bucket_cors(connection, module): def create_or_update_bucket_cors(connection, module):
@ -129,17 +124,8 @@ def create_or_update_bucket_cors(connection, module):
if changed: if changed:
try: try:
cors = connection.put_bucket_cors(Bucket=name, CORSConfiguration={'CORSRules': new_camel_rules}) cors = connection.put_bucket_cors(Bucket=name, CORSConfiguration={'CORSRules': new_camel_rules})
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json( module.fail_json_aws(e, msg="Unable to update CORS for bucket {0}".format(name))
msg="Unable to update CORS for bucket {0}: {1}".format(name, to_native(e)),
exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response)
)
except BotoCoreError as e:
module.fail_json(
msg=to_native(e),
exception=traceback.format_exc()
)
module.exit_json(changed=changed, name=name, rules=rules) module.exit_json(changed=changed, name=name, rules=rules)
@ -152,40 +138,23 @@ def destroy_bucket_cors(connection, module):
try: try:
cors = connection.delete_bucket_cors(Bucket=name) cors = connection.delete_bucket_cors(Bucket=name)
changed = True changed = True
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json( module.fail_json_aws(e, msg="Unable to delete CORS for bucket {0}".format(name))
msg="Unable to delete CORS for bucket {0}: {1}".format(name, to_native(e)),
exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response)
)
except BotoCoreError as e:
module.fail_json(
msg=to_native(e),
exception=traceback.format_exc()
)
module.exit_json(changed=changed) module.exit_json(changed=changed)
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( name=dict(required=True, type='str'),
dict( rules=dict(type='list'),
name=dict(required=True, type='str'), state=dict(type='str', choices=['present', 'absent'], required=True)
rules=dict(type='list'),
state=dict(type='str', choices=['present', 'absent'], required=True)
)
) )
module = AnsibleModule(argument_spec=argument_spec) module = AnsibleAWSModule(argument_spec=argument_spec)
if not HAS_BOTO3: client = module.client('s3')
module.fail_json(msg='boto3 is required.')
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
client = boto3_conn(module, conn_type='client', resource='s3',
region=region, endpoint=ec2_url, **aws_connect_kwargs)
state = module.params.get("state") state = module.params.get("state")

View file

@ -262,33 +262,29 @@ trail:
sample: {'environment': 'dev', 'Name': 'default'} sample: {'environment': 'dev', 'Name': 'default'}
''' '''
import traceback
try: try:
from botocore.exceptions import ClientError from botocore.exceptions import ClientError, BotoCoreError
except ImportError: except ImportError:
# Handled in main() by imported HAS_BOTO3 pass # Handled by AnsibleAWSModule
pass
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import (boto3_conn, ec2_argument_spec, get_aws_connection_info, from ansible.module_utils.ec2 import (camel_dict_to_snake_dict,
HAS_BOTO3, ansible_dict_to_boto3_tag_list, ansible_dict_to_boto3_tag_list, boto3_tag_list_to_ansible_dict)
boto3_tag_list_to_ansible_dict, camel_dict_to_snake_dict)
def create_trail(module, client, ct_params): def create_trail(module, client, ct_params):
""" """
Creates a CloudTrail Creates a CloudTrail
module : AnsibleModule object module : AnsibleAWSModule object
client : boto3 client connection object client : boto3 client connection object
ct_params : The parameters for the Trail to create ct_params : The parameters for the Trail to create
""" """
resp = {} resp = {}
try: try:
resp = client.create_trail(**ct_params) resp = client.create_trail(**ct_params)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to create Trail")
return resp return resp
@ -297,7 +293,7 @@ def tag_trail(module, client, tags, trail_arn, curr_tags=None, dry_run=False):
""" """
Creates, updates, removes tags on a CloudTrail resource Creates, updates, removes tags on a CloudTrail resource
module : AnsibleModule object module : AnsibleAWSModule object
client : boto3 client connection object client : boto3 client connection object
tags : Dict of tags converted from ansible_dict to boto3 list of dicts tags : Dict of tags converted from ansible_dict to boto3 list of dicts
trail_arn : The ARN of the CloudTrail to operate on trail_arn : The ARN of the CloudTrail to operate on
@ -331,16 +327,16 @@ def tag_trail(module, client, tags, trail_arn, curr_tags=None, dry_run=False):
if not dry_run: if not dry_run:
try: try:
client.remove_tags(ResourceId=trail_arn, TagsList=removes + updates) client.remove_tags(ResourceId=trail_arn, TagsList=removes + updates)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to remove tags from Trail")
if updates or adds: if updates or adds:
changed = True changed = True
if not dry_run: if not dry_run:
try: try:
client.add_tags(ResourceId=trail_arn, TagsList=updates + adds) client.add_tags(ResourceId=trail_arn, TagsList=updates + adds)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to add tags to Trail")
return changed return changed
@ -362,7 +358,7 @@ def set_logging(module, client, name, action):
""" """
Starts or stops logging based on given state Starts or stops logging based on given state
module : AnsibleModule object module : AnsibleAWSModule object
client : boto3 client connection object client : boto3 client connection object
name : The name or ARN of the CloudTrail to operate on name : The name or ARN of the CloudTrail to operate on
action : start or stop action : start or stop
@ -371,14 +367,14 @@ def set_logging(module, client, name, action):
try: try:
client.start_logging(Name=name) client.start_logging(Name=name)
return client.get_trail_status(Name=name) return client.get_trail_status(Name=name)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to start logging")
elif action == 'stop': elif action == 'stop':
try: try:
client.stop_logging(Name=name) client.stop_logging(Name=name)
return client.get_trail_status(Name=name) return client.get_trail_status(Name=name)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to stop logging")
else: else:
module.fail_json(msg="Unsupported logging action") module.fail_json(msg="Unsupported logging action")
@ -387,15 +383,15 @@ def get_trail_facts(module, client, name):
""" """
Describes existing trail in an account Describes existing trail in an account
module : AnsibleModule object module : AnsibleAWSModule object
client : boto3 client connection object client : boto3 client connection object
name : Name of the trail name : Name of the trail
""" """
# get Trail info # get Trail info
try: try:
trail_resp = client.describe_trails(trailNameList=[name]) trail_resp = client.describe_trails(trailNameList=[name])
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to describe Trail")
# Now check to see if our trail exists and get status and tags # Now check to see if our trail exists and get status and tags
if len(trail_resp['trailList']): if len(trail_resp['trailList']):
@ -403,8 +399,8 @@ def get_trail_facts(module, client, name):
try: try:
status_resp = client.get_trail_status(Name=trail['Name']) status_resp = client.get_trail_status(Name=trail['Name'])
tags_list = client.list_tags(ResourceIdList=[trail['TrailARN']]) tags_list = client.list_tags(ResourceIdList=[trail['TrailARN']])
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to describe Trail")
trail['IsLogging'] = status_resp['IsLogging'] trail['IsLogging'] = status_resp['IsLogging']
trail['tags'] = boto3_tag_list_to_ansible_dict(tags_list['ResourceTagList'][0]['TagsList']) trail['tags'] = boto3_tag_list_to_ansible_dict(tags_list['ResourceTagList'][0]['TagsList'])
@ -423,33 +419,32 @@ def delete_trail(module, client, trail_arn):
""" """
Delete a CloudTrail Delete a CloudTrail
module : AnsibleModule object module : AnsibleAWSModule object
client : boto3 client connection object client : boto3 client connection object
trail_arn : Full CloudTrail ARN trail_arn : Full CloudTrail ARN
""" """
try: try:
client.delete_trail(Name=trail_arn) client.delete_trail(Name=trail_arn)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to delete Trail")
def update_trail(module, client, ct_params): def update_trail(module, client, ct_params):
""" """
Delete a CloudTrail Delete a CloudTrail
module : AnsibleModule object module : AnsibleAWSModule object
client : boto3 client connection object client : boto3 client connection object
ct_params : The parameters for the Trail to update ct_params : The parameters for the Trail to update
""" """
try: try:
client.update_trail(**ct_params) client.update_trail(**ct_params)
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to update Trail")
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update(dict(
state=dict(default='present', choices=['present', 'absent', 'enabled', 'disabled']), state=dict(default='present', choices=['present', 'absent', 'enabled', 'disabled']),
name=dict(default='default'), name=dict(default='default'),
enable_logging=dict(default=True, type='bool'), enable_logging=dict(default=True, type='bool'),
@ -463,15 +458,12 @@ def main():
cloudwatch_logs_log_group_arn=dict(), cloudwatch_logs_log_group_arn=dict(),
kms_key_id=dict(), kms_key_id=dict(),
tags=dict(default={}, type='dict'), tags=dict(default={}, type='dict'),
)) )
required_if = [('state', 'present', ['s3_bucket_name']), ('state', 'enabled', ['s3_bucket_name'])] required_if = [('state', 'present', ['s3_bucket_name']), ('state', 'enabled', ['s3_bucket_name'])]
required_together = [('cloudwatch_logs_role_arn', 'cloudwatch_logs_log_group_arn')] required_together = [('cloudwatch_logs_role_arn', 'cloudwatch_logs_log_group_arn')]
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, required_together=required_together, required_if=required_if) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, required_together=required_together, required_if=required_if)
if not HAS_BOTO3:
module.fail_json(msg='boto3 is required for this module')
# collect parameters # collect parameters
if module.params['state'] in ('present', 'enabled'): if module.params['state'] in ('present', 'enabled'):
@ -505,11 +497,8 @@ def main():
if module.params['kms_key_id']: if module.params['kms_key_id']:
ct_params['KmsKeyId'] = module.params['kms_key_id'] ct_params['KmsKeyId'] = module.params['kms_key_id']
try: client = module.client('cloudtrail')
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) region = module.region
client = boto3_conn(module, conn_type='client', resource='cloudtrail', region=region, endpoint=ec2_url, **aws_connect_params)
except ClientError as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response))
results = dict( results = dict(
changed=False, changed=False,
@ -589,8 +578,8 @@ def main():
# Get the trail status # Get the trail status
try: try:
status_resp = client.get_trail_status(Name=created_trail['Name']) status_resp = client.get_trail_status(Name=created_trail['Name'])
except ClientError as err: except (BotoCoreError, ClientError) as err:
module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response)) module.fail_json_aws(err, msg="Failed to fetch Trail statuc")
# Set the logging state for the trail to desired value # Set the logging state for the trail to desired value
if enable_logging and not status_resp['IsLogging']: if enable_logging and not status_resp['IsLogging']:
set_logging(module, client, name=ct_params['Name'], action='start') set_logging(module, client, name=ct_params['Name'], action='start')
@ -603,9 +592,9 @@ def main():
if module.check_mode: if module.check_mode:
acct_id = '123456789012' acct_id = '123456789012'
try: try:
sts_client = boto3_conn(module, conn_type='client', resource='sts', region=region, endpoint=ec2_url, **aws_connect_params) sts_client = module.client('sts')
acct_id = sts_client.get_caller_identity()['Account'] acct_id = sts_client.get_caller_identity()['Account']
except ClientError: except (BotoCoreError, ClientError):
pass pass
trail = dict() trail = dict()
trail.update(ct_params) trail.update(ct_params)

View file

@ -223,13 +223,12 @@ termination_policies:
import re import re
try: try:
from botocore.exceptions import ClientError from botocore.exceptions import BotoCoreError, ClientError
except ImportError: except ImportError:
pass # caught by imported HAS_BOTO3 pass # caught by AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import (get_aws_connection_info, boto3_conn, ec2_argument_spec, from ansible.module_utils.ec2 import camel_dict_to_snake_dict
camel_dict_to_snake_dict, HAS_BOTO3)
def match_asg_tags(tags_to_match, asg): def match_asg_tags(tags_to_match, asg):
@ -335,14 +334,14 @@ def find_asgs(conn, module, name=None, tags=None):
try: try:
asgs_paginator = conn.get_paginator('describe_auto_scaling_groups') asgs_paginator = conn.get_paginator('describe_auto_scaling_groups')
asgs = asgs_paginator.paginate().build_full_result() asgs = asgs_paginator.paginate().build_full_result()
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response)) module.fail_json_aws(e, msg='Failed to describe AutoScalingGroups')
if not asgs: if not asgs:
return asgs return asgs
try: try:
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True) elbv2 = module.client('elbv2')
elbv2 = boto3_conn(module, conn_type='client', resource='elbv2', region=region, endpoint=ec2_url, **aws_connect_kwargs)
except ClientError as e: except ClientError as e:
# This is nice to have, not essential # This is nice to have, not essential
elbv2 = None elbv2 = None
@ -381,6 +380,10 @@ def find_asgs(conn, module, name=None, tags=None):
except ClientError as e: except ClientError as e:
if e.response['Error']['Code'] == 'TargetGroupNotFound': if e.response['Error']['Code'] == 'TargetGroupNotFound':
asg['target_group_names'] = [] asg['target_group_names'] = []
else:
module.fail_json_aws(e, msg="Failed to describe Target Groups")
except BotoCoreError as e:
module.fail_json_aws(e, msg="Failed to describe Target Groups")
else: else:
asg['target_group_names'] = [] asg['target_group_names'] = []
matched_asgs.append(asg) matched_asgs.append(asg)
@ -390,28 +393,18 @@ def find_asgs(conn, module, name=None, tags=None):
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( name=dict(type='str'),
dict( tags=dict(type='dict'),
name=dict(type='str'),
tags=dict(type='dict'),
)
) )
module = AnsibleModule(argument_spec=argument_spec) module = AnsibleAWSModule(argument_spec=argument_spec)
if module._name == 'ec2_asg_facts': if module._name == 'ec2_asg_facts':
module.deprecate("The 'ec2_asg_facts' module has been renamed to 'ec2_asg_info'", version='2.13') module.deprecate("The 'ec2_asg_facts' module has been renamed to 'ec2_asg_info'", version='2.13')
if not HAS_BOTO3:
module.fail_json(msg='boto3 required for this module')
asg_name = module.params.get('name') asg_name = module.params.get('name')
asg_tags = module.params.get('tags') asg_tags = module.params.get('tags')
try: autoscaling = module.client('autoscaling')
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
autoscaling = boto3_conn(module, conn_type='client', resource='autoscaling', region=region, endpoint=ec2_url, **aws_connect_kwargs)
except ClientError as e:
module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response))
results = find_asgs(autoscaling, module, name=asg_name, tags=asg_tags) results = find_asgs(autoscaling, module, name=asg_name, tags=asg_tags)
module.exit_json(results=results) module.exit_json(results=results)

View file

@ -95,48 +95,25 @@ security_groups:
sample: sample:
''' '''
import traceback
try: try:
from botocore.exceptions import ClientError from botocore.exceptions import BotoCoreError, ClientError
except ImportError: except ImportError:
pass # caught by imported HAS_BOTO3 pass # caught by AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import (ec2_argument_spec, boto3_conn, HAS_BOTO3, get_aws_connection_info, from ansible.module_utils.ec2 import (boto3_tag_list_to_ansible_dict, ansible_dict_to_boto3_filter_list, camel_dict_to_snake_dict)
boto3_tag_list_to_ansible_dict, ansible_dict_to_boto3_filter_list,
camel_dict_to_snake_dict)
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( filters=dict(default={}, type='dict')
dict(
filters=dict(default={}, type='dict')
)
) )
module = AnsibleModule(argument_spec=argument_spec, module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True)
supports_check_mode=True)
if module._name == 'ec2_group_facts': if module._name == 'ec2_group_facts':
module.deprecate("The 'ec2_group_facts' module has been renamed to 'ec2_group_info'", version='2.13') module.deprecate("The 'ec2_group_facts' module has been renamed to 'ec2_group_info'", version='2.13')
if not HAS_BOTO3: connection = module.client('ec2')
module.fail_json(msg='boto3 required for this module')
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)
if region:
connection = boto3_conn(
module,
conn_type='client',
resource='ec2',
region=region,
endpoint=ec2_url,
**aws_connect_params
)
else:
module.fail_json(msg="region must be specified")
# Replace filter key underscores with dashes, for compatibility, except if we're dealing with tags # Replace filter key underscores with dashes, for compatibility, except if we're dealing with tags
sanitized_filters = module.params.get("filters") sanitized_filters = module.params.get("filters")
@ -148,8 +125,8 @@ def main():
security_groups = connection.describe_security_groups( security_groups = connection.describe_security_groups(
Filters=ansible_dict_to_boto3_filter_list(sanitized_filters) Filters=ansible_dict_to_boto3_filter_list(sanitized_filters)
) )
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg=e.message, exception=traceback.format_exc()) module.fail_json_aws(e, msg='Failed to describe security groups')
snaked_security_groups = [] snaked_security_groups = []
for security_group in security_groups['SecurityGroups']: for security_group in security_groups['SecurityGroups']:

View file

@ -181,12 +181,10 @@ import traceback
try: try:
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
except ImportError: except ImportError:
pass # Taken care of by ec2.HAS_BOTO3 pass # Handled by AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import (HAS_BOTO3, boto3_conn, boto_exception, ec2_argument_spec, from ansible.module_utils.ec2 import boto_exception, compare_policies, sort_json_policy_dict
get_aws_connection_info, compare_policies,
sort_json_policy_dict)
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
@ -205,15 +203,8 @@ def build_kwargs(registry_id):
class EcsEcr: class EcsEcr:
def __init__(self, module): def __init__(self, module):
region, ec2_url, aws_connect_kwargs = \ self.ecr = module.client('ecr')
get_aws_connection_info(module, boto3=True) self.sts = module.client('sts')
self.ecr = boto3_conn(module, conn_type='client',
resource='ecr', region=region,
endpoint=ec2_url, **aws_connect_kwargs)
self.sts = boto3_conn(module, conn_type='client',
resource='sts', region=region,
endpoint=ec2_url, **aws_connect_kwargs)
self.check_mode = module.check_mode self.check_mode = module.check_mode
self.changed = False self.changed = False
self.skipped = False self.skipped = False
@ -507,8 +498,7 @@ def run(ecr, params):
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update(dict(
name=dict(required=True), name=dict(required=True),
registry_id=dict(required=False), registry_id=dict(required=False),
state=dict(required=False, choices=['present', 'absent'], state=dict(required=False, choices=['present', 'absent'],
@ -517,23 +507,16 @@ def main():
policy=dict(required=False, type='json'), policy=dict(required=False, type='json'),
image_tag_mutability=dict(required=False, choices=['mutable', 'immutable'], image_tag_mutability=dict(required=False, choices=['mutable', 'immutable'],
default='mutable'), default='mutable'),
purge_policy=dict(required=False, type='bool', aliases=['delete_policy']), purge_policy=dict(required=False, type='bool', aliases=['delete_policy'],
deprecated_aliases=[dict(name='delete_policy', version='2.14')]),
lifecycle_policy=dict(required=False, type='json'), lifecycle_policy=dict(required=False, type='json'),
purge_lifecycle_policy=dict(required=False, type='bool'))) purge_lifecycle_policy=dict(required=False, type='bool')
)
mutually_exclusive = [
['policy', 'purge_policy'],
['lifecycle_policy', 'purge_lifecycle_policy']]
module = AnsibleModule(argument_spec=argument_spec, module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=mutually_exclusive)
supports_check_mode=True,
mutually_exclusive=[
['policy', 'purge_policy'],
['lifecycle_policy', 'purge_lifecycle_policy']])
if module.params.get('delete_policy'):
module.deprecate(
'The alias "delete_policy" has been deprecated and will be removed, '
'use "purge_policy" instead',
version='2.14')
if not HAS_BOTO3:
module.fail_json(msg='boto3 required for this module')
ecr = EcsEcr(module) ecr = EcsEcr(module)
passed, result = run(ecr, module.params) passed, result = run(ecr, module.params)

View file

@ -237,18 +237,15 @@ tags:
from time import sleep from time import sleep
from time import time as timestamp from time import time as timestamp
import traceback
try: try:
from botocore.exceptions import ClientError, BotoCoreError from botocore.exceptions import ClientError, BotoCoreError
except ImportError as e: except ImportError as e:
pass # Taken care of by ec2.HAS_BOTO3 pass # Handled by AnsibleAWSModule
from ansible.module_utils._text import to_native from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.ec2 import (compare_aws_tags, camel_dict_to_snake_dict,
from ansible.module_utils.ec2 import (HAS_BOTO3, boto3_conn, camel_dict_to_snake_dict, ansible_dict_to_boto3_tag_list, boto3_tag_list_to_ansible_dict)
ec2_argument_spec, get_aws_connection_info, ansible_dict_to_boto3_tag_list,
compare_aws_tags, boto3_tag_list_to_ansible_dict)
def _index_by_key(key, items): def _index_by_key(key, items):
@ -264,10 +261,9 @@ class EFSConnection(object):
STATE_DELETING = 'deleting' STATE_DELETING = 'deleting'
STATE_DELETED = 'deleted' STATE_DELETED = 'deleted'
def __init__(self, module, region, **aws_connect_params): def __init__(self, module):
self.connection = boto3_conn(module, conn_type='client', self.connection = module.client('efs')
resource='efs', region=region, region = module.region
**aws_connect_params)
self.module = module self.module = module
self.region = region self.region = region
@ -441,12 +437,8 @@ class EFSConnection(object):
try: try:
self.connection.create_file_system(**params) self.connection.create_file_system(**params)
changed = True changed = True
except ClientError as e: except (ClientError, BotoCoreError) as e:
self.module.fail_json(msg="Unable to create file system: {0}".format(to_native(e)), self.module.fail_json_aws(e, msg="Unable to create file system.")
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except BotoCoreError as e:
self.module.fail_json(msg="Unable to create file system: {0}".format(to_native(e)),
exception=traceback.format_exc())
# we always wait for the state to be available when creating. # we always wait for the state to be available when creating.
# if we try to take any actions on the file system before it's available # if we try to take any actions on the file system before it's available
@ -483,12 +475,8 @@ class EFSConnection(object):
try: try:
self.connection.update_file_system(FileSystemId=fs_id, **params) self.connection.update_file_system(FileSystemId=fs_id, **params)
changed = True changed = True
except ClientError as e: except (ClientError, BotoCoreError) as e:
self.module.fail_json(msg="Unable to update file system: {0}".format(to_native(e)), self.module.fail_json_aws(e, msg="Unable to update file system.")
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except BotoCoreError as e:
self.module.fail_json(msg="Unable to update file system: {0}".format(to_native(e)),
exception=traceback.format_exc())
return changed return changed
def converge_file_system(self, name, tags, purge_tags, targets, throughput_mode, provisioned_throughput_in_mibps): def converge_file_system(self, name, tags, purge_tags, targets, throughput_mode, provisioned_throughput_in_mibps):
@ -507,12 +495,8 @@ class EFSConnection(object):
FileSystemId=fs_id, FileSystemId=fs_id,
TagKeys=tags_to_delete TagKeys=tags_to_delete
) )
except ClientError as e: except (ClientError, BotoCoreError) as e:
self.module.fail_json(msg="Unable to delete tags: {0}".format(to_native(e)), self.module.fail_json_aws(e, msg="Unable to delete tags.")
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except BotoCoreError as e:
self.module.fail_json(msg="Unable to delete tags: {0}".format(to_native(e)),
exception=traceback.format_exc())
result = True result = True
@ -522,12 +506,8 @@ class EFSConnection(object):
FileSystemId=fs_id, FileSystemId=fs_id,
Tags=ansible_dict_to_boto3_tag_list(tags_need_modify) Tags=ansible_dict_to_boto3_tag_list(tags_need_modify)
) )
except ClientError as e: except (ClientError, BotoCoreError) as e:
self.module.fail_json(msg="Unable to create tags: {0}".format(to_native(e)), self.module.fail_json_aws(e, msg="Unable to create tags.")
exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except BotoCoreError as e:
self.module.fail_json(msg="Unable to create tags: {0}".format(to_native(e)),
exception=traceback.format_exc())
result = True result = True
@ -710,8 +690,7 @@ def main():
""" """
Module action handler Module action handler
""" """
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update(dict(
encrypt=dict(required=False, type="bool", default=False), encrypt=dict(required=False, type="bool", default=False),
state=dict(required=False, type='str', choices=["present", "absent"], default="present"), state=dict(required=False, type='str', choices=["present", "absent"], default="present"),
kms_key_id=dict(required=False, type='str', default=None), kms_key_id=dict(required=False, type='str', default=None),
@ -725,14 +704,11 @@ def main():
provisioned_throughput_in_mibps=dict(required=False, type='float'), provisioned_throughput_in_mibps=dict(required=False, type='float'),
wait=dict(required=False, type="bool", default=False), wait=dict(required=False, type="bool", default=False),
wait_timeout=dict(required=False, type="int", default=0) wait_timeout=dict(required=False, type="int", default=0)
)) )
module = AnsibleModule(argument_spec=argument_spec) module = AnsibleAWSModule(argument_spec=argument_spec)
if not HAS_BOTO3:
module.fail_json(msg='boto3 required for this module')
region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) connection = EFSConnection(module)
connection = EFSConnection(module, region, **aws_connect_params)
name = module.params.get('name') name = module.params.get('name')
fs_id = module.params.get('id') fs_id = module.params.get('id')

View file

@ -280,16 +280,14 @@ iam_roles:
''' '''
import re import re
import traceback
try: try:
from botocore.exception import ClientError from botocore.exception import BotoCoreError, ClientError
except ImportError: except ImportError:
pass # will be picked up from imported HAS_BOTO3 pass # caught by AnsibleAWSModule
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.ec2 import ec2_argument_spec, boto3_conn, get_aws_connection_info from ansible.module_utils.ec2 import camel_dict_to_snake_dict
from ansible.module_utils.ec2 import HAS_BOTO3, camel_dict_to_snake_dict
def match_tags(tags_to_match, cluster): def match_tags(tags_to_match, cluster):
@ -306,8 +304,8 @@ def find_clusters(conn, module, identifier=None, tags=None):
try: try:
cluster_paginator = conn.get_paginator('describe_clusters') cluster_paginator = conn.get_paginator('describe_clusters')
clusters = cluster_paginator.paginate().build_full_result() clusters = cluster_paginator.paginate().build_full_result()
except ClientError as e: except (BotoCoreError, ClientError) as e:
module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) module.fail_json_aws(e, msg='Failed to fetch clusters.')
matched_clusters = [] matched_clusters = []
@ -332,14 +330,11 @@ def find_clusters(conn, module, identifier=None, tags=None):
def main(): def main():
argument_spec = ec2_argument_spec() argument_spec = dict(
argument_spec.update( cluster_identifier=dict(type='str', aliases=['identifier', 'name']),
dict( tags=dict(type='dict')
cluster_identifier=dict(type='str', aliases=['identifier', 'name']),
tags=dict(type='dict')
)
) )
module = AnsibleModule( module = AnsibleAWSModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True supports_check_mode=True
) )
@ -349,14 +344,7 @@ def main():
cluster_identifier = module.params.get('cluster_identifier') cluster_identifier = module.params.get('cluster_identifier')
cluster_tags = module.params.get('tags') cluster_tags = module.params.get('tags')
if not HAS_BOTO3: redshift = module.client('redshift')
module.fail_json(msg='boto3 required for this module')
try:
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
redshift = boto3_conn(module, conn_type='client', resource='redshift', region=region, endpoint=ec2_url, **aws_connect_kwargs)
except ClientError as e:
module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
results = find_clusters(redshift, module, identifier=cluster_identifier, tags=cluster_tags) results = find_clusters(redshift, module, identifier=cluster_identifier, tags=cluster_tags)
module.exit_json(results=results) module.exit_json(results=results)