- Newest
- Most votes
- Most comments
Hello.
Try using the code below.
I corrected the indentation and ran a test from the Lambda console to confirm that no errors occurred.
import boto3
import os
from datetime import datetime
# Define regions
# SOURCE_REGION = "us-west-1" # N. California
SOURCE_REGION = "us-west-2" # Oregon
DEST_REGION = "us-west-2" # Oregon
NUM_SNAPSHOTS = 2 # Number of snapshots to process
def lambda_handler(event, context):
# Create RDS clients for both regions
source_rds = boto3.client('rds', region_name=SOURCE_REGION)
dest_rds = boto3.client('rds', region_name=DEST_REGION)
# Step 1: Delete oldest manual snapshots in destination region
delete_oldest_snapshots(dest_rds, NUM_SNAPSHOTS)
# Step 2: Copy latest system snapshots from source to destination
copy_latest_snapshots(source_rds, dest_rds, NUM_SNAPSHOTS)
return {
'statusCode': 200,
'body': f'Successfully processed {NUM_SNAPSHOTS} snapshots'
}
def delete_oldest_snapshots(dest_rds, count):
# Get all manual snapshots in destination region
response = dest_rds.describe_db_snapshots(SnapshotType='manual')
# Sort snapshots by creation time (oldest first)
snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime'])
# Delete the oldest 'count' snapshots
for i, snapshot in enumerate(snapshots):
if i >= count:
break
snapshot_id = snapshot['DBSnapshotIdentifier']
print(f"Deleting snapshot: {snapshot_id}")
try:
dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id)
print(f"Successfully deleted snapshot: {snapshot_id}")
except Exception as e:
print(f"Error deleting snapshot {snapshot_id}: {str(e)}")
def copy_latest_snapshots(source_rds, dest_rds, count):
# Get all automated snapshots in source region
response = source_rds.describe_db_snapshots(SnapshotType='automated')
# Sort snapshots by creation time (newest first)
snapshots = sorted(response['DBSnapshots'],
key=lambda s: s['SnapshotCreateTime'],
reverse=True
)
# Get today's date for naming
today = datetime.now().strftime("%Y-%m-%d")
# Define the database names based on your example
# "amgen", "alpine"
db_names = [
"demo", "drtest20240314"
]
# Copy the newest 'count' snapshots
for i, snapshot in enumerate(snapshots[:count]):
if i >= count:
break
source_snapshot_id = snapshot['DBSnapshotIdentifier']
db_instance_id = snapshot['DBInstanceIdentifier']
# Use the corresponding db name from the list if available
db_name = db_names[i] if i < len(db_names) else db_instance_id
# Create target snapshot name
target_snapshot_id = f"copy-rds-db-{db_name}-{today}"
print(f"Copying snapshot {source_snapshot_id} to {target_snapshot_id}")
try:
# Create ARN for source snapshot
source_arn = snapshot['DBSnapshotArn']
# Copy the snapshot
dest_rds.copy_db_snapshot(
SourceDBSnapshotIdentifier=source_arn,
TargetDBSnapshotIdentifier=target_snapshot_id,
SourceRegion=SOURCE_REGION
)
print(f"Successfully initiated copy of {source_snapshot_id} to {target_snapshot_id}")
except Exception as e:
print(f"Error copying snapshot {source_snapshot_id}: {str(e)}")
Also, around line 85, the snapshot ARN is created as follows, but this is unnecessary.
source_arn = f"arn:aws:rds:{SOURCE_REGION}:{snapshot['DBSnapshotArn'].split(':')[4]}:{source_snapshot_id}"
You can get the ARN using "snapshot['DBSnapshotArn']", so I have modified it as follows.
source_arn = snapshot['DBSnapshotArn']
The error you're seeing is due to indentation issues in your Python code. In Python, indentation defines code blocks, and your current code has inconsistent indentation which is causing the snapshots variable to be out of scope when you try to use it.
Here's the corrected code with proper indentation:
import boto3 import os from datetime import datetime # Define regions # SOURCE_REGION = "us-west-1" # N. California SOURCE_REGION = "us-west-2" # Oregon DEST_REGION = "us-west-2" # Oregon NUM_SNAPSHOTS = 2 # Number of snapshots to process def lambda_handler(event, context): # Create RDS clients for both regions source_rds = boto3.client('rds', region_name=SOURCE_REGION) dest_rds = boto3.client('rds', region_name=DEST_REGION) # Step 1: Delete oldest manual snapshots in destination region delete_oldest_snapshots(dest_rds, NUM_SNAPSHOTS) # Step 2: Copy latest system snapshots from source to destination copy_latest_snapshots(source_rds, dest_rds, NUM_SNAPSHOTS) return { 'statusCode': 200, 'body': f'Successfully processed {NUM_SNAPSHOTS} snapshots' } def delete_oldest_snapshots(dest_rds, count): # Get all manual snapshots in destination region response = dest_rds.describe_db_snapshots(SnapshotType='manual') # Sort snapshots by creation time (oldest first) snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime']) # Delete the oldest 'count' snapshots for i, snapshot in enumerate(snapshots): if i >= count: break snapshot_id = snapshot['DBSnapshotIdentifier'] print(f"Deleting snapshot: {snapshot_id}") try: dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id) print(f"Successfully deleted snapshot: {snapshot_id}") except Exception as e: print(f"Error deleting snapshot {snapshot_id}: {str(e)}") def copy_latest_snapshots(source_rds, dest_rds, count): # Get all automated snapshots in source region response = source_rds.describe_db_snapshots(SnapshotType='automated') # Sort snapshots by creation time (newest first) snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime'], reverse=True) # Get today's date for naming today = datetime.now().strftime("%Y-%m-%d") # Define the database names based on your example db_names = [ "demo", "drtest20240314" ] # Copy the newest 'count' snapshots for i, snapshot in enumerate(snapshots[:count]): if i >= count: break source_snapshot_id = snapshot['DBSnapshotIdentifier'] db_instance_id = snapshot['DBInstanceIdentifier'] # Use the corresponding db name from the list if available db_name = db_names[i] if i < len(db_names) else db_instance_id # Create target snapshot name target_snapshot_id = f"copy-rds-db-{db_name}-{today}" print(f"Copying snapshot {source_snapshot_id} to {target_snapshot_id}") try: # Create ARN for source snapshot source_arn = f"arn:aws:rds:{SOURCE_REGION}:{snapshot['DBSnapshotArn'].split(':')[4]}:{source_snapshot_id}" # Copy the snapshot dest_rds.copy_db_snapshot( SourceDBSnapshotIdentifier=source_arn, TargetDBSnapshotIdentifier=target_snapshot_id, SourceRegion=SOURCE_REGION ) print(f"Successfully initiated copy of {source_snapshot_id} to {target_snapshot_id}") except Exception as e: print(f"Error copying snapshot {source_snapshot_id}: {str(e)}")
The key issues I fixed:
- Proper indentation for all function definitions and their contents
- Consistent indentation within code blocks (4 spaces per level)
- Properly indented the code inside the
delete_oldest_snapshotsandcopy_latest_snapshotsfunctions
This should resolve the "name 'snapshots' is not defined" error because now the snapshots variable is properly defined within the scope where it's being used.
Sources
Lambda Init failure with "NameError: name 'long' is not defined" | AWS re:Post
Nope. Same indent errors. Now it's complaining about line 13, which it's never had issue with before.
Status: Failed Test Event Name: TestEventLambdaSnap2
Response: { "errorMessage": "Syntax error in module 'lambda_function': expected an indented block after function definition on line 11 (lambda_function.py, line 13)", "errorType": "Runtime.UserCodeSyntaxError", "requestId": "", "stackTrace": [ " File "/var/task/lambda_function.py" Line 13\n source_rds = boto3.client('rds', region_name=SOURCE_REGION)\n" ] }
Relevant content
- asked 9 months ago
- asked 2 years ago
- AWS OFFICIALUpdated 4 years ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 2 years ago

Riku - I want to thank you very much for helping me out! I did not realize that "tab" does not create the appropriate indent action, which I was doing. The re-format you provided worked like a charm and the test ran until it a timeout error (Sandbox.Timedout), which I believe I can fix via re-configuring the timeout setting. For others reading this, the timeout error is:
Status: Failed Test Event Name: TestEventLambdaSnap2
Response: { "errorType": "Sandbox.Timedout",
Thank you again Riku! Best Regards, Donald