Last active
July 16, 2023 15:48
-
-
Save dedunumax/cc66e901e29e139247690d54be77d026 to your computer and use it in GitHub Desktop.
This AWS Lambda function will scan for RDS instances with no connections for last 14 days using boto3 and stop them. -https://github.com/dedunu/blog/blob/main/2020/2020-07-04-unused-rds-lambda.md
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
"""RDS-Unused AWS Lambda Function | |
It will go through the REGION's RDS instances and check on CloudWatch for the unused | |
instances and will stop them. | |
""" | |
import json | |
from datetime import datetime, timedelta | |
from multiprocessing import Process, Pipe | |
import boto3 | |
REGION = 'us-west-1' | |
"""str: Region to scan | |
""" | |
def lambda_handler(event, context): | |
"""Entry point for the Lambda function | |
:param event: Parameters sent to the function | |
:param context: Runtime information | |
:return: number of databases scanned | |
""" | |
print("Event:" + str(event)) | |
print("Context:" + str(event)) | |
# Connecting to AWS and getting all the instances | |
client = boto3.client('rds', region_name=REGION) | |
paginator = client.get_paginator('describe_db_instances') | |
pages = paginator.paginate() | |
processes = [] | |
parents = [] | |
# Creating threads using process for each database instance | |
for db_instance in [db_instances | |
for page in pages | |
for db_instances in page['DBInstances']]: | |
create_process(db_instance['DBInstanceIdentifier'], processes, parents) | |
# Starting all the processes | |
for process in processes: | |
process.start() | |
# Waiting for all the process to end | |
for process in processes: | |
process.join() | |
# Counting the number of instances scanned | |
db_instances_scanned = sum(parent.recv()[0] for parent in parents) | |
print('Ununsed instance scan finished successfully. Scanned ' + | |
str(db_instances_scanned) + ' instances.') | |
return { | |
'scanned': json.dumps(db_instances_scanned) | |
} | |
def create_process(db_instance, processes, parent_connections): | |
"""Create a process and add to processes | |
:param db_instance: Instance object returned from boto3 | |
:param processes: Process array with all the processes | |
:param parent_connections: Parent connections to collect results | |
""" | |
parent_conn, child_conn = Pipe() | |
parent_connections.append(parent_conn) | |
process = Process( | |
target=check_for_unused, | |
args=(db_instance, child_conn) | |
) | |
processes.append(process) | |
def check_for_unused(db_instance, conn): | |
"""Checking for instances with no connections and stop them. | |
:param db_instance: Database instance information returned fromm boto3 | |
:param conn: child connection | |
""" | |
client = boto3.client('cloudwatch', region_name=REGION) | |
end_date = datetime.utcnow() | |
start_date = end_date - timedelta(days=14) | |
# Getting DatabaseConnections metrics for the last 14 days | |
connection_statistics = client.get_metric_statistics( | |
Namespace='AWS/RDS', | |
MetricName='DatabaseConnections', | |
Dimensions=[ | |
{ | |
'Name': 'DBInstanceIdentifier', | |
'Value': db_instance | |
}, | |
], | |
StartTime=start_date, | |
EndTime=end_date, | |
Period=86400, | |
Statistics=["Maximum"] | |
) | |
total_connection_count = sum(data_point['Maximum'] | |
for data_point in connection_statistics['Datapoints']) | |
if total_connection_count == 0: | |
rds_client = boto3.client('rds', region_name=REGION) | |
try: | |
rds_client.stop_db_instance(DBInstanceIdentifier=db_instance) | |
print(db_instance + " database was stopped.") | |
except rds_client.exceptions.InvalidDBInstanceStateFault: | |
print('Failed to stop ' + db_instance) | |
conn.send([1]) | |
conn.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment