简体   繁体   English

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

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

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

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() ) .实际上,我编写的代码很匆忙,没有经过适当的测试(我也懒得修改 % 字符串格式并将其替换为 str.format() )。 In fact,using Filters parameter is not properly documented in AWS.事实上,AWS 中没有正确记录使用 Filters 参数。

Please refer to Russell Ballestrini blog Filtering AWS resources with Boto3 to 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.过滤器接受列表值,标签内的信息应该是 dict。 thus [{}]因此 [{}]
  2. Boto3 documentation is pretty ambiguous on how to use specify the tag name. Boto3 文档对于如何使用指定标签名称非常含糊。 It is confusing without examples when they say you may use tag:key.当他们说您可以使用 tag:key 时,没有示例会令人困惑。 So many people will just do [{"tag:keyname","Values": [""] }] and it doesn't work.很多人只会做[{"tag:keyname","Values": [""] }]而它不起作用。 (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":[""] }] .所以指定标签名称的正确方法是[{"Name" :"tag:keyname", "Values":[""] }] It is tricky.这很棘手。

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

Although not actually the answer to your question but DO NOT , NEVER , put your AWS credentials hard coded in your scripts.虽然实际上不是您问题的答案,但不要永远不要将您的 AWS 凭证硬编码到您的脚本中。 With your AWS credentials, anyone can use your account.凭借您的 AWS 凭证,任何人都可以使用您的账户。 There are bots scouring github and other git repositories looking for hard coded AWS credentials.有机器人在 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配置您的 ~/.aws/credentials 文件
  2. Use IAM Roles使用 IAM 角色
  3. Use STS to 'assumeRole'使用 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.确保 'Value' 是一个列表而不是一个字符串。 For example, if 'argEnv' is a string, make sure you use '[]' to encase your variable.例如,如果 '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 .您可以在此处查看响应语法。

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

Fix the Env and Role, as I am not sure mine or mootmoot's answer will work because the Array for Values expects strings.修复 Env 和 Role,因为我不确定我的或没有实际意义的答案是否有效,因为值数组需要字符串。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM