web-dev-qa-db-ja.com

カスタムタグ名を使用するBoto3フィルターを記述する正しい方法は何ですか?

異なるタグキーのタグ値のインスタンスをリストしようとしています。たとえば、1つのタグキー-環境、他のタグキー-ロールです。私のコードは次のとおりです:

import argparse
import boto3

AWS_ACCESS_KEY_ID = '<Access Key>'
AWS_SECRET_ACCESS_KEY = '<Secret Key>'

def get_ec2_instances(Env,Role):
    ec2 = boto3.client("ec2", region)
    reservations = ec2.describe_instances(Filters={"tag:environment" :   Env, "tag:role" : Role})
    for reservation in reservations["Reservations"] :
        for instance in reservation["Instances"]:
             print  "%s" % (instance.tags['Name'])

if  __name__ == '__main__':

    regions = ['us-east-1','us-west-1','us-west-2','eu-west-1','sa-east-1',
               'ap-southeast-1','ap-southeast-2','ap-northeast-1']
    parser = argparse.ArgumentParser()
    parser.add_argument('Env', default="environment", help='value for   tag:environment');
    parser.add_argument('Role', default="role", help='value for tag:role');
    args = parser.parse_args()

    for region in regions: get_ec2_instances(args.Env, args.Role)

このスクリプトを実行した後:python script.py arg1 arg2

次のエラーが発生しています

Traceback (most recent call last):
  File "script.py", line 27, in <module>
    for region in regions: get_ec2_instances(args.Env, args.Role)
  File "script.py", line 10, in get_ec2_instances
    reservations = ec2.describe_instances(Filters={"tag:environment" :  Env, "tag:role" : Role})
  File "/usr/local/lib/python2.7/dist-packages/botocore/client.py", line 258, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/usr/local/lib/python2.7/dist-packages/botocore/client.py", line 524, in _make_api_call
    api_params, operation_model, context=request_context)
  File "/usr/local/lib/python2.7/dist-packages/botocore/client.py", line 577, in _convert_to_request_dict
    api_params, operation_model)
  File "/usr/local/lib/python2.7/dist-packages/botocore/validate.py", line 270, in serialize_to_request
    raise ParamValidationError(report=report.generate_report())
botocore.exceptions.ParamValidationError: Parameter validation failed:
Invalid type for parameter Filters, value: {'tag:role': 'arg1', 'tag:environment': 'arg2'}, type: <type 'dict'>, valid types: <type 'list'>, <type 'Tuple'>
11
Abhi

これはおなじみのようですが、誰かのためにこれを変更しましたか;-)。実際、私が書いたコードはRushにあり、適切にテストされていません(そして、文字列の書式設定を修正してstr.format()に置き換えることはありません)。実際、AWSではFiltersパラメーターの使用が適切に文書化されていません。

Russell Ballestriniブログ Boto3によるAWSリソースのフィルタリング を参照して、正しいboto Filtersメソッドの詳細をご覧ください。

  1. フィルターはリストの値を受け入れ、タグ内の情報はdictである必要があります。したがって、[{}]
  2. Boto3のドキュメントでは、タグ名の指定方法についてかなり曖昧です。 tag:keyを使用するかもしれないと彼らが言うとき、それは例なしで混乱しています。多くの人が[{"tag:keyname","Values": [""] }]そしてそれは動作しません。 (実際には、Originコードは、フィルターがどのように機能するかを開発者が知っていると想定しているため、構造のみを修正します).
  3. 実際には、「名前」と「値」のペアを明示的に指定する必要があります。したがって、タグ名を指定する正しい方法は[{"Name" :"tag:keyname", "Values":[""] }]。トリッキーです。

したがって、あなたの例に使用したい場合、フィルターをフォーマットする正しい方法

filters = [{'Name':'tag:environment', 'Values':[Env]},
           {'Name':'tag:role', 'Values':[Role]}
          ]

(更新)そして、argparseが文字列値を取るようにするには、引数を強制して文字列値を取るだけです

parser.add_argument('Env', type=str, default="environment",
                    help='value for   tag:environment');
parser.add_argument('Role', type=str,default="role",
                    help='value for tag:role');
20
mootmoot

私自身のpythonスクリプトでは、以下を使用します。

import boto3
ec2client = boto3.client('ec2','us-east-1')
response = ec2client.describe_instances(Filters=[{'Name' : 'instance-state-name','Values' : ['running']}])
3
A Bantly

実際にはあなたの質問に対する答えではなく、DO NOT[〜#〜] never [〜#〜] 、スクリプトにハードコードされたAWS認証情報を入力します。 AWS認証情報を使用すると、anyoneがアカウントを使用できます。 githubなどのgitリポジトリを探して、ハードコードされたAWS認証情報を探しているボットがあります。

また、資格情報をローテーションすると、すべてのコードが破損するか、すべてのコードを更新するのに苦労します。

代わりに、AWS認証情報をハードコーディングするいくつかの選択肢:

  1. 〜/ .aws/credentialsファイルを構成します
  2. IAMロールを使用する
  3. STSを使用して「assumeRole」

ここで説明するベストプラクティスに従います。 AWSアクセスキーを管理するためのベストプラクティス

ここで、質問に答えるために、タグでフィルタリングする方法の例を示します。

argEnv = '<any_string_you_want_to_match_as_a_value_for_a_tag>'
ec2Client = boto3.client('ec2')
response = ec2Client.describe_instances(
    Filters=[
            {
                'Name': 'tag:Projeto',
                'Values': [argEnv]
        }
    ]
)

「値」が文字列ではなくリストであることを確認してください。たとえば、「argEnv」が文字列の場合、「[]」を使用して変数を入れてください。

次に、Tag:Nameを参照してその値(たとえば、コンソールで特定のEC2インスタンスに設定した名前)を取得する場合:

for reservation in res['Reservations']:
    for instance in reservation['Instances']:
        for tag in instance['Tags']:
            if tag['Key'] == 'Name':
                consoleName = tag['Value']
print(consoleName)

出力は、すべてのリソースの名前タグの値になります。ご覧のとおり、結果を取得するには結果をループする必要があります。 Response Syntax here を確認できます。

0
Paulo Aragão