''' Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at http://aws.amazon.com/apache2.0/ or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Modified by Suman Koduri (skkoduri@amazon.com) ''' # delete_old_snapshots_rds # This Lambda function will delete snapshots that have expired and match the regex set in the PATTERN environment variable. It will also look for a matching timestamp in the following format: YYYY-MM-DD-HH-mm import boto3 from datetime import datetime import time import os import logging import re from delete_snapshots_utils import * LOGLEVEL = os.getenv('LOG_LEVEL', 'ERROR').strip() RETENTION_DAYS = int(os.getenv('RETENTION_DAYS', '7')) TIMESTAMP_FORMAT = '%Y-%m-%d-%H-%M' # Set default Bucket and Key if none are specified if 'S3BUCKET' in os.environ: BUCKET = os.getenv('S3BUCKET') else: RDSBackupToolException("S3BUCKET Environment Variable not found") KEY = "rds_backups_list.txt" logger = logging.getLogger() logger.setLevel(LOGLEVEL.upper()) def lambda_handler(event, context): pending_delete = 0 client = boto3.client('rds') s3 = boto3.client('s3') obj = s3.get_object(Bucket = BUCKET, Key = KEY) rds_instances = obj['Body'].read().decode('utf-8').split('\r\n') # Filter RDS/Aurora instances filtered_rds = filter_rds(rds_instances, client) # Get list of filtered RDS and Aurora instances to back up filtered_instances = filtered_rds[0] filtered_clusters = filtered_rds[1] # Filter snapshots for RDS and Aurora filtered_snapshots_rds = get_own_snapshots_source_rds(filtered_instances, paginate_api_call(client, 'describe_db_snapshots', 'DBSnapshots')) filtered_snapshots_aurora = get_own_snapshots_source_aurora(filtered_clusters, paginate_api_call(client, 'describe_db_cluster_snapshots', 'DBClusterSnapshots')) for snapshot in filtered_snapshots_rds.keys(): creation_date = get_timestamp_rds(snapshot, filtered_snapshots_rds) if creation_date: difference = datetime.now() - creation_date days_difference = difference.total_seconds() / 3600 / 24 logger.debug('{} created {} days ago'.format(snapshot, days_difference)) # if we are past RETENTION_DAYS if days_difference > RETENTION_DAYS: # delete it logger.info('Deleting {}'.format(snapshot)) try: response = client.delete_db_snapshot( DBSnapshotIdentifier=snapshot) manageSnapshotRecord(action = 'update', snapshot_id = response['DBSnapshot']['DBSnapshotIdentifier'], rds_name = response['DBSnapshot']['DBInstanceIdentifier'], snapshot_state = "deleted",deleted_bool = True) except Exception: pending_delete += 1 logger.info('Could not delete {} '.format(snapshot)) else: logger.info('Not deleting {}. Created only {}'.format(snapshot, days_difference)) for snapshot in filtered_snapshots_aurora.keys(): creation_date = get_timestamp_aurora(snapshot, filtered_snapshots_aurora) if creation_date: difference = datetime.now() - creation_date days_difference = difference.total_seconds() / 3600 / 24 logger.debug('{} created {} days ago'.format(snapshot, days_difference)) # if we are past RETENTION_DAYS if days_difference > RETENTION_DAYS: # delete it logger.info('Deleting {}'.format(snapshot)) try: response = client.delete_db_cluster_snapshot( DBClusterSnapshotIdentifier=snapshot) manageSnapshotRecord(action = 'update', snapshot_id = response['DBClusterSnapshot']['DBClusterSnapshotIdentifier'], rds_name = response['DBClusterSnapshot']['DBClusterIdentifier'], snapshot_state = "deleted", deleted_bool = True) except Exception: pending_delete += 1 logger.info('Could not delete {} '.format(snapshot)) else: # Not older than RETENTION_DAYS logger.debug('{} created less than {} days. Not deleting'.format(snapshot, RETENTION_DAYS)) else: # Did not have a timestamp logger.debug('Not deleting {}. Could not find a timestamp in the name'.format(snapshot)) if pending_delete > 0: message = 'Snapshots pending delete: {}'.format(pending_delete) logger.error(message) raise RDSBackupToolException(message) if __name__ == '__main__': lambda_handler(None, None)