Last active
November 14, 2020 20:50
-
-
Save ljmocic/f9c122fd6f75ffa38fae3fc6badd0b4f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import boto3 | |
import json | |
from datetime import datetime, timedelta | |
REGION = 'us-east-1' | |
TAG = 'A' | |
ARN = 'arn:aws:sns:us-east-1:12345678:snsName' | |
UTILIZATION_PERCENTAGE = 0.5 | |
TIME = 60 * 60 * 2 | |
# if you are testing set to 1, if you want script to shut them down, set to 0 | |
TEST_MODE = 1 | |
ec2 = boto3.resource('ec2', region_name=REGION) | |
cloudwatch = boto3.client('cloudwatch', region_name=REGION) | |
sns = boto3.client('sns', region_name=REGION) | |
def notify(content): | |
message = {"log": content} | |
print(content) | |
''' | |
sns.publish( | |
TargetArn=ARN, | |
Message=json.dumps({'default': json.dumps(message)}), | |
MessageStructure='json' | |
) | |
''' | |
def get_tag_value(all_tags, temp_tag): | |
for tag in all_tags: | |
if tag['Key'] == temp_tag: | |
return tag['Value'] | |
def get_instance_name(instance): | |
for tag in instance.tags: | |
if 'Name'in tag['Key']: | |
return tag['Value'] | |
return 'empty_instance_name' | |
def get_avg_utilization(instance_id): | |
response = cloudwatch.get_metric_statistics( | |
Namespace='AWS/EC2', | |
MetricName='CPUUtilization', | |
Dimensions=[ | |
{ | |
'Name': 'InstanceId', | |
'Value': instance_id | |
}, | |
], | |
StartTime=datetime.utcnow() - timedelta(seconds=TIME), | |
EndTime=datetime.utcnow(), | |
Period=TIME, | |
Statistics=[ | |
'Average', | |
], | |
Unit='Percent' | |
) | |
for cpu in response['Datapoints']: | |
if 'Average' in cpu: | |
return float(cpu['Average']) | |
def get_group_shutdown_status(instances_from_tag_value): | |
no_of_idle = 0 | |
for instance in instances_from_tag_value: | |
utilization = get_avg_utilization(instance.id) | |
print('[INFO] Instance: ' + get_tag_value(instance.tags, TAG) + ':' + get_instance_name(instance) + ':' + instance.id + ' has been active with ' + str(round(utilization, 2)) + '% CPU utilization.') | |
if utilization < UTILIZATION_PERCENTAGE: | |
no_of_idle += 1 | |
# If all of them are idle, set the signal for shutdown | |
if no_of_idle == len(instances_from_tag_value): | |
return True | |
else: | |
return False | |
def get_instance_ids(instances): | |
instance_ids = [] | |
for instance in instances: | |
instance_ids.append(instance.id) | |
return instance_ids | |
def stop_instances(instance_ids): | |
if TEST_MODE == 1: | |
for id in instance_ids: | |
print('[INFO] Shutting down instance: ' + TAG + ':' + id) | |
elif TEST_MODE == 0: | |
ec2.instances.filter(InstanceIds=instance_ids).stop() | |
def lambda_handler(event, context): | |
instances_map = {} | |
response = '' | |
filter = [ | |
{ | |
'Name': 'tag-key', | |
'Values': [TAG] | |
}, | |
{ | |
'Name': 'instance-state-name', | |
'Values': ['running'] | |
} | |
] | |
# Group instances by tag_value, which in this case are users | |
groupingtag_instances = ec2.instances.filter(Filters=filter) | |
ins_count = 0 | |
for ins in groupingtag_instances: | |
ins_count += 1 | |
if ins_count == 0: | |
response += ('TAG: ' + TAG + ' instances has not been found.') | |
else: | |
response += ('Found ' + str(ins_count) + ' with ' + TAG + '.') | |
for instance in groupingtag_instances: | |
tag_value = get_tag_value(ec2.Instance(instance.id).tags, TAG) | |
print('[INFO] Found instance: ' + TAG + ':' + get_tag_value(instance.tags, TAG) + ':' + get_instance_name(instance) + ':' + instance.id) | |
if tag_value != None: | |
if tag_value not in instances_map: | |
instances_map[tag_value] = [] | |
instances_map[tag_value].append(instance) | |
print(instances_map) | |
# Check for every group for shutdown and send the signal for shutdown if needed | |
for tag_value in instances_map: | |
shutdown_status = get_group_shutdown_status(instances_map[tag_value]) | |
if shutdown_status == True: | |
instance_ids = get_instance_ids(instances_map[tag_value]) | |
stop_instances(instance_ids) | |
response += (TAG + ' : ' + tag_value + ' is idle. Will be shutdown.\n') | |
else: | |
response += (TAG + ' : ' + tag_value + ' is busy. Will not shut down.\n') | |
notify(response) | |
return 'Success' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, thanks for sharing,
I tried this class with a role with lambda permissions to EC2, SNS, and cloudwatch but it did not seem to print anything on the logs neither shut the instances. Is there anything I'm missing?
Let me know