Reputation: 552
I created a AWS Lambda function to send alert mails(SNS) whenever a EC2 instance changes state, which works perfectly fine. I did this by creating a rule in cloudWatch to trigger my lambda function & it captures all the instance details and publishes SNS to send out mails.
Current Feature: 1. Triggering point - A change in instance state 2. Lambda triggered - Captures instance state (running/stopped) 3. Lambda publishes the SNS mail - Mail has instance state details (running/stopped) about all EC2 instances even the instance which state is not changed.
Required Feature: 1. Triggering point - A change in instance state 2. Lambda triggered - Captures instance state (running/stopped) 3. Lambda publishes the SNS mail - Mail should send instance state details (running/stopped) only about the ec2 instances which got changed.
Thanks in advance!
Lambda Code:
import boto3
import json
import logging
import datetime
import os
from botocore.exceptions import ClientError
from datetime import timedelta
region ='us-east-1'
ec2 = boto3.resource('ec2',region)
client = boto3.client('ec2',region)
snsClient = boto3.client('sns',region)
def lambda_handler(event, context):
global stop
global start
stop = ec2.instances.filter(Filters=[{'Name': 'instance-state-name', 'Values': ['stopped']}])
start = ec2.instances.filter(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
for instance1 in stop:
print('Ec2 Instances which are stopped: ', 'Instance ID: ', instance1.id, 'Instance state: ', instance1.state, 'Instance type: ',instance1.instance_type)
for instance2 in start:
print('Ec2 Instances which are running: ', 'Instance ID: ', instance2.id, 'Instance state: ', instance2.state, 'Instance type: ',instance2.instance_type)
publish_sns()
def publish_sns():
print('Publish Messsage to SNS Topic')
subject_str = 'Alert! EC2 Instances Started / Stopped'
affected_instances1 = [instance1.id for instance1 in stop]
affected_instances2 = [instance2.id for instance2 in start]
DT = datetime.datetime.now() + timedelta(hours = 5.5)
Waqt = DT.strftime("%Y-%m-%d %H:%M:%S")
msg = '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nHello Team, \n\nFollowing EC2 instances have been started / stopped: \n\nStopped instances: \n'+ str(affected_instances1)+ '\n\nStarted instances: \n'+str(affected_instances2)+'\n\nInstance state changed time IST: '+str(Waqt)+'\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'
response = snsClient.publish(TopicArn=os.environ['SNSARN'],Message=msg,Subject=subject_str)
Upvotes: 0
Views: 2270
Reputation: 21
Your lambda is invoked with two parameters - event & context - you should use event since it contains the information regarding the EC2 instance change instead of querying ec2.instance which will always return all the instances regardless to their state change.
Regardless to your implementation - What you are describing is to have the ability to know the previous state of all the instances and filtering the unchanged instances before emailing. You can save the entire array to a db and compare it back when your lambda is invoked by a state change.
Upvotes: 2