Skip to content

Commit

Permalink
Cleanup - use is_boto3_error_(message|code) (ansible-collections#268)
Browse files Browse the repository at this point in the history
* 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: ansible-collections@4cf52ef
  • Loading branch information
tremble authored and alinabuzachis committed Oct 6, 2023
1 parent 1fd6420 commit 60080f2
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 47 deletions.
76 changes: 36 additions & 40 deletions plugins/modules/iam_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)):
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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))


Expand All @@ -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)
Expand All @@ -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))


Expand All @@ -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))


Expand All @@ -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)
Expand All @@ -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)
Expand Down
15 changes: 8 additions & 7 deletions plugins/modules/iam_role_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 60080f2

Please sign in to comment.