forked from chef-boneyard/lambda_ebs_snapshot
-
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement delete old AMIs feature (#4)
- Loading branch information
Showing
6 changed files
with
127 additions
and
178 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
# Module directory | ||
.terraform/ | ||
*.zip | ||
.idea/ |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,98 +2,50 @@ | |
# | ||
# @author Robert Kozora <[email protected]> | ||
# | ||
# This script will search for all instances having a tag with "Backup" or "backup" | ||
# on it. As soon as we have the instances list, we loop through each instance | ||
# and create an AMI of it. Also, it will look for a "Retention" tag key which | ||
# will be used as a retention policy number in days. If there is no tag with | ||
# that name, it will use a 7 days default value for each AMI. | ||
# "retention_days" is environment variable which will be used as a retention policy number in days. If there is no | ||
# environment variable with that name, it will use a 14 days default value for each AMI. | ||
# | ||
# After creating the AMI it creates a "DeleteOn" tag on the AMI indicating when | ||
# After creating the AMI it creates a "AMIDeleteOn" tag on the AMI indicating when | ||
# it will be deleted using the Retention value and another Lambda function | ||
|
||
from __future__ import print_function | ||
import boto3 | ||
import collections | ||
import datetime | ||
import sys | ||
import pprint | ||
import os | ||
|
||
ec = boto3.client('ec2') | ||
#image = ec.Image('id') | ||
ec2_instance_id = os.environ['instance_id'] | ||
label_id = os.environ['label_id'] | ||
|
||
|
||
def lambda_handler(event, context): | ||
|
||
reservations = ec.describe_instances( | ||
Filters=[ | ||
{'Name': 'tag-key', 'Values': ['backup', 'Backup', 'Snapshot']}, | ||
try: | ||
retention_days = int(os.environ['retention']) | ||
except ValueError: | ||
retention_days = 14 | ||
create_time = datetime.datetime.now() | ||
create_fmt = create_time.strftime('%Y-%m-%d') | ||
|
||
AMIid = ec.create_image(InstanceId=ec2_instance_id, | ||
Name=label_id + "-" + ec2_instance_id + "-" + create_fmt, | ||
Description=label_id + "-" + ec2_instance_id + "-" + create_fmt, | ||
NoReboot=True, DryRun=False) | ||
|
||
print("Retaining AMI %s of instance %s for %d days" % ( | ||
AMIid['ImageId'], | ||
ec2_instance_id, | ||
retention_days, | ||
)) | ||
|
||
delete_date = datetime.date.today() + datetime.timedelta(days=retention_days) | ||
delete_fmt = delete_date.strftime('%m-%d-%Y') | ||
|
||
ec.create_tags( | ||
Resources=[ec2_instance_id, AMIid['ImageId']], | ||
Tags=[ | ||
{'Key': 'AMIDeleteOn', 'Value': delete_fmt}, | ||
] | ||
).get( | ||
'Reservations', [] | ||
) | ||
|
||
instances = sum( | ||
[ | ||
[i for i in r['Instances']] | ||
for r in reservations | ||
], []) | ||
|
||
print "Found %d instances that need backing up" % len(instances) | ||
|
||
to_tag = collections.defaultdict(list) | ||
|
||
for instance in instances: | ||
try: | ||
retention_days = [ | ||
int(t.get('Value')) for t in instance['Tags'] | ||
if t['Key'] == 'Retention'][0] | ||
except IndexError: | ||
retention_days = 7 | ||
|
||
#for dev in instance['BlockDeviceMappings']: | ||
# if dev.get('Ebs', None) is None: | ||
# continue | ||
# vol_id = dev['Ebs']['VolumeId'] | ||
# print "Found EBS volume %s on instance %s" % ( | ||
# vol_id, instance['InstanceId']) | ||
|
||
#snap = ec.create_snapshot( | ||
# VolumeId=vol_id, | ||
#) | ||
|
||
#create_image(instance_id, name, description=None, no_reboot=False, block_device_mapping=None, dry_run=False) | ||
# DryRun, InstanceId, Name, Description, NoReboot, BlockDeviceMappings | ||
create_time = datetime.datetime.now() | ||
create_fmt = create_time.strftime('%Y-%m-%d-%H-%M-%S') | ||
|
||
AMIid = ec.create_image(InstanceId=instance['InstanceId'], Name="Lambda - " + instance['InstanceId'] + " from " + create_fmt, Description="Lambda created AMI of instance " + instance['InstanceId'] + " from " + create_fmt, NoReboot=True, DryRun=False) | ||
|
||
|
||
pprint.pprint(instance) | ||
#sys.exit() | ||
#break | ||
|
||
#to_tag[retention_days].append(AMIid) | ||
|
||
to_tag[retention_days].append(AMIid['ImageId']) | ||
|
||
print "Retaining AMI %s of instance %s for %d days" % ( | ||
AMIid['ImageId'], | ||
instance['InstanceId'], | ||
retention_days, | ||
) | ||
|
||
print to_tag.keys() | ||
|
||
for retention_days in to_tag.keys(): | ||
delete_date = datetime.date.today() + datetime.timedelta(days=retention_days) | ||
delete_fmt = delete_date.strftime('%m-%d-%Y') | ||
print "Will delete %d AMIs on %s" % (len(to_tag[retention_days]), delete_fmt) | ||
|
||
#break | ||
|
||
ec.create_tags( | ||
Resources=to_tag[retention_days], | ||
Tags=[ | ||
{'Key': 'DeleteOn', 'Value': delete_fmt}, | ||
] | ||
) | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,14 @@ | |
# | ||
# @author Robert Kozora <[email protected]> | ||
# | ||
# This script will search for all instances having a tag with "Backup" or "backup" | ||
# on it. As soon as we have the instances list, we loop through each instance | ||
# and reference the AMIs of that instance. We check that the latest daily backup | ||
# This script will search for all AMIs having a tag with "AMIDeleteOn" | ||
# on it. As soon as we have the AMIs list, we loop through each images | ||
# and reference the AMIs. We check that the latest daily backup | ||
# succeeded then we store every image that's reached its DeleteOn tag's date for | ||
# deletion. We then loop through the AMIs, deregister them and remove all the | ||
# deletion. We loop through the AMIs, deregister them and remove all the | ||
# snapshots associated with that AMI. | ||
|
||
from __future__ import print_function | ||
import boto3 | ||
import collections | ||
import datetime | ||
|
@@ -18,26 +19,13 @@ | |
|
||
ec = boto3.client('ec2', os.environ['region']) | ||
ec2 = boto3.resource('ec2', os.environ['region']) | ||
images = ec2.images.filter(Owners=[os.environ['ami_owner']]) | ||
images = ec2.images.filter(Owners=[os.environ['ami_owner']], | ||
Filters=[{'Name': 'tag-key', 'Values': ['AMIDeleteOn']}]) | ||
|
||
def lambda_handler(event, context): | ||
|
||
reservations = ec.describe_instances( | ||
Filters=[ | ||
{'Name': 'tag-key', 'Values': ['backup', 'Backup', 'Snapshot']}, | ||
] | ||
).get( | ||
'Reservations', [] | ||
) | ||
|
||
instances = sum( | ||
[ | ||
[i for i in r['Instances']] | ||
for r in reservations | ||
], []) | ||
|
||
print "Found %d instances that need evaluated" % len(instances) | ||
label_id = os.environ['label_id'] | ||
instance_id = os.environ['instance_id'] | ||
|
||
def lambda_handler(event, context): | ||
to_tag = collections.defaultdict(list) | ||
|
||
date = datetime.datetime.now() | ||
|
@@ -48,61 +36,58 @@ def lambda_handler(event, context): | |
# Set to true once we confirm we have a backup taken today | ||
backupSuccess = False | ||
|
||
# Loop through all of our instances with a tag named "Backup" | ||
for instance in instances: | ||
imagecount = 0 | ||
|
||
# Loop through each image of our current instance | ||
for image in images: | ||
|
||
# Our other Lambda Function names its AMIs Lambda - i-instancenumber. | ||
# We now know these images are auto created | ||
if image.name.startswith('Lambda - ' + instance['InstanceId']): | ||
|
||
# print "FOUND IMAGE " + image.id + " FOR INSTANCE " + instance['InstanceId'] | ||
|
||
# Count this image's occcurance | ||
imagecount = imagecount + 1 | ||
|
||
try: | ||
if image.tags is not None: | ||
deletion_date = [ | ||
t.get('Value') for t in image.tags | ||
if t['Key'] == 'DeleteOn'][0] | ||
delete_date = time.strptime(deletion_date, "%m-%d-%Y") | ||
except IndexError: | ||
deletion_date = False | ||
delete_date = False | ||
|
||
today_time = datetime.datetime.now().strftime('%m-%d-%Y') | ||
# today_fmt = today_time.strftime('%m-%d-%Y') | ||
today_date = time.strptime(today_time, '%m-%d-%Y') | ||
|
||
# If image's DeleteOn date is less than or equal to today, | ||
# add this image to our list of images to process later | ||
if delete_date <= today_date: | ||
imagesList.append(image.id) | ||
|
||
# Make sure we have an AMI from today and mark backupSuccess as true | ||
if image.name.endswith(date_fmt): | ||
# Our latest backup from our other Lambda Function succeeded | ||
backupSuccess = True | ||
print "Latest backup from " + date_fmt + " was a success" | ||
|
||
print "instance " + instance['InstanceId'] + " has " + str(imagecount) + " AMIs" | ||
|
||
print "=============" | ||
|
||
print "About to process the following AMIs:" | ||
print imagesList | ||
# Loop through each image | ||
for image in images: | ||
|
||
try: | ||
if image.tags is not None: | ||
deletion_date = [ | ||
t.get('Value') for t in image.tags | ||
if t['Key'] == 'AMIDeleteOn'][0] | ||
delete_date = time.strptime(deletion_date, "%m-%d-%Y") | ||
except IndexError: | ||
deletion_date = False | ||
delete_date = False | ||
|
||
# Our other Lambda Function names its AMIs label_id- | ||
# We now know these images are auto created | ||
if image.name.startswith(label_id + '-' + instance_id): | ||
|
||
try: | ||
if image.tags is not None: | ||
deletion_date = [ | ||
t.get('Value') for t in image.tags | ||
if t['Key'] == 'AMIDeleteOn'][0] | ||
delete_date = time.strptime(deletion_date, "%m-%d-%Y") | ||
except IndexError: | ||
deletion_date = False | ||
delete_date = False | ||
|
||
today_time = datetime.datetime.now().strftime('%m-%d-%Y') | ||
today_date = time.strptime(today_time, '%m-%d-%Y') | ||
|
||
# If image's DeleteOn date is less than or equal to today, | ||
# add this image to our list of images to process later | ||
if delete_date <= today_date: | ||
imagesList.append(image.id) | ||
|
||
# Make sure we have an AMI from today and mark backupSuccess as true | ||
if image.name.endswith(date_fmt): | ||
# Our latest backup from our other Lambda Function succeeded | ||
backupSuccess = True | ||
|
||
print("=============") | ||
|
||
print("About to process the following AMIs:") | ||
print(imagesList) | ||
|
||
if backupSuccess == True: | ||
|
||
snapshots = ec.describe_snapshots(MaxResults=1000, OwnerIds=[os.environ['ami_owner']])['Snapshots'] | ||
|
||
# loop through list of image IDs | ||
for image in imagesList: | ||
print "deregistering image %s" % image | ||
print("deregistering image %s" % image) | ||
amiResponse = ec.deregister_image( | ||
DryRun=False, | ||
ImageId=image, | ||
|
@@ -111,8 +96,8 @@ def lambda_handler(event, context): | |
for snapshot in snapshots: | ||
if snapshot['Description'].find(image) > 0: | ||
snap = ec.delete_snapshot(SnapshotId=snapshot['SnapshotId']) | ||
print "Deleting snapshot " + snapshot['SnapshotId'] | ||
print "-------------" | ||
print("Deleting snapshot " + snapshot['SnapshotId']) | ||
print("-------------") | ||
|
||
else: | ||
print "No current backup found. Termination suspended." | ||
print("No current backup found. Termination suspended.") |
Oops, something went wrong.