Skip to content

Commit

Permalink
Use module.fail_json_aws and is_boto3_error_code to simplify error ha…
Browse files Browse the repository at this point in the history
…ndling
  • Loading branch information
tremble committed Apr 26, 2020
1 parent 45043bd commit 4157273
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 105 deletions.
17 changes: 7 additions & 10 deletions plugins/modules/cloudformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ def create_stack(module, stack_params, cfn, events_limit):
# Use stack ID to follow stack state in case of on_create_failure = DELETE
result = stack_operation(cfn, response['StackId'], 'CREATE', events_limit, stack_params.get('ClientRequestToken', None))
except Exception as err:
error_msg = boto_exception(err)
module.fail_json(msg="Failed to create stack {0}: {1}.".format(stack_params.get('StackName'), error_msg), exception=traceback.format_exc())
module.fail_json_aws(err, msg="Failed to create stack {0}".format(stack_params.get('StackName')))
if not result:
module.fail_json(msg="empty result")
return result
Expand Down Expand Up @@ -440,8 +439,7 @@ def create_changeset(module, stack_params, cfn, events_limit):
try:
newcs = cfn.describe_change_set(ChangeSetName=cs['Id'])
except botocore.exceptions.BotoCoreError as err:
error_msg = boto_exception(err)
module.fail_json(msg=error_msg)
module.fail_json_aws(err)
if newcs['Status'] == 'CREATE_PENDING' or newcs['Status'] == 'CREATE_IN_PROGRESS':
time.sleep(1)
elif newcs['Status'] == 'FAILED' and "The submitted information didn't contain changes" in newcs['StatusReason']:
Expand All @@ -465,7 +463,7 @@ def create_changeset(module, stack_params, cfn, events_limit):
if 'No updates are to be performed.' in error_msg:
result = dict(changed=False, output='Stack is already up-to-date.')
else:
module.fail_json(msg="Failed to create change set: {0}".format(error_msg), exception=traceback.format_exc())
module.fail_json_aws(err, msg='Failed to create change set')

if not result:
module.fail_json(msg="empty result")
Expand All @@ -487,7 +485,7 @@ def update_stack(module, stack_params, cfn, events_limit):
if 'No updates are to be performed.' in error_msg:
result = dict(changed=False, output='Stack is already up-to-date.')
else:
module.fail_json(msg="Failed to update stack {0}: {1}".format(stack_params.get('StackName'), error_msg), exception=traceback.format_exc())
module.fail_json_aws(err, msg="Failed to update stack {0}".format(stack_params.get('StackName')))
if not result:
module.fail_json(msg="empty result")
return result
Expand All @@ -505,7 +503,7 @@ def update_termination_protection(module, cfn, stack_name, desired_termination_p
EnableTerminationProtection=desired_termination_protection_state,
StackName=stack_name)
except botocore.exceptions.ClientError as e:
module.fail_json(msg=boto_exception(e), exception=traceback.format_exc())
module.fail_json_aws(e)


def boto_supports_termination_protection(cfn):
Expand Down Expand Up @@ -601,8 +599,7 @@ def check_mode_changeset(module, stack_params, cfn):
return {'changed': True, 'msg': reason, 'meta': description['Changes']}

except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as err:
error_msg = boto_exception(err)
module.fail_json(msg=error_msg, exception=traceback.format_exc())
module.fail_json_aws(err)


def get_stack_facts(cfn, stack_name):
Expand Down Expand Up @@ -805,7 +802,7 @@ def main():
result = stack_operation(cfn, stack_params['StackName'], 'DELETE', module.params.get('events_limit'),
stack_params.get('ClientRequestToken', None))
except Exception as err:
module.fail_json(msg=boto_exception(err), exception=traceback.format_exc())
module.fail_json_aws(err)

module.exit_json(**result)

Expand Down
22 changes: 10 additions & 12 deletions plugins/modules/ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,6 @@

import time
import datetime
import traceback
from ast import literal_eval
from distutils.version import LooseVersion

Expand Down Expand Up @@ -1045,7 +1044,7 @@ def create_instances(module, ec2, vpc, override_count=None):
grp_details = ec2.get_all_security_groups(group_ids=group_id)
group_name = [grp_item.name for grp_item in grp_details]
except boto.exception.NoAuthHandlerFound as e:
module.fail_json(msg=str(e))
module.fail_json_aws(e, msg='Unable to authenticate to AWS')

# Lookup any instances that much our run id.

Expand Down Expand Up @@ -1186,11 +1185,11 @@ def create_instances(module, ec2, vpc, override_count=None):
ec2.get_all_instances(instids)
break
except boto.exception.EC2ResponseError as e:
if "<Code>InvalidInstanceID.NotFound</Code>" in str(e):
if e.error_code == 'InvalidInstanceID.NotFound'
# there's a race between start and get an instance
continue
else:
module.fail_json(msg=str(e))
module.fail_json_aws(e)

# The instances returned through ec2.run_instances above can be in
# terminated state due to idempotency. See commit 7f11c3d for a complete
Expand Down Expand Up @@ -1243,7 +1242,7 @@ def create_instances(module, ec2, vpc, override_count=None):
else:
instids = []
except boto.exception.BotoServerError as e:
module.fail_json(msg="Instance creation failed => %s: %s" % (e.error_code, e.error_message))
module.fail_json_aws(e, msg='Instance creation failed')

# wait here until the instances are up
num_running = 0
Expand Down Expand Up @@ -1295,7 +1294,7 @@ def create_instances(module, ec2, vpc, override_count=None):
try:
ec2.create_tags(instids, instance_tags)
except boto.exception.EC2ResponseError as e:
module.fail_json(msg="Instance tagging failed => %s: %s" % (e.error_code, e.error_message))
module.fail_json_aws(e, msg='Instance tagging failed')

instance_dict_array = []
created_instance_ids = []
Expand Down Expand Up @@ -1344,7 +1343,7 @@ def terminate_instances(module, ec2, instance_ids):
try:
ec2.terminate_instances([inst.id])
except EC2ResponseError as e:
module.fail_json(msg='Unable to terminate instance {0}, error: {1}'.format(inst.id, e))
module.fail_json_aws(e, msg='Unable to terminate instance {0}'.format(inst.id))
changed = True

# wait here until the instances are 'terminated'
Expand Down Expand Up @@ -1460,7 +1459,7 @@ def startstop_instances(module, ec2, instance_ids, state, instance_tags):
else:
inst.stop()
except EC2ResponseError as e:
module.fail_json(msg='Unable to change state for instance {0}, error: {1}'.format(inst.id, e))
module.fail_json_aws(e, 'Unable to change state for instance {0}'.format(inst.id))
changed = True
existing_instances_array.append(inst.id)

Expand Down Expand Up @@ -1546,7 +1545,7 @@ def restart_instances(module, ec2, instance_ids, state, instance_tags):
try:
inst.reboot()
except EC2ResponseError as e:
module.fail_json(msg='Unable to change state for instance {0}, error: {1}'.format(inst.id, e))
module.fail_json_aws(e, msg='Unable to change state for instance {0}'.format(inst.id))
changed = True

return (changed, instance_dict_array, instance_ids)
Expand Down Expand Up @@ -1596,8 +1595,7 @@ def check_source_dest_attr(module, inst, ec2):
ec2.modify_network_interface_attribute(interface.id, "sourceDestCheck", source_dest_check)
return True
else:
module.fail_json(msg='Failed to handle source_dest_check state for instance {0}, error: {1}'.format(inst.id, exc),
exception=traceback.format_exc())
module.fail_json_aws(exc, msg='Failed to handle source_dest_check state for instance {0}'.format(inst.id))


def warn_if_public_ip_assignment_changed(module, instance):
Expand Down Expand Up @@ -1688,7 +1686,7 @@ def main():

vpc = connect_vpc(**aws_connect_kwargs)
except boto.exception.NoAuthHandlerFound as e:
module.fail_json(msg="Failed to get connection: %s" % e.message, exception=traceback.format_exc())
module.fail_json_aws(e, msg='Failed to get connection')

tagged_instances = []

Expand Down
17 changes: 8 additions & 9 deletions plugins/modules/ec2_elb_lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@

import random
import time
import traceback

try:
import boto
Expand Down Expand Up @@ -405,7 +404,7 @@ def _get_vpc_connection(module, region, aws_connect_params):
try:
return connect_to_aws(boto.vpc, region, **aws_connect_params)
except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e:
module.fail_json(msg=str(e))
module.fail_json_aws(e, 'Failed to connect to AWS')


_THROTTLING_RETRIES = 5
Expand Down Expand Up @@ -456,7 +455,7 @@ def __init__(self, module, name, listeners=None, purge_listeners=None,
try:
self.elb = self._get_elb()
except boto.exception.BotoServerError as e:
module.fail_json(msg='unable to get all load balancers: %s' % e.message, exception=traceback.format_exc())
module.fail_json_aws(e, msg='Unable to get all load balancers')

self.ec2_conn = self._get_ec2_connection()

Expand Down Expand Up @@ -656,7 +655,7 @@ def _wait_for_elb_interface_removed(self):
status_achieved = True
break
else:
self.module.fail_json(msg=to_native(e), exception=traceback.format_exc())
self.module.fail_json_aws(e, 'Failure while waiting for interface to be removed')

return status_achieved

Expand All @@ -673,14 +672,14 @@ def _get_elb_connection(self):
return connect_to_aws(boto.ec2.elb, self.region,
**self.aws_connect_params)
except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e:
self.module.fail_json(msg=str(e))
self.module.fail_json_aws(e, 'Failure while connecting to AWS')

def _get_ec2_connection(self):
try:
return connect_to_aws(boto.ec2, self.region,
**self.aws_connect_params)
except (boto.exception.NoAuthHandlerFound, Exception) as e:
self.module.fail_json(msg=to_native(e), exception=traceback.format_exc())
self.module.fail_json_aws(e, 'Failure while connecting to AWS')

@_throttleable_operation(_THROTTLING_RETRIES)
def _delete_elb(self):
Expand Down Expand Up @@ -817,15 +816,15 @@ def _enable_zones(self, zones):
try:
self.elb.enable_zones(zones)
except boto.exception.BotoServerError as e:
self.module.fail_json(msg='unable to enable zones: %s' % e.message, exception=traceback.format_exc())
self.module.fail_json_aws(e, msg='unable to enable zones')

self.changed = True

def _disable_zones(self, zones):
try:
self.elb.disable_zones(zones)
except boto.exception.BotoServerError as e:
self.module.fail_json(msg='unable to disable zones: %s' % e.message, exception=traceback.format_exc())
self.module.fail_json_aws(e, msg='unable to disable zones')
self.changed = True

def _attach_subnets(self, subnets):
Expand Down Expand Up @@ -1312,7 +1311,7 @@ def main():
group_id = [str(grp.id) for grp in grp_details if str(grp.name) in group_name]
security_group_ids.extend(group_id)
except boto.exception.NoAuthHandlerFound as e:
module.fail_json(msg=str(e))
module.fail_json_aws(e)

elb_man = ElbManager(module, name, listeners, purge_listeners, zones,
purge_zones, security_group_ids, health_check,
Expand Down
12 changes: 6 additions & 6 deletions plugins/modules/ec2_eni.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ def create_eni(connection, vpc_id, module):
changed = True

except BotoServerError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e)

module.exit_json(changed=changed, interface=get_eni_info(eni))

Expand Down Expand Up @@ -449,7 +449,7 @@ def modify_eni(connection, vpc_id, module, eni):
detach_eni(eni, module)

except BotoServerError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e)

eni.update()
module.exit_json(changed=changed, interface=get_eni_info(eni))
Expand Down Expand Up @@ -482,7 +482,7 @@ def delete_eni(connection, module):
if regex.search(e.message) is not None:
module.exit_json(changed=False)
else:
module.fail_json(msg=e.message)
module.fail_json_aws(e)


def detach_eni(eni, module):
Expand Down Expand Up @@ -535,7 +535,7 @@ def uniquely_find_eni(connection, module):
return None

except BotoServerError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e)

return None

Expand All @@ -555,7 +555,7 @@ def _get_vpc_id(connection, module, subnet_id):
try:
return connection.get_all_subnets(subnet_ids=[subnet_id])[0].vpc_id
except BotoServerError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e)


def main():
Expand Down Expand Up @@ -601,7 +601,7 @@ def main():
connection = connect_to_aws(boto.ec2, region, **aws_connect_params)
vpc_connection = connect_to_aws(boto.vpc, region, **aws_connect_params)
except (boto.exception.NoAuthHandlerFound, AnsibleAWSError) as e:
module.fail_json(msg=str(e))
module.fail_json_aws(e)
else:
module.fail_json(msg="region must be specified")

Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ec2_eni_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def list_eni(connection, module):
try:
network_interfaces_result = connection.describe_network_interfaces(Filters=filters)['NetworkInterfaces']
except (ClientError, NoCredentialsError) as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e)

# Modify boto3 tags list to be ansible friendly dict and then camel_case
camel_network_interfaces = []
Expand Down
8 changes: 4 additions & 4 deletions plugins/modules/ec2_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def create_snapshot(module, ec2, state=None, description=None, wait=None,
try:
volumes = ec2.get_all_volumes(filters={'attachment.instance-id': instance_id, 'attachment.device': device_name})
except boto.exception.BotoServerError as e:
module.fail_json(msg="%s: %s" % (e.error_code, e.error_message))
module.fail_json_aws(e)

if not volumes:
module.fail_json(msg="Could not find volume with name %s attached to instance %s" % (device_name, instance_id))
Expand All @@ -237,7 +237,7 @@ def create_snapshot(module, ec2, state=None, description=None, wait=None,
if e.error_code == 'InvalidSnapshot.NotFound':
module.exit_json(changed=False)
else:
module.fail_json(msg="%s: %s" % (e.error_code, e.error_message))
module.fail_json_aws(e)

# successful delete
module.exit_json(changed=True)
Expand All @@ -246,7 +246,7 @@ def create_snapshot(module, ec2, state=None, description=None, wait=None,
try:
current_snapshots = ec2.get_all_snapshots(filters={'volume_id': volume_id})
except boto.exception.BotoServerError as e:
module.fail_json(msg="%s: %s" % (e.error_code, e.error_message))
module.fail_json_aws(e)

last_snapshot_min_age = last_snapshot_min_age * 60 # Convert to seconds
snapshot = _get_most_recent_snapshot(current_snapshots,
Expand All @@ -263,7 +263,7 @@ def create_snapshot(module, ec2, state=None, description=None, wait=None,
for k, v in snapshot_tags.items():
snapshot.add_tag(k, v)
except boto.exception.BotoServerError as e:
module.fail_json(msg="%s: %s" % (e.error_code, e.error_message))
module.fail_json_aws(e)

module.exit_json(changed=changed,
snapshot_id=snapshot.id,
Expand Down
11 changes: 5 additions & 6 deletions plugins/modules/ec2_snapshot_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,12 @@ def list_ec2_snapshots(connection, module):

try:
snapshots = connection.describe_snapshots(SnapshotIds=snapshot_ids, OwnerIds=owner_ids, RestorableByUserIds=restorable_by_user_ids, Filters=filters)
except is_boto3_error_code('InvalidSnapshot.NotFound') as e:
if len(snapshot_ids) > 1:
module.warn("Some of your snapshots may exist, but %s" % str(e))
snapshots = {'Snapshots': []}
except ClientError as e:
if e.response['Error']['Code'] == "InvalidSnapshot.NotFound":
if len(snapshot_ids) > 1:
module.warn("Some of your snapshots may exist, but %s" % str(e))
snapshots = {'Snapshots': []}
else:
module.fail_json(msg="Failed to describe snapshots: %s" % str(e))
module.fail_json_aws(e, msg='Failed to describe snapshots')

# Turn the boto3 result in to ansible_friendly_snaked_names
snaked_snapshots = []
Expand Down
Loading

0 comments on commit 4157273

Please sign in to comment.