From 60080f25c0a46dfa4e9aa88c7c8bcb1498bbf58a Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 5 Feb 2021 09:43:09 +0100 Subject: [PATCH] Cleanup - use is_boto3_error_(message|code) (#268) * Reorder imports * Make use of is_boto3_error_message * Mass-migration over to is_boto3_error_code * Remove unused imports * unused vars in exception * Improve consistency around catching BotoCoreError and ClientError * Remove unused imports * Remove unused 'PolicyError' from iam_policy_info * Avoid catching botocore.exceptions.ClientError when we only want some error codes * Import camel_dict_to_snake_dict/snake_dict_to_camel_dict from ansible.module_utils.common.dict_transformations This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/4cf52ef67682fd4f9ed2a707adfbafffe7b88f15 --- plugins/modules/iam_role.py | 76 +++++++++++++++----------------- plugins/modules/iam_role_info.py | 15 ++++--- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/plugins/modules/iam_role.py b/plugins/modules/iam_role.py index 9a2eaca8cfe..ddc8ad23041 100644 --- a/plugins/modules/iam_role.py +++ b/plugins/modules/iam_role.py @@ -194,19 +194,21 @@ import json -from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict, compare_policies -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import (AWSRetry, - ansible_dict_to_boto3_tag_list, - boto3_tag_list_to_ansible_dict, - compare_aws_tags, - ) - try: - from botocore.exceptions import ClientError, BotoCoreError + import botocore except ImportError: pass # caught by AnsibleAWSModule +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + +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 AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list +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 compare_aws_tags +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import compare_policies + def compare_assume_role_policy_doc(current_policy_doc, new_policy_doc): if not compare_policies(current_policy_doc, json.loads(new_policy_doc)): @@ -242,7 +244,7 @@ def attach_policies(connection, module, policies_to_attach, params): try: if not module.check_mode: connection.attach_role_policy(RoleName=params['RoleName'], PolicyArn=policy_arn, aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to attach policy {0} to role {1}".format(policy_arn, params['RoleName'])) changed = True return changed @@ -254,7 +256,7 @@ def remove_policies(connection, module, policies_to_remove, params): try: if not module.check_mode: connection.detach_role_policy(RoleName=params['RoleName'], PolicyArn=policy, aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to detach policy {0} from {1}".format(policy, params['RoleName'])) changed = True return changed @@ -293,7 +295,7 @@ def create_basic_role(connection, module, params): else: role = {'MadeInCheckMode': True} role['AssumeRolePolicyDocument'] = json.loads(params['AssumeRolePolicyDocument']) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to create role") return role @@ -312,7 +314,7 @@ def update_role_assumed_policy(connection, module, params, role): RoleName=params['RoleName'], PolicyDocument=json.dumps(json.loads(params['AssumeRolePolicyDocument'])), aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to update assume role policy for role {0}".format(params['RoleName'])) return True @@ -329,7 +331,7 @@ def update_role_description(connection, module, params, role): try: connection.update_role_description(RoleName=params['RoleName'], Description=params['Description'], aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to update description for role {0}".format(params['RoleName'])) return True @@ -346,7 +348,7 @@ def update_role_max_session_duration(connection, module, params, role): try: connection.update_role(RoleName=params['RoleName'], MaxSessionDuration=params['MaxSessionDuration'], aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to update maximum session duration for role {0}".format(params['RoleName'])) return True @@ -364,12 +366,12 @@ def update_role_permissions_boundary(connection, module, params, role): if params.get('PermissionsBoundary') == '': try: connection.delete_role_permissions_boundary(RoleName=params['RoleName'], aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to remove permission boundary for role {0}".format(params['RoleName'])) else: try: connection.put_role_permissions_boundary(RoleName=params['RoleName'], PermissionsBoundary=params['PermissionsBoundary'], aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to update permission boundary for role {0}".format(params['RoleName'])) return True @@ -457,7 +459,7 @@ def create_instance_profiles(connection, module, params, role): # Fetch existing Profiles try: instance_profiles = connection.list_instance_profiles_for_role(RoleName=params['RoleName'], aws_retry=True)['InstanceProfiles'] - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to list instance profiles for role {0}".format(params['RoleName'])) # Profile already exists @@ -470,20 +472,17 @@ def create_instance_profiles(connection, module, params, role): # Make sure an instance profile is created try: connection.create_instance_profile(InstanceProfileName=params['RoleName'], Path=params['Path'], aws_retry=True) - except ClientError as e: + except is_boto3_error_code('EntityAlreadyExists'): # If the profile already exists, no problem, move on. # Implies someone's changing things at the same time... - if e.response['Error']['Code'] == 'EntityAlreadyExists': - return False - else: - module.fail_json_aws(e, msg="Unable to create instance profile for role {0}".format(params['RoleName'])) - except BotoCoreError as e: + return False + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Unable to create instance profile for role {0}".format(params['RoleName'])) # And attach the role to the profile try: connection.add_role_to_instance_profile(InstanceProfileName=params['RoleName'], RoleName=params['RoleName'], aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to attach role {0} to instance profile {0}".format(params['RoleName'])) return True @@ -495,7 +494,7 @@ def remove_instance_profiles(connection, module, role_params, role): try: instance_profiles = connection.list_instance_profiles_for_role(aws_retry=True, **role_params)['InstanceProfiles'] - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to list instance profiles for role {0}".format(role_name)) # Remove the role from the instance profile(s) @@ -508,9 +507,9 @@ def remove_instance_profiles(connection, module, role_params, role): if delete_profiles: try: connection.delete_instance_profile(InstanceProfileName=profile_name, aws_retry=True) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to remove instance profile {0}".format(profile_name)) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to remove role {0} from instance profile {1}".format(role_name, profile_name)) @@ -537,7 +536,7 @@ def destroy_role(connection, module): try: if not module.check_mode: connection.delete_role(aws_retry=True, **role_params) - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to delete role") module.exit_json(changed=True) @@ -546,26 +545,23 @@ def destroy_role(connection, module): def get_role_with_backoff(connection, module, name): try: return AWSRetry.jittered_backoff(catch_extra_error_codes=['NoSuchEntity'])(connection.get_role)(RoleName=name)['Role'] - except (BotoCoreError, ClientError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to get role {0}".format(name)) def get_role(connection, module, name): try: return connection.get_role(RoleName=name, aws_retry=True)['Role'] - except ClientError as e: - if e.response['Error']['Code'] == 'NoSuchEntity': - return None - else: - module.fail_json_aws(e, msg="Unable to get role {0}".format(name)) - except BotoCoreError as e: + except is_boto3_error_code('NoSuchEntity'): + return None + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Unable to get role {0}".format(name)) def get_attached_policy_list(connection, module, name): try: return connection.list_attached_role_policies(RoleName=name, aws_retry=True)['AttachedPolicies'] - except (ClientError, BotoCoreError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to list attached policies for role {0}".format(name)) @@ -575,7 +571,7 @@ def get_role_tags(connection, module): return {} try: return boto3_tag_list_to_ansible_dict(connection.list_role_tags(RoleName=role_name, aws_retry=True)['Tags']) - except (ClientError, BotoCoreError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to list tags for role {0}".format(role_name)) @@ -590,7 +586,7 @@ def update_role_tags(connection, module, params, role): try: existing_tags = boto3_tag_list_to_ansible_dict(connection.list_role_tags(RoleName=role_name, aws_retry=True)['Tags']) - except (ClientError, KeyError): + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError, KeyError): existing_tags = {} tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, new_tags, purge_tags=purge_tags) @@ -601,7 +597,7 @@ def update_role_tags(connection, module, params, role): connection.untag_role(RoleName=role_name, TagKeys=tags_to_remove, aws_retry=True) if tags_to_add: connection.tag_role(RoleName=role_name, Tags=ansible_dict_to_boto3_tag_list(tags_to_add), aws_retry=True) - except (ClientError, BotoCoreError) as e: + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to set tags for role %s' % role_name) changed = bool(tags_to_add) or bool(tags_to_remove) diff --git a/plugins/modules/iam_role_info.py b/plugins/modules/iam_role_info.py index 95eabdb95ab..132bdeedcc9 100644 --- a/plugins/modules/iam_role_info.py +++ b/plugins/modules/iam_role_info.py @@ -152,8 +152,12 @@ except ImportError: pass # caught by AnsibleAWSModule +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + 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, camel_dict_to_snake_dict, AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict @AWSRetry.exponential_backoff() @@ -208,12 +212,9 @@ def describe_iam_roles(module, client): if name: try: roles = [client.get_role(RoleName=name)['Role']] - except botocore.exceptions.ClientError as e: - if e.response['Error']['Code'] == 'NoSuchEntity': - return [] - else: - module.fail_json_aws(e, msg="Couldn't get IAM role %s" % name) - except botocore.exceptions.BotoCoreError as e: + except is_boto3_error_code('NoSuchEntity'): + return [] + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Couldn't get IAM role %s" % name) else: params = dict()