Skip to content

Commit

Permalink
Python 3 compatibility error handling: use to_native(e) instead of st…
Browse files Browse the repository at this point in the history
…r(e) or e.me… (ansible-collections#26)

* Py3 compat error handling: use to_native(e) instead of str(e) or e.message
* PR comment changes, use fail_json_aws and is_boto3_error_code
  • Loading branch information
veloutin authored Aug 15, 2020
1 parent 75fdfbf commit 4999441
Show file tree
Hide file tree
Showing 20 changed files with 104 additions and 103 deletions.
7 changes: 3 additions & 4 deletions plugins/modules/dynamodb_ttl.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@

from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info


Expand Down Expand Up @@ -157,11 +156,11 @@ def main():
result['current_status'] = current_state

except botocore.exceptions.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 get or update ttl state")
except botocore.exceptions.ParamValidationError as e:
module.fail_json(msg=e.message, exception=traceback.format_exc())
module.fail_json_aws(e, msg="Failed due to invalid parameters")
except ValueError as e:
module.fail_json(msg=str(e))
module.fail_json_aws(e, msg="Failed")

module.exit_json(**result)

Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ec2_customer_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def __init__(self, module):
module.fail_json(msg="Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file")
self.ec2 = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs)
except ClientError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e, msg="Failed to get connection")

@AWSRetry.jittered_backoff(delay=2, max_delay=30, retries=6, catch_extra_error_codes=['IncorrectState'])
def ensure_cgw_absent(self, gw_id):
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ec2_instance_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ def list_ec2_instances(connection, module):
reservations_paginator = connection.get_paginator('describe_instances')
reservations = reservations_paginator.paginate(InstanceIds=instance_ids, Filters=filters).build_full_result()
except 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 list ec2 instances")

# Get instances from reservations
instances = []
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ec2_lc_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def list_launch_configs(connection, module):
pg = connection.get_paginator('describe_launch_configurations')
launch_configs = pg.paginate(LaunchConfigurationNames=launch_config_name).build_full_result()
except ClientError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e, msg="Failed to list launch configs")

snaked_launch_configs = []
for launch_config in launch_configs['LaunchConfigurations']:
Expand Down
38 changes: 17 additions & 21 deletions plugins/modules/ec2_vpc_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,10 @@
pass # Handled by AnsibleAWSModule

from ansible.module_utils.six import string_types
from ansible.module_utils._text import to_native

from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict
Expand Down Expand Up @@ -289,19 +291,15 @@ def create_vpc_endpoint(client, module):
status_achieved, result = wait_for_status(client, module, result['vpc_endpoint_id'], 'available')
if not status_achieved:
module.fail_json(msg='Error waiting for vpc endpoint to become available - please check the AWS console')
except botocore.exceptions.ClientError as e:
if "DryRunOperation" in e.message:
changed = True
result = 'Would have created VPC Endpoint if not in check mode'
elif "IdempotentParameterMismatch" in e.message:
module.fail_json(msg="IdempotentParameterMismatch - updates of endpoints are not allowed by the API")
elif "RouteAlreadyExists" in e.message:
module.fail_json(msg="RouteAlreadyExists for one of the route tables - update is not allowed by the API")
else:
module.fail_json(msg=str(e), exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response))
except is_boto3_error_code('DryRunOperation'):
changed = True
result = 'Would have created VPC Endpoint if not in check mode'
except is_boto3_error_code('IdempotentParameterMismatch'): # pylint: disable=duplicate-except
module.fail_json(msg="IdempotentParameterMismatch - updates of endpoints are not allowed by the API")
except is_boto3_error_code('RouteAlreadyExists'): # pylint: disable=duplicate-except
module.fail_json(msg="RouteAlreadyExists for one of the route tables - update is not allowed by the API")
except Exception as e:
module.fail_json(msg=str(e), exception=traceback.format_exc(),
module.fail_json(msg=to_native(e), exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response))

return changed, result
Expand All @@ -319,15 +317,13 @@ def setup_removal(client, module):
result = client.delete_vpc_endpoints(**params)['Unsuccessful']
if not module.check_mode and (result != []):
module.fail_json(msg=result)
except botocore.exceptions.ClientError as e:
if "DryRunOperation" in e.message:
changed = True
result = 'Would have deleted VPC Endpoint if not in check mode'
else:
module.fail_json(msg=str(e), exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response))
except is_boto3_error_code('DryRunOperation'):
changed = True
result = 'Would have deleted VPC Endpoint if not in check mode'
except botocore.exceptions.ClientError as e: # pylint: disable=duplicate-except
module.fail_json_aws(e, "Failed to delete VPC endpoint")
except Exception as e:
module.fail_json(msg=str(e), exception=traceback.format_exc(),
module.fail_json(msg=to_native(e), exception=traceback.format_exc(),
**camel_dict_to_snake_dict(e.response))
return changed, result

Expand Down Expand Up @@ -362,7 +358,7 @@ def main():
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
except NameError as e:
# Getting around the get_aws_connection_info boto reliance for region
if "global name 'boto' is not defined" in e.message:
if "global name 'boto' is not defined" in to_native(e):
module.params['region'] = botocore.session.get_session().get_config_variable('region')
if not module.params['region']:
module.fail_json(msg="Error - no region provided")
Expand Down
3 changes: 2 additions & 1 deletion plugins/modules/ec2_vpc_endpoint_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
except ImportError:
pass # Handled by AnsibleAWSModule

from ansible.module_utils._text import to_native
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info
Expand Down Expand Up @@ -156,7 +157,7 @@ def get_endpoints(client, module):
try:
results = json.loads(json.dumps(results, default=date_handler))
except Exception as e:
module.fail_json(msg=str(e.message))
module.fail_json_aws(e, msg="Failed to get endpoints")
return dict(vpc_endpoints=[camel_dict_to_snake_dict(result) for result in results])


Expand Down
18 changes: 11 additions & 7 deletions plugins/modules/ec2_vpc_nat_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,9 @@
except ImportError:
pass # Handled by AnsibleAWSModule

from ansible.module_utils._text import to_native
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict
Expand Down Expand Up @@ -698,13 +700,15 @@ def create(client, subnet_id, allocation_id, client_token=None,
'NAT gateway {0} created'.format(result['nat_gateway_id'])
)

except botocore.exceptions.ClientError as e:
if "IdempotentParameterMismatch" in e.message:
err_msg = (
'NAT Gateway does not support update and token has already been provided: ' + str(e)
)
else:
err_msg = str(e)
except is_boto3_error_code('IdempotentParameterMismatch'):
err_msg = (
'NAT Gateway does not support update and token has already been provided: ' + err_msg
)
success = False
changed = False
result = None
except botocore.exceptions.ClientError as e: # pylint: disable=duplicate-except
err_msg = to_native(e)
success = False
changed = False
result = None
Expand Down
3 changes: 2 additions & 1 deletion plugins/modules/ec2_vpc_nat_gateway_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
except ImportError:
pass # Handled by AnsibleAWSModule

from ansible.module_utils._text import to_native
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
Expand All @@ -105,7 +106,7 @@ def get_nat_gateways(client, module, nat_gateway_id=None):
try:
result = json.loads(json.dumps(client.describe_nat_gateways(**params), default=date_handler))
except Exception as e:
module.fail_json(msg=str(e.message))
module.fail_json(msg=to_native(e))

for gateway in result['NatGateways']:
# Turn the boto3 result into ansible_friendly_snaked_names
Expand Down
5 changes: 3 additions & 2 deletions plugins/modules/ec2_vpc_peering_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
except ImportError:
pass # Handled by AnsibleAWSModule

from ansible.module_utils._text import to_native
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
Expand All @@ -94,7 +95,7 @@ def get_vpc_peers(client, module):
try:
result = json.loads(json.dumps(client.describe_vpc_peering_connections(**params), default=date_handler))
except Exception as e:
module.fail_json(msg=str(e.message))
module.fail_json(msg=to_native(e))

return result['VpcPeeringConnections']

Expand All @@ -114,7 +115,7 @@ def main():
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
except NameError as e:
# Getting around the get_aws_connection_info boto reliance for region
if "global name 'boto' is not defined" in e.message:
if "global name 'boto' is not defined" in to_native(e):
module.params['region'] = botocore.session.get_session().get_config_variable('region')
if not module.params['region']:
module.fail_json(msg="Error - no region provided")
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ec2_vpc_route_table_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def list_ec2_vpc_route_tables(connection, module):
try:
all_route_tables = connection.get_all_route_tables(filters=filters)
except BotoServerError as e:
module.fail_json(msg=e.message)
module.fail_json_aws(e, msg="Failed to get route tables")

for route_table in all_route_tables:
route_table_dict_array.append(get_route_table_info(route_table))
Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/ecs_taskdefinition.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def register_task(self, family, task_role_arn, execution_role_arn, network_mode,
try:
response = self.ecs.register_task_definition(**params)
except botocore.exceptions.ClientError as e:
self.module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response))
self.module.fail_json_aws(e, msg="Failed to register task")

return response['taskDefinition']

Expand Down
15 changes: 5 additions & 10 deletions plugins/modules/elasticache.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,7 @@ def create(self):
self.conn.create_cache_cluster(**kwargs)

except botocore.exceptions.ClientError as e:
self.module.fail_json(msg=e.message, exception=format_exc(),
**camel_dict_to_snake_dict(e.response))
self.module.fail_json_aws(e, msg="Failed to create cache cluster")

self._refresh_data()

Expand All @@ -255,8 +254,7 @@ def delete(self):
try:
response = self.conn.delete_cache_cluster(CacheClusterId=self.name)
except botocore.exceptions.ClientError as e:
self.module.fail_json(msg=e.message, exception=format_exc(),
**camel_dict_to_snake_dict(e.response))
self.module.fail_json_aws(e, msg="Failed to delete cache cluster")

cache_cluster_data = response['CacheCluster']
self._refresh_data(cache_cluster_data)
Expand Down Expand Up @@ -306,8 +304,7 @@ def modify(self):
ApplyImmediately=True,
EngineVersion=self.cache_engine_version)
except botocore.exceptions.ClientError as e:
self.module.fail_json(msg=e.message, exception=format_exc(),
**camel_dict_to_snake_dict(e.response))
self.module.fail_json_aws(e, msg="Failed to modify cache cluster")

self._refresh_data()

Expand Down Expand Up @@ -335,8 +332,7 @@ def reboot(self):
self.conn.reboot_cache_cluster(CacheClusterId=self.name,
CacheNodeIdsToReboot=cache_node_ids)
except botocore.exceptions.ClientError as e:
self.module.fail_json(msg=e.message, exception=format_exc(),
**camel_dict_to_snake_dict(e.response))
self.module.fail_json_aws(e, msg="Failed to reboot cache cluster")

self._refresh_data()

Expand Down Expand Up @@ -455,8 +451,7 @@ def _refresh_data(self, cache_cluster_data=None):
self.status = 'gone'
return
else:
self.module.fail_json(msg=e.message, exception=format_exc(),
**camel_dict_to_snake_dict(e.response))
self.module.fail_json_aws(e, msg="Failed to describe cache clusters")
cache_cluster_data = response['CacheClusters'][0]
self.data = cache_cluster_data
self.status = self.data['CacheClusterStatus']
Expand Down
3 changes: 2 additions & 1 deletion plugins/modules/elasticache_subnet_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
except ImportError:
pass # Handled by HAS_BOTO

from ansible.module_utils._text import to_native
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import HAS_BOTO
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import get_aws_connection_info
Expand Down Expand Up @@ -105,7 +106,7 @@ def main():
try:
conn = connect_to_region(region_name=region, **aws_connect_kwargs)
except boto.exception.NoAuthHandlerFound as e:
module.fail_json(msg=e.message)
module.fail_json(msg=to_native(e))

try:
changed = False
Expand Down
21 changes: 11 additions & 10 deletions plugins/modules/elb_application_lb_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@
except ImportError:
pass # Handled by AnsibleAWSModule

from ansible.module_utils._text import to_native
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_conn
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict
Expand All @@ -182,23 +184,23 @@ def get_elb_listeners(connection, module, elb_arn):
try:
return connection.describe_listeners(LoadBalancerArn=elb_arn)['Listeners']
except 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 describe elb listeners")


def get_listener_rules(connection, module, listener_arn):

try:
return connection.describe_rules(ListenerArn=listener_arn)['Rules']
except 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 describe listener rules")


def get_load_balancer_attributes(connection, module, load_balancer_arn):

try:
load_balancer_attributes = boto3_tag_list_to_ansible_dict(connection.describe_load_balancer_attributes(LoadBalancerArn=load_balancer_arn)['Attributes'])
except 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 describe load balancer attributes")

# Replace '.' with '_' in attribute key names to make it more Ansibley
for k, v in list(load_balancer_attributes.items()):
Expand All @@ -213,7 +215,7 @@ def get_load_balancer_tags(connection, module, load_balancer_arn):
try:
return boto3_tag_list_to_ansible_dict(connection.describe_tags(ResourceArns=[load_balancer_arn])['TagDescriptions'][0]['Tags'])
except 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 describe load balancer tags")


def list_load_balancers(connection, module):
Expand All @@ -229,13 +231,12 @@ def list_load_balancers(connection, module):
load_balancers = load_balancer_paginator.paginate(LoadBalancerArns=load_balancer_arns).build_full_result()
if names:
load_balancers = load_balancer_paginator.paginate(Names=names).build_full_result()
except ClientError as e:
if e.response['Error']['Code'] == 'LoadBalancerNotFound':
module.exit_json(load_balancers=[])
else:
module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
except is_boto3_error_code('LoadBalancerNotFound'):
module.exit_json(load_balancers=[])
except ClientError as e: # pylint: disable=duplicate-except
module.fail_json_aws(e, msg="Failed to list load balancers")
except NoCredentialsError as e:
module.fail_json(msg="AWS authentication problem. " + e.message, exception=traceback.format_exc())
module.fail_json(msg="AWS authentication problem. " + to_native(e), exception=traceback.format_exc())

for load_balancer in load_balancers['LoadBalancers']:
# Get the attributes for each elb
Expand Down
6 changes: 3 additions & 3 deletions plugins/modules/elb_classic_lb.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,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(msg='unable to get all load balancers: %s' % to_native(e), exception=traceback.format_exc())

self.ec2_conn = self._get_ec2_connection()

Expand Down Expand Up @@ -820,15 +820,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(msg='unable to enable zones: %s' % to_native(e), exception=traceback.format_exc())

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(msg='unable to disable zones: %s' % to_native(e), exception=traceback.format_exc())
self.changed = True

def _attach_subnets(self, subnets):
Expand Down
Loading

0 comments on commit 4999441

Please sign in to comment.