Shawn
Shawn

Reputation: 9402

Why does AWS boto3 call to associate_iam_instance_profile cause InvalidParameterValue for invalid name when the name is valid?

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

  1. Invoke iam_client.create_instance_profile to create a new instance profile
  2. Invoke iam_client.create_role to create a new role
  3. Invoke iam_client.attach_role_policy to attach an AWS-managed policy to the new role
  4. Invoke iam_client.add_role_to_instance_profile to add the new role to the instance profile
  5. Invoke ec2_client.associate_iam_instance_profile to associate the profile to an instance

But 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

Answers (2)

b.b3rn4rd
b.b3rn4rd

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

Shawn
Shawn

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

Related Questions