Created
December 7, 2016 07:05
-
-
Save bdpdx/0ebb6e0849564153e34f2733c03114ae 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 collections | |
import datetime | |
ec = boto3.client('ec2') | |
# inspired by https://serverlesscode.com/post/lambda-schedule-ebs-snapshot-backups/ | |
# | |
# snapshot deletion lambda | |
# this function deletes snapshots backed up by the EBSSnapshotterCreator | |
# prerequisites: | |
# only snapshots for attached volumes are considered | |
# the instance that owns the volume must have a Backup=true tag | |
# the instance may optionally have a BackupRetentionDays=n tag where n | |
# is an integer specifying the number of days to retain backups. | |
# if not present, the default is 0 | |
# this script only considers completed EBS backups for deletion, and it | |
# will always retain the most current complete backup. Only snapshots | |
# that have the createdByEBSSnapshotter=true tag will be considered. | |
def lambda_handler(event, context): | |
now = datetime.datetime.now() | |
volumeIds = {} | |
reservations = ec.describe_instances()['Reservations'] | |
for reservation in reservations: | |
for instance in reservation['Instances']: | |
backup = False | |
backupRetentionDays = 0 | |
for tag in instance['Tags']: | |
key = tag['Key'] | |
value = tag['Value'] | |
if key == 'Backup': | |
backup = tag['Value'] == 'true' | |
elif key == 'BackupRetentionDays': | |
backupRetentionDays = int(tag['Value']) | |
if not backup: continue | |
retentionDate = (now - datetime.timedelta(days=backupRetentionDays)).date() | |
for device in instance['BlockDeviceMappings']: | |
if device.get('Ebs', None) is None: continue | |
volumeId = device['Ebs']['VolumeId'] | |
info = ec.describe_volumes(VolumeIds=[volumeId])['Volumes'][0] | |
name = volumeId | |
skip = False | |
for tag in info['Tags']: | |
key = tag['Key'] | |
if key == 'Backup': | |
skip = tag['Value'] == 'false' | |
elif key == 'Name': | |
name += ' (' + tag['Value'] + ')' | |
if skip: | |
print 'Ignoring snapshots for volume %s due to Backup=false tag' % (name) | |
continue | |
else: | |
volumeIds[volumeId] = { | |
'name': name, | |
'retentionDate': retentionDate, | |
'snapshotsToDelete': [] | |
} | |
accountId = '000000000000' # your 12-digit AWS account id here | |
snapshots = ec.describe_snapshots(OwnerIds=[accountId])['Snapshots'] | |
for snapshot in snapshots: | |
if not snapshot['State'] == 'completed': continue | |
volumeId = snapshot['VolumeId'] | |
if volumeId not in volumeIds: continue | |
createdByEBSSnapshotter = False | |
tags = snapshot.get('Tags', None) | |
if tags is None: continue | |
for tag in tags: | |
if tag['Key'] == 'createdByEBSSnapshotter': | |
createdByEBSSnapshotter = tag['Value'] == 'true' | |
break | |
if not createdByEBSSnapshotter: continue | |
creationDate = snapshot['StartTime'].date() | |
retentionDate = volumeIds[volumeId]['retentionDate'] | |
if creationDate > retentionDate: continue | |
snapshotId = snapshot['SnapshotId'] | |
volumeIds[volumeId]['snapshotsToDelete'].append((snapshotId, creationDate)) | |
for volumeId in volumeIds.keys(): | |
name = volumeIds[volumeId]['name'] | |
snapshotsToDelete = volumeIds[volumeId]['snapshotsToDelete'] | |
if len(snapshotsToDelete) < 2: | |
print 'Ignoring snapshots for volume %s because there are fewer than 2 snapshots' % (name) | |
continue # always leave one complete snapshot | |
snapshotsToDelete = sorted(snapshotsToDelete, key=lambda creationDate: creationDate[1]) | |
snapshotsToDelete.pop() | |
for snapshot in snapshotsToDelete: | |
snapshotId = snapshot[0] | |
print 'Deleting snapshot %s for volume %s' % (snapshotId, name) | |
ec.delete_snapshot(SnapshotId=snapshotId) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment