使用自定义标记名编写Boto3过滤器的正确方法是什么?

2024-05-23 13:57:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在不同标记键的标记值上列出实例 例如,一个标记键-环境,另一个标记键-角色。 我的代码如下:

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

Tags: instancesinpyenvapiforenvironmenttag
3条回答

在我自己的python脚本中,我使用以下命令:

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

这看起来很熟悉,我是不是为某个人修改过这个;-)。实际上,我编写的代码很仓促,没有经过正确的测试(而且我也懒得修改%string格式并用str.format()替换它)。事实上,使用Filters参数并没有在AWS中得到正确的记录。

请参阅Russell balletrini博客Filtering AWS resources with Boto3了解有关正确的boto过滤器方法的更多信息。

  1. 过滤器接受列表值,标签中的信息应该是dict
  2. Boto3文档在如何使用指定标记名方面非常模糊。当他们说您可以使用tag:key时,如果没有示例,会让人感到困惑。那么多人只会做[{"tag:keyname","Values": [""] }]而这行不通。(实际上,我假设开发人员知道过滤器是如何工作的,所以我只修改了结构)。
  3. 实际上,您必须显式地指定“Name”和“Values”对。因此,指定标记名的正确方法是[{"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');

虽然实际上不是问题的答案,但是不要将AWS凭证硬编码到脚本中。使用您的AWS凭据,任何人都可以使用您的帐户。有一些机器人正在搜索github和其他git存储库,寻找硬编码的AWS凭证。

另外,当轮换凭证时,所有代码都将被破坏,或者您将很难更新所有凭证。

一些替代方案代替硬编码您的AWS凭据:

  1. 配置~/.aws/credentials文件
  2. 使用IAM角色
  3. 使用STS“assumeRole”

遵循此处描述的最佳实践:Best Practices for Managing AWS Access Keys

现在,为了回答您的问题,下面是一个如何按标记筛选的示例:

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]
        }
    ]
)

确保'Value'是一个列表而不是一个字符串。例如,如果“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)

输出将是每个资源的名称标记的值。如您所见,您必须循环遍历结果以获得结果。您可以检查响应语法here

相关问题 更多 >