2017-09-14 6 views
1

Pour donner suite à cette question: Filter CloudWatch Logs to extract Instance IDComment accéder à l'objet événement avec python dans AWS Lambda?

Je pense qu'il laisse la question incomplète parce qu'elle ne dit pas comment accéder à l'objet de l'événement avec python.

Mon but est de:

  • lu l'instance qui a été déclenchée par un changement d'état en cours d'exécution
  • obtenir une valeur d'étiquette associée à l'instance
  • départ toutes les autres instances qui ont la même étiquette

L'événement déclencheur CloudWatch est:

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

Je peux voir des exemples comme ceci:

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) 

je peux voir l'objet événement, mais je ne vois pas comment percer vers le bas dans la balise de l'instance qui l'avait changé en cours d'exécution est l'état.

S'il vous plaît, ce qui est l'objet d'attribut par lequel je peux obtenir une étiquette de l'instance déclenchée?

Je soupçonne que c'est quelque chose comme:

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

Répondre

0

Dans la section Détails de l'événement, vous obtiendrez l'instance id. En utilisant l'ID d'instance et AWS SDK, vous pouvez interroger les balises. L'exemple d'événement suivant est l'événement

{ 
    "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

Merci, Vaisakh. Cela aide beaucoup. Je vois l'objet d'événement et la section de détail, mais s'il vous plaît, comment obtient-on une balise spécifique, en utilisant python, pour cet ID d'instance. Est-ce un exercice d'analyse JSON? Ou cela peut-il être fait avec des attributs d'objet? La valeur de l'étiquette de l'instance ne semble pas figurer dans l'objet d'événement. Merci, Chris. – Chrisjx

0

Les données d'événement transmises à Lambda contiennent l'ID d'instance.

Vous devez ensuite appeler describe_tags() pour récupérer un dictionnaire des mots clés.

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

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

John, J'ai vu des références à l'objet client dans les documents boto3 mais je n'ai pas vu la méthode describe_tags. J'ai posté mon code de travail (peut-être pas le meilleur). Cela fonctionne rapidement bien qu'il génère une erreur lorsque je teste avec un ID d'instance inexistant. Je pense que c'est OK, car je ne vais probablement pas lancer une instance de la liste des instances qui n'existe pas. Nous allons en fait, je suppose qu'il pourrait être terminé, toujours dans la liste, et je l'ai accidentellement sélectionné. Tant pis. – Chrisjx

0

C'est ce que je suis venu avec ...

S'il vous plaît laissez-moi savoir comment il peut être fait mieux. Merci pour l'aide.

# 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)