summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan S. Brown <sb@ryansb.com>2018-04-13 16:28:50 -0400
committerRyan S. Brown <sb@ryansb.com>2018-04-13 16:28:50 -0400
commitf1ee3f8c0033a892d892e781880107ecb81c3117 (patch)
treef6239ee65669cc1a329cb8432ec15be487e7aca4
parent53a3b8b602610dbf4428ea532a097dc467fcf181 (diff)
downloadansible-ec2_instance_role_switching.tar.gz
[cloud] Add support for updating IAM role with ec2_instance moduleec2_instance_role_switching
-rw-r--r--lib/ansible/modules/cloud/amazon/ec2_instance.py47
1 files changed, 45 insertions, 2 deletions
diff --git a/lib/ansible/modules/cloud/amazon/ec2_instance.py b/lib/ansible/modules/cloud/amazon/ec2_instance.py
index 9437afee4a..86c2e7cb1e 100644
--- a/lib/ansible/modules/cloud/amazon/ec2_instance.py
+++ b/lib/ansible/modules/cloud/amazon/ec2_instance.py
@@ -737,6 +737,47 @@ def build_volume_spec(params):
return [ec2_utils.snake_dict_to_camel_dict(v, capitalize_first=True) for v in volumes]
+def add_or_update_instance_profile(instance, desired_profile_name):
+ instance_profile_setting = instance.get('IamInstanceProfile')
+ if instance_profile_setting and desired_profile_name:
+ if desired_profile_name in (instance_profile_setting.get('Name'), instance_profile_setting.get('Arn')):
+ # great, the profile we asked for is what's there
+ return False
+ else:
+ desired_arn = determine_iam_role(desired_profile_name)
+ if instance_profile_setting.get('Arn') == desired_arn:
+ return False
+ # update association
+ ec2 = module.client('ec2')
+ try:
+ association = ec2.describe_iam_instance_profile_associations(Filters=[{'Name': 'instance-id', 'Values': [instance['InstanceId']]}])
+ except botocore.exceptions.ClientError as e:
+ # check for InvalidAssociationID.NotFound
+ module.fail_json_aws(e, "Could not find instance profile association")
+ try:
+ resp = ec2.replace_iam_instance_profile_association(
+ AssociationId=association['IamInstanceProfileAssociations'][0]['AssociationId'],
+ IamInstanceProfile={'Arn': determine_iam_role(desired_profile_name)}
+ )
+ return True
+ except botocore.exceptions.ClientError as e:
+ module.fail_json_aws(e, "Could not associate instance profile")
+
+ if not instance_profile_setting and desired_profile_name:
+ # create association
+ ec2 = module.client('ec2')
+ try:
+ resp = ec2.associate_iam_instance_profile(
+ IamInstanceProfile={'Arn': determine_iam_role(desired_profile_name)},
+ InstanceId=instance['InstanceId']
+ )
+ return True
+ except botocore.exceptions.ClientError as e:
+ module.fail_json_aws(e, "Could not associate new instance profile")
+
+ return False
+
+
def build_network_spec(params, ec2=None):
"""
Returns list of interfaces [complex]
@@ -1292,9 +1333,9 @@ def pretty_instance(i):
def determine_iam_role(name_or_arn):
if re.match(r'^arn:aws:iam::\d+:instance-profile/[\w+=/,.@-]+$', name_or_arn):
return name_or_arn
- iam = module.client('iam')
+ iam = module.client('iam', retry_decorator=AWSRetry.jittered_backoff())
try:
- role = iam.get_instance_profile(InstanceProfileName=name_or_arn)
+ role = iam.get_instance_profile(InstanceProfileName=name_or_arn, aws_retry=True)
return role['InstanceProfile']['Arn']
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == 'NoSuchEntity':
@@ -1313,6 +1354,8 @@ def handle_existing(existing_matches, changed, ec2, state):
changes = diff_instance_and_params(existing_matches[0], module.params)
for c in changes:
ec2.modify_instance_attribute(**c)
+ changed |= bool(changes)
+ changed |= add_or_update_instance_profile(existing_matches[0], module.params.get('instance_role'))
changed |= change_network_attachments(existing_matches[0], module.params, ec2)
altered = find_instances(ec2, ids=[i['InstanceId'] for i in existing_matches])
module.exit_json(