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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37293366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 19:11:59  来源:igfitidea点击:

What is the correct ways to write Boto3 filters to use customise tag name?

pythonamazon-web-servicesamazon-ec2instanceboto3

提问by Abhi

I am trying to list the instances on tag values of different tag keys For eg> one tag key - Environment, other tag key - Role. My code is given below :

我试图列出不同标签键的标签值的实例例如>一个标签键 - 环境,其他标签键 - 角色。我的代码如下:

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)

After running this script : python script.py arg1 arg2

运行此脚本后:python script.py arg1 arg2

I am getting following error

我收到以下错误

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

回答by mootmoot

This looks familiar, did I modify this for somebody somewhere ;-) . Actually the code I wrote is in rush and not tested properly (And I don't bother to amend the % string formating and replace it with str.format() ) . In fact,using Filters parameter is not properly documented in AWS.

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

Please refer to Russell Ballestrini blog Filtering AWS resources with Boto3to learn more about correct boto Filters method.

请参阅 Russell Ballestrini博客使用 Boto3 过滤 AWS 资源以了解有关正确 boto 过滤器方法的更多信息。

  1. Filters accept list value, and info inside the tag should be dict. thus [{}]
  2. Boto3 documentation is pretty ambiguous on how to use specify the tag name. It is confusing without examples when they say you may use tag:key. So many people will just do [{"tag:keyname","Values": [""] }]and it doesn't work. (Actually the origin code I assume the developer know how the filters works, so I just amend the structure only).
  3. Actually, You MUST explicitly specify "Name" and "Values" pair. So the correct way to specify tag name is [{"Name" :"tag:keyname", "Values":[""] }]. It is tricky.
  1. 过滤器接受列表值,标签内的信息应该是 dict。因此 [{}]
  2. Boto3 文档对于如何使用指定标签名称非常含糊。当他们说您可以使用 tag:key 时,没有示例会令人困惑。很多人会这样做[{"tag:keyname","Values": [""] }],但它不起作用。(实际上,我假设开发人员知道过滤器的工作原理是原始代码,所以我只是修改了结构)。
  3. 实际上,您必须明确指定“名称”和“值”对。所以指定标签名称的正确方法是[{"Name" :"tag:keyname", "Values":[""] }]. 这很棘手。

So the correct way of formatting a filters if you want to use for your example

因此,如果您想用于示例,则格式化过滤器的正确方法

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

(Update) And to make sure argparse take up string value, you just enforce the argument to take string values

(更新)并确保 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');

回答by Paulo Arag?o

Although not actually the answer to your question but DO NOT, NEVER, put your AWS credentials hard coded in your scripts. With your AWS credentials, anyonecan use your account. There are bots scouring github and other git repositories looking for hard coded AWS credentials.

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

Also, when rotating credentials all your code will be broken or you will have a hard time updating all of them.

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

Some alternatives instead hard coding your AWS credentials:

一些替代方案改为硬编码您的 AWS 凭证:

  1. Configure your ~/.aws/credentials file
  2. Use IAM Roles
  3. Use STS to 'assumeRole'
  1. 配置您的 ~/.aws/credentials 文件
  2. 使用 IAM 角色
  3. 使用 STS 来“承担角色”

Follow the best practices described here: Best Practices for Managing AWS Access Keys

遵循此处描述的最佳实践:管理 AWS 访问密钥的最佳实践

Now, for answering your question, here is an example on how to filter by tags:

现在,为了回答您的问题,这里有一个关于如何按标签过滤的示例:

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

Make sure 'Value' is a list and not a string. For example, if 'argEnv' is a string, make sure you use '[]' to encase your variable.

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

Then if you want to consult the Tag:Name and get the Value of it (for example, the name you set up for a specific EC2 instance in the console):

然后,如果您想查询 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)

The output will be the Value of the Name tag for every resource. As you can see, you have to loop through the results to get the result. You can check the Response Syntax here.

输出将是每个资源的名称标签的值。如您所见,您必须遍历结果才能获得结果。您可以在此处查看响应语法。

回答by A Bantly

In my own python script I use the following:

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

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

回答by Zeretil

Fix the Env and Role, as I am not sure mine or mootmoot's answer will work because the Array for Values expectsstrings.

修复 Env 和 Role,因为我不确定我的或没有实际意义的答案是否有效,因为值数组需要字符串。

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