import boto3 import time import logging import os TOPICARN = os.getenv('TOPICARN').strip() LOGLEVEL = os.getenv('LOG_LEVEL', 'ERROR').strip() logger = logging.getLogger() logger.setLevel(LOGLEVEL) class RDSBackupToolException(Exception): pass def delSnapshotRecord(snapshot_id, rds_name): """Function to delete a record passed to function""" response = boto3.client("dynamodb").delete_item( TableName = "RDS_Snapshot_Logging", Key = { "Snapshot_ID": { "S": snapshot_id }, "RDS_Name": { "S": rds_name } }, ConditionExpression = "Deleted = :Deleted", ExpressionAttributeValues = {":Deleted": { "BOOL": True }} ) logger.debug("Responde for 'delSnapshotRecord' is: {}".format(response)) return response def getSnapshotRecords(attribute): """Function to get records from DynamoDB based on attribute passed to function""" if attribute == '': log_message = "Get Snapshot Records Attribute cannot be empty" logger.error(log_message) raise RDSBackupToolException(log_message) filter_expression = '' value_expression = {} if attribute == 'emailed': filter_expression = "Emailed" value_expression[':search_string'] = {"BOOL": False} elif attribute == 'deleted': filter_expression = "Deleted" value_expression[':search_string'] = {"BOOL": True} elif attribute == 'snap_state': filter_expression = "Snapshot_State" value_expression[':search_string'] = {"S": "creating"} else: log_message = "Unknown attribute: {}".format(attribute) logger.error(log_message) raise RDSBackupToolException(log_message) response = boto3.client("dynamodb").scan( TableName = "RDS_Snapshot_Logging", Select = "ALL_ATTRIBUTES", FilterExpression = "{} = :search_string".format(filter_expression), ExpressionAttributeValues = value_expression )['Items'] logger.debug( "Response from getSnapshotRecords using '{}' attribute: {}".format( attribute, response ) ) return response def manageSnapshotRecord(**kwargs): """Function to add/update records to/in the RDS_Snapshot_Logging DynamoDB Table.""" # Get current time stamp in "mm-dd-yyyy HH:MM" format timestamp = time.strftime("%m-%d-%Y %H:%M") action = '' snapshot_id = '' rds_name = '' snapshot_state = 'creating' emailed_bool = False deleted_bool = False # Empty dict for building the ExpressionAttributeValues for update_item below expression = {} # String for building the UpdateExpression for update_item below with default timestamp value update = 'set Created_Snapshot_Timestamp = if_not_exists(Created_Snapshot_Timestamp, :Snapshot_Timestamp), \ Updated_Snapshot_Timestamp = :Snapshot_Timestamp' expression[':Snapshot_Timestamp'] = {"S": timestamp} for key, value in kwargs.items(): if 'action' in key: action = value if 'snapshot_id' in key: snapshot_id = value if 'rds_name' in key: rds_name = value # If snapshot_region is specified, use it if 'snapshot_region' in key: expression[':Snapshot_Region'] = {"S": value} update += ',Snapshot_Region = if_no_exists( Snapshot_Region, :Snapshot_Region)' # If snapshot_state is specified, use it if 'snapshot_state' in key: expression[':Snapshot_State'] = {"S": value} update += ',Snapshot_State = :Snapshot_State' if 'rds_engine' in key: expression[':RDS_Engine'] = {"S": value} update += ',RDS_Engine = if_not_exists(RDS_Engine, :RDS_Engine)' # If emailed_bool is specified, use it if 'emailed_bool' in key: expression[':emailed'] = {"BOOL": value} update += ',Emailed = :emailed' # If deleted_bool is specified, use it if 'deleted_bool' in key: expression[':deleted'] = {"BOOL": value} update += ',Deleted = :deleted' # Action = add or update if action == '': logger.error("Action is empty. Valid values: 'add' or 'update'") return "ERROR: Action required" # Add default states if action is add if action == 'add': expression[':deleted'] = {"BOOL": deleted_bool} update += ',Deleted = :deleted' expression[':emailed'] = {"BOOL": emailed_bool} update += ',Emailed = :emailed' expression[':Snapshot_State'] = {"S": snapshot_state} update += ',Snapshot_State = :Snapshot_State' if snapshot_id == '' or rds_name == '': logger.error("Snapshot ID and RDS Identifier cannot be empty.") return False logger.debug("Update expression 'update' variable: {}".format(update)) logger.debug( "Expression Attribute Values 'expression': {}".format(expression) ) response = boto3.client("dynamodb").update_item( TableName = "RDS_Snapshot_Logging", Key = { "Snapshot_ID": { "S": snapshot_id }, "RDS_Name": { "S": rds_name } }, ReturnValues = "UPDATED_NEW", UpdateExpression = update, ExpressionAttributeValues = expression ) logger.debug("manageSnapshotRecord response: {}".format(response)) return response def publishToSNS(message_body): """Function to push content to SNS""" response = boto3.client("sns").publish( TopicArn = TOPICARN, Subject = "RDS Backup Tool Notification", Message = message_body ) logger.debug("Response from sendViaSNS is: {}".format(response)) return response