-
-
Save bkozora/d4f1cf0e5cf26acdd377 to your computer and use it in GitHub Desktop.
# Automated AMI and Snapshot Deletion | |
# | |
# @author Bobby Kozora | |
# | |
# This script will search for all instances having a tag named "Backup" with a value of "Backup". | |
# 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 | |
# 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 | |
# snapshots associated with that AMI. | |
import boto3 | |
import collections | |
import datetime | |
import time | |
import sys | |
ec = boto3.client('ec2', 'us-east-1') | |
ec2 = boto3.resource('ec2', 'us-east-1') | |
images = ec2.images.filter(Owners=["self"]) | |
def lambda_handler(event, context): | |
reservations = ec.describe_instances(Filters=[ | |
{ | |
'Name': 'tag-key', | |
'Values': ['backup', 'Backup'] | |
}, | |
]).get('Reservations', []) | |
instances = sum([[i for i in r['Instances']] for r in reservations], []) | |
print("Found %d instances that need evaluated" % len(instances)) | |
to_tag = collections.defaultdict(list) | |
date = datetime.datetime.now() | |
date_fmt = date.strftime('%Y-%m-%d') | |
imagesList = [] | |
# 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) | |
if backupSuccess == True: | |
myAccount = boto3.client('sts').get_caller_identity()['Account'] | |
snapshots = ec.describe_snapshots(MaxResults=1000, | |
OwnerIds=[myAccount])['Snapshots'] | |
# loop through list of image IDs | |
for image in imagesList: | |
print("deregistering image %s" % image) | |
amiResponse = ec.deregister_image( | |
DryRun=False, | |
ImageId=image, | |
) | |
for snapshot in snapshots: | |
if snapshot['Description'].find(image) > 0: | |
snap = ec.delete_snapshot( | |
SnapshotId=snapshot['SnapshotId']) | |
print("Deleting snapshot " + snapshot['SnapshotId']) | |
print("-------------") | |
else: | |
print("No current backup found. Termination suspended.") |
@mohanish12 For those of you who changed line 65 in the backup function script:
create_fmt = create_time.strftime('%Y-%m-%d')
To
create_fmt = create_time.strftime('%Y-%m-%d--%H-%M-%S')
The cleanup function is looking for
if image.name.endswith(date_fmt):
on line 86. Since the strftime variable does not now end with today's date (now time), then it will throw error.My workaround was to put the time in front of the date, like this:
create_fmt = create_time.strftime('%H-%M-%S(UTC)--on--%Y-%m-%d')
Hope this helps someone.
Thank you so much for such solution.
Here is the cleanup code & the output: It able to detect the instance but not able to delete the ami created today, even I changed backupSuccess = True
Test Event Name
test
Response
null
Function Logs
START RequestId: 3f72e0b7-59bb-433e-a46d-4f097c8acb45 Version: $LATEST
Found 1 instances that need evaluated
instance i-0acbe212ea7c31c7e has 0 AMIs
About to process the following AMIs:
[]
END RequestId: 3f72e0b7-59bb-433e-a46d-4f097c8acb45
import boto3
import collections
import datetime
import time
import sys
ec = boto3.client('ec2', 'ap-south-1')
ec2 = boto3.resource('ec2', 'ap-south-1')
images = ec2.images.filter(Owners=["self"])
def lambda_handler(event, context):
reservations = ec.describe_instances(Filters=[
{
'Name': 'tag-key',
'Values': ['backup', 'Backup']
},
]).get('Reservations', [])
instances = sum([[i for i in r['Instances']] for r in reservations], [])
print("Found %d instances that need evaluated" % len(instances))
to_tag = collections.defaultdict(list)
date = datetime.datetime.now()
date_fmt = date.strftime('%Y-%m-%d')
imagesList = []
# Set to true once we confirm we have a backup taken today
backupSuccess = True
# 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)
if backupSuccess == True:
myAccount = boto3.client('sts').get_caller_identity()['Account']
snapshots = ec.describe_snapshots(MaxResults=1000,
OwnerIds=[myAccount])['Snapshots']
# loop through list of image IDs
for image in imagesList:
print("deregistering image %s" % image)
amiResponse = ec.deregister_image(
DryRun=False,
ImageId=image,
)
for snapshot in snapshots:
if snapshot['Description'].find(image) > 0:
snap = ec.delete_snapshot(
SnapshotId=snapshot['SnapshotId'])
print("Deleting snapshot " + snapshot['SnapshotId'])
print("-------------")
else:
print("No current backup found. Termination suspended.")
Hi
I have code to have the retention backup days for 7, however, how to exclude the weekends snapshots for the last 35 days in deletion.
I want to have the snapshots for last 7 days and last 5 weekend Saturdays snapshots without using tags.
Kindly let me know the code if possible
Hi,
I tried running the code with python 3.6 but it is throwing following error.
=======Error Message===========
{
"errorMessage": "'<=' not supported between instances of 'bool' and 'time.struct_time'",
"errorType": "TypeError",
"stackTrace": [
" File "/var/task/lambda_function.py", line 66, in lambda_handler\n if delete_date <= today_date:\n"
]
}