如何使用AWS Lambda中的python访问事件对象?

问题描述:

要跟进这个问题: Filter CloudWatch Logs to extract Instance ID如何使用AWS Lambda中的python访问事件对象?

我认为它留下的问题不完整的,因为它并没有说如何使用Python访问事件对象。

我的目标是:

  • 读取被改变运行状态
  • 获得与实例
  • 开始具有相同标记的所有其他实例相关联的标签值触发实例

的CloudWatch的触发事件是:

{ 
    "source": [ 
    "aws.ec2" 
    ], 
    "detail-type": [ 
    "EC2 Instance State-change Notification" 
    ], 
    "detail": { 
    "state": [ 
     "running" 
    ] 
    } 
} 

,我可以看到的例子是这样的:

def lambda_handler(event, context): 

    # here I want to get the instance tag value 
    # and set the tag filter based on the instance that 
    # triggered the event 

    filters = [{ 
      'Name': 'tag:StartGroup', 
      'Values': ['startgroup1'] 
     }, 
     { 
      'Name': 'instance-state-name', 
      'Values': ['running'] 
     } 
    ] 

    instances = ec2.instances.filter(Filters=filters) 

我可以看到事件对象,但我不知道如何深入到这有它的状态转变为运行实例的标签。

请问,通过哪些对象属性可以从触发实例中获取标签?

我怀疑它是这样的:

myTag = event.details.instance-id.tags["startgroup1"] 

在事件的细节部分,你会得到的实例ID的。使用实例ID和AWS SDK您可以查询标签。以下是示例事件

{ 
    "version": "0", 
    "id": "ee376907-2647-4179-9203-343cfb3017a4", 
    "detail-type": "EC2 Instance State-change Notification", 
    "source": "aws.ec2", 
    "account": "123456789012", 
    "time": "2015-11-11T21:30:34Z", 
    "region": "us-east-1", 
    "resources": [ 
    "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111" 
    ], 
    "detail": { 
    "instance-id": "i-abcd1111", 
    "state": "running" 
    } 
} 
+0

谢谢,Vaisakh。 这实际上有很大帮助。我看到事件对象和详细信息部分,但是,请问,如何使用python为此实例标识获取特定标记。 这是一个json解析练习吗?或者这可以通过对象属性来完成吗? 实例的标记值看起来不在事件对象中。 谢谢, 克里斯。 – Chrisjx

传递给Lambda的事件数据包含实例ID。您需要致电describe_tags()以检索标签字典。

import boto3 
client = boto3.client('ec2') 

client.describe_tags(Filters=[ 
     { 
      'Name': 'resource-id', 
      'Values': [ 
       event['detail']['instance-id'] 
      ] 
     } 
    ] 
) 
+0

John, 我在boto3文档中看到了对客户端对象的引用,但没有看到describe_tags方法。 我已经发布了我的工作(也许不是最好的)代码。它工作的很快,但是当我用一个不存在的实例id进行测试时它会抛出一个错误。我认为这很好,因为我可能不会从不存在的实例列表中启动实例。实际上,我想它可能会被终止,仍在列表中,并且我意外地选择了它。好吧。 – Chrisjx

这是我想出了...

请让我知道如何可以做得更好。谢谢您的帮助。

# StartMeUp_Instances_byOne 
# 
# This lambda script is triggered by a CloudWatch Event, startGroupByInstance. 
# Every evening a separate lambda script is launched on a schedule to stop 
# all non-essential instances. 
# 
# This script will turn on all instances with a LaunchGroup tag that matches 
# a single instance which has been changed to the running state. 
# 
# To start all instances in a LaunchGroup, 
# start one of the instances in the LaunchGroup and wait about 5 minutes. 
# 
# Costs to run: approx. $0.02/month 
# https://s3.amazonaws.com/lambda-tools/pricing-calculator.html 
# 150 executions per month * 128 MB Memory * 60000 ms Execution Time 
# 
# Problems: talk to chrisj 
# ====================================== 

# test system 
# this is what the event object looks like (see below) 
# it is configured in the test event object with a specific instance-id 
# change that to test a different instance-id with a different LaunchGroup 

# { "version": "0", 
# "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
# "detail-type": "EC2 Instance State-change Notification", 
# "source": "aws.ec2", 
# "account": "999999999999999", 
# "time": "2015-11-11T21:30:34Z", 
# "region": "us-east-1", 
# "resources": [ 
#  "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111" 
# ], 
# "detail": { 
#  "instance-id": "i-0aad9474", # <---------- chg this 
#  "state": "running" 
# } 
# } 
# ====================================== 

import boto3 
import logging 
import json 

ec2 = boto3.resource('ec2') 

def get_instance_LaunchGroup(iid): 
    # When given an instance ID as str e.g. 'i-1234567', 
    # return the instance LaunchGroup. 
    ec2 = boto3.resource('ec2') 
    ec2instance = ec2.Instance(iid) 
    thisTag = '' 
    for tags in ec2instance.tags: 
     if tags["Key"] == 'LaunchGroup': 
      thisTag = tags["Value"] 
    return thisTag 

# this is the entry point for the cloudwatch trigger 
def lambda_handler(event, context): 

    # get the instance id that triggered the event 
    thisInstanceID = event['detail']['instance-id'] 
    print("instance-id: " + thisInstanceID) 

    # get the LaunchGroup tag value of the thisInstanceID 
    thisLaunchGroup = get_instance_LaunchGroup(thisInstanceID) 
    print("LaunchGroup: " + thisLaunchGroup) 
    if thisLaunchGroup == '': 
     print("No LaunchGroup associated with this InstanceID - ending lambda function") 
     return 

    # set the filters 
    filters = [{ 
      'Name': 'tag:LaunchGroup', 
      'Values': [thisLaunchGroup] 
     }, 
     { 
      'Name': 'instance-state-name', 
      'Values': ['stopped'] 
     } 
    ] 

    # get the instances based on the filter, thisLaunchGroup and stopped 
    instances = ec2.instances.filter(Filters=filters) 

    # get the stopped instance IDs 
    stoppedInstances = [instance.id for instance in instances] 

    # make sure there are some instances not already started 
    if len(stoppedInstances) > 0: 
     startingUp = ec2.instances.filter(InstanceIds=stoppedInstances).start() 

    print ("Finished launching all instances for tag: " + thisLaunchGroup)