Commit 0168d33e authored by A-Gordon's avatar A-Gordon

Lambda function to tidy up stale Packer instances

parents
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
\ No newline at end of file
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:TerminateInstances",
"Resource": "*"
}
]
}
\ No newline at end of file
resource "aws_iam_role" "packer_janitor" {
name = "iam_packer_janitor"
assume_role_policy = "${file("${path.module}/assume-role.json")}"
}
resource "aws_iam_policy" "packer_janitor" {
name = "packer_janitor"
policy = "${file("${path.module}/iam-policy.json")}"
}
resource "aws_iam_role_policy_attachment" "packer_janitor" {
role = "${aws_iam_role.packer_janitor.name}"
policy_arn = "${aws_iam_policy.packer_janitor.arn}"
}
resource "aws_lambda_function" "packer_janitor" {
filename = "${path.module}/packer_janitor.zip"
function_name = "packer_janitor"
role = "${aws_iam_role.packer_janitor.arn}"
handler = "packer_janitor.lambda_handler"
timeout = "300"
runtime = "python2.7"
source_code_hash = "${base64sha256(file("${path.module}/packer_janitor.zip"))}"
}
variable "cloudwatch_schedule" {
description = "Schedule for cloudwatch event to invoke Lambda function"
default = "cron(*/2 * ? * * *)"
}
resource "aws_cloudwatch_event_rule" "packer_janitor" {
name = "packer_janitor"
description = "Run packer janitor to tidy up stale packer instances."
schedule_expression = "${var.cloudwatch_schedule}"
}
resource "aws_cloudwatch_event_target" "packer_janitor" {
rule = "${aws_cloudwatch_event_rule.packer_janitor.name}"
arn = "${aws_lambda_function.packer_janitor.arn}"
}
resource "aws_lambda_permission" "allow_cloudwatch" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.packer_janitor.arn}"
principal = "events.amazonaws.com"
}
\ No newline at end of file
import boto3
import datetime
import logging
import sys
from dateutil.parser import *
from datetime import timedelta
"""
This function lists all stale packer instances and terminates them.
"""
# Define the Tag of the packer instances
PACKER_TAG = 'Packer Builder'
REGION = 'eu-west-1'
DRYRUN = False
# Define the Connection
ec2 = boto3.resource('ec2', region_name=REGION)
date = datetime.datetime.now()
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.info('Packer Tag: %s', PACKER_TAG)
def lambda_handler (event, context):
logger.info('Starting scan for instances')
instances = ec2.instances.filter(Filters=[
{'Name': 'tag:Name', 'Values': [PACKER_TAG]},
{'Name': 'instance-state-name', 'Values': ['running']},
])
for instance in instances:
instance_tags = tags_dict(instance.tags)
instance_launch_time = instance.launch_time
logger.info('Found New Instance, ID: [%s]', instance.id)
logger.info('[%s]: Tags: %s', instance.id, instance_tags)
logger.info('[%s]: Launch Time: %s', instance.id, instance_launch_time)
current_time = datetime.datetime.now(instance_launch_time.tzinfo)
logger.debug('Current Time: %s', current_time)
runtime = time_diff(instance_launch_time, current_time)
runtime_days = runtime.days
runtime_minutes = runtime.seconds/60
logger.info('[%s]: Runtime: %s days', instance.id, runtime_days)
logger.info('[%s]: Runtime: %s mins', instance.id, runtime_minutes)
if (runtime_days >= 1) or (runtime_minutes >= 120):
logger.info('[%s]: Instance has been running for %s days and %s mins. Marking for termination', instance.id, runtime.days, runtime_minutes)
instance.terminate(DryRun=DRYRUN)
logger.info('[%s]: Stopped Instance', instance.id)
return True
def time_diff(launch_time, current_time):
running_time = current_time - launch_time
return running_time
def tags_dict(tags):
'''Flatten a list of tags dicts into a single dict'''
return {t['Key']: t['Value'] for t in tags} if tags else {}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment