编写 Boto3 过滤器以使用自定义标签名称的正确方法是啥?

Posted

技术标签:

【中文标题】编写 Boto3 过滤器以使用自定义标签名称的正确方法是啥?【英文标题】:What is the correct ways to write Boto3 filters to use customise tag name?编写 Boto3 过滤器以使用自定义标签名称的正确方法是什么? 【发布时间】:2016-09-14 13:42:54 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

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

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

一些替代方法是硬编码您的 AWS 凭证:

    配置您的 ~/.aws/credentials 文件 使用 IAM 角色 使用 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]
        
    ]
)

确保“值”是一个列表而不是字符串。例如,如果 'argEnv' 是一个字符串,请确保使用 '[]' 来封装变量。

那么,如果您想查询 Tag:Name 并获取它的 Value(例如,您在控制台中为特定 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。

【讨论】:

在第二个代码 sn-p 中,“res”是从哪里来的?它是第一个代码示例中的“响应”吗?【参考方案2】:

这看起来很熟悉,我是不是在某个地方为某人修改了这个 ;-) 。实际上我写的代码很匆忙,没有正确测试(而且我懒得修改 % 字符串格式并用 str.format() 替换它)。事实上,AWS 中没有正确记录使用 Filters 参数。

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

    过滤器接受列表值,标签内的信息应该是字典。因此 [] Boto3 文档对于如何使用指定标签名称非常含糊。当他们说您可以使用 tag:key 时,没有示例会令人困惑。很多人只会做["tag:keyname","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');

【讨论】:

【参考方案3】:

在我自己的 python 脚本中,我使用以下内容:

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

【讨论】:

【参考方案4】:

修复环境和角色,因为我不确定我的或 mootmoot 的答案是否有效,因为值数组 expects 字符串。

reservervations = ec2.describe_instances(
        Filters=[
           'Name': 'tag:environment', 'Values': ['%s'], 'Name': 'tag:role', 'Values': ['%s'] % (Env, Role),
        ]]
    ).get(
        'Reservations', []
    )  

【讨论】:

以上是关于编写 Boto3 过滤器以使用自定义标签名称的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Django自定义模板标签和过滤器

django 编写我的第一个自定义模板标签和过滤器

BOTO3:如何过滤标签“不相等”的实例?

如何编写自定义排序器以在 UI 中按名称对 springdoc swagger 标签进行排序?

在 Django 中自定义模板标签以过滤博客中的特色帖子

如何使用 ArrayAdapter 为 ListView 编写自定义过滤器