Почему вызов AWS boto3 для файла associate_iam_instance_profile вызывает значение InvalidParameterValue для недопустимого имени, если имя допустимо?

#amazon-web-services #aws-lambda #boto3

Вопрос:

У меня есть код, который вызывает API AWS boto3. Этот код выполняет несколько действий с использованием клиента iam и клиента ec2:

 iam_client = boto3.client('iam')
ec2_client = boto3.client('ec2')
 

Для всех этих вызовов имя роли и имя профиля совпадают: MyExampleName

  1. Вызов iam_client.create_instance_profile для создания нового профиля экземпляра
  2. Вызов iam_client.create_role для создания новой роли
  3. Вызовите iam_client.attach_role_policy , чтобы прикрепить политику, управляемую AWS, к новой роли
  4. Вызовите iam_client.add_role_to_instance_profile , чтобы добавить новую роль в профиль экземпляра
  5. Вызов ec2_client.associate_iam_instance_profile , чтобы связать профиль с экземпляром

Но последний вызов завершается ошибкой с таким сообщением, как это:

ИНФОРМАЦИЯ «НЕ УДАЛОСЬ: Произошла ошибка (значение InvalidParameterValue) при вызове операции AssociateIamInstanceProfile: Значение (MyExampleName) для параметра iamInstanceProfile.имя недопустимо. Неверное имя профиля экземпляра IAM, Идентификатор учетной записи: XXXXXXXXXXXXX, Ресурс: EC2 экземпляр: i-78sd976sd6912»

Я только что создал профиль, так как же получается, что вызов associate_iam_instance_profile говорит, что он недействителен?

Ответ №1:

Более удобным подходом было бы полагаться на boto3 официантов, специально созданных для того, чтобы ждать, пока появятся определенные ресурсы.

 waiter = client.get_waiter('instance_profile_exists')
waiter.wait(
    InstanceProfileName='string',
    WaiterConfig={
        'Delay': 123,
        'MaxAttempts': 123
    }
)
 

Проблема с вашим подходом заключается в том, что вы полагаетесь на предположение, что ресурс будет создан в течение 60 секунд, что может быть не всегда так. В то время как официанты продолжают опрашивать, пока ресурс не станет доступным.

Чтобы узнать больше о доступных официантах https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iam.html#IAM.Client.get_waiter

Комментарии:

1. Спасибо! Я попробовал это, но обнаружил, что официант возвращается, а последующий вызов клиента EC2 по- прежнему не удается. На шаге 1, когда я создаю профиль, я получаю ответ, содержащий ARN профиля. Я попытался добавить официанта между моими шагами 4 и 5, но вызов на шаге 5 с помощью клиента EC2 все равно не удался. Возможно, мне следует использовать официанта после шага 1 и до шага 4, но это, похоже, не помогает при вызове EC2 в #5. По-прежнему кажется, что это связано с использованием клиента EC2 в сочетании с клиентом IAM.

2. Кроме того, в примере в документации для create_instance_profile говорится: «Следующая команда создает профиль экземпляра с именем Webserver, который готов к присоединению роли, а затем будет связан с экземпляром EC2 «. Я делаю этот звонок, возвращаю ARN в ответе, затем пытаюсь связать его, но получаю ошибку. Похоже, что эта документация неверна-как будто она не сразу готова к связыванию с экземпляром EC2.

3. Я проголосовал, потому что это добавляет полезную информацию, которую все равно нужно учитывать, даже если это не решило мою проблему.

Ответ №2:

Существует небольшая проблема со временем использования как клиента IAM, так и клиента EC2. Профиль, созданный с помощью iam_client , может не сразу использоваться пользователем ec2_client . С некоторой логикой повторных попыток имя, похоже, в конечном итоге работает-на самом деле оно не является недействительным, оно просто еще не найдено:

 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!')
 

В следующих журналах показан реальный пример записей журнала, которые показывают, что клиент EC2 в конечном итоге соответствует клиенту IAM:

 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!"
 

Комментарии:

1. Я все равно поддерживаю это, так как вы на правильном пути