Reputation: 9402
I have code that is calling AWS boto3 APIs. This code does several things using an iam client and an ec2 client:
iam_client = boto3.client('iam')
ec2_client = boto3.client('ec2')
For all of these calls the role name and the profile name are the same: MyExampleName
iam_client.create_instance_profile
to create a new instance profileiam_client.create_role
to create a new roleiam_client.attach_role_policy
to attach an AWS-managed policy to the new roleiam_client.add_role_to_instance_profile
to add the new role to the instance profileec2_client.associate_iam_instance_profile
to associate the profile to an instanceBut the last call is failing with a message such as this:
INFO "FAILED: An error occurred (InvalidParameterValue) when calling the AssociateIamInstanceProfile operation: Value (MyExampleName) for parameter iamInstanceProfile.name is invalid. Invalid IAM Instance Profile name, Account Id: XXXXXXXXXXXXX, Resource: EC2 instance: i-78sd976sd6912"
I just created the profile, so how is it that the call to associate_iam_instance_profile is saying it is invalid?
Upvotes: 1
Views: 877
Reputation: 8830
The more convenient approach would be to rely on boto3
waiters purposely built do wait for certain resources to become available.
waiter = client.get_waiter('instance_profile_exists')
waiter.wait(
InstanceProfileName='string',
WaiterConfig={
'Delay': 123,
'MaxAttempts': 123
}
)
The problem with your approach, is that you're relying on a assumption that a resource will get created within 60 seconds, that might not be always the case. While waiters are keep polling until a resource becomes available.
To read more about available waiters https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iam.html#IAM.Client.get_waiter
Upvotes: 1
Reputation: 9402
There is a bit of a timing issue using both the IAM client and the EC2 client. The profile created via the iam_client
may not immediately be usable by the ec2_client
. With some retry logic, the name seems to eventually work--it isn't really invalid, it just isn't found yet:
import time
logger.info('Attaching profile: MyExampleName'))
counter = 0
while counter < 60:
try:
ec2_client.associate_iam_instance_profile(IamInstanceProfile={'Name': 'MyExampleName'},
InstanceId='i-78sd976sd6912')
break
except ClientError as err:
if err.response['Error']['Code'] == 'InvalidParameterValue':
counter = counter + 1
logger.info('The ec2 client did not find the profile yet; wait 1 second and then try again')
time.sleep(1)
logger.info('Finally worked!')
The following logs show a real-world sample of log entries that show the EC2 client is eventually consistent with the IAM client:
INFO "Attaching profile: MyExampleName"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "The profile is not found yet; wait 1 second and then try again"
INFO "Finally worked!"
Upvotes: 2