Skip to content

Commit 59e3eff

Browse files
committed
refactor for python 3.11
1 parent 760a5e9 commit 59e3eff

File tree

2 files changed

+61
-27
lines changed

2 files changed

+61
-27
lines changed

main.py

+59-27
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
#! /usr/bin/env python3
2-
import boto3
3-
import botocore
2+
3+
"""
4+
Small AWS Lambda function to copy RDS snapshots to another region.
5+
"""
6+
47
import datetime
58
import re
69

10+
import boto3
11+
import botocore
12+
713
# Region where the automated snapshots are located
814
SOURCE_REGION = "eu-west-1"
915
# List of RDS instances which snapshots should be copied
@@ -16,34 +22,51 @@
1622
KEEP = 10
1723

1824

19-
def bySnapshotId(snap):
25+
class BackupException(Exception):
26+
"""
27+
Backup exception raised when somthing went wrong doing the backups.
28+
"""
29+
30+
31+
def by_snapshot_id(snap):
32+
"""
33+
Returns the snapshot identifier for an RDS instance
34+
"""
2035
return snap["DBSnapshotIdentifier"]
2136

2237

23-
def byClusterSnapshotId(snap):
38+
def by_cluster_snapshot_id(snap):
39+
"""
40+
Returns the snapshot identifier for an RDS cluster instance
41+
"""
2442
return snap["DBClusterSnapshotIdentifier"]
2543

2644

27-
def byTimestamp(snap):
45+
def by_timestamp(snap):
46+
"""
47+
Returns the timestamp of a snapshot
48+
"""
2849
if "SnapshotCreateTime" in snap:
2950
return datetime.datetime.isoformat(snap["SnapshotCreateTime"])
30-
else:
31-
return datetime.datetime.isoformat(datetime.datetime.now())
51+
return datetime.datetime.isoformat(datetime.datetime.now())
3252

3353

3454
def copy_rds_snapshots(source_client, target_client, account, name):
35-
print("Copying snapshots for {}".format(name))
55+
"""
56+
Copies snapshots from an RDS instance
57+
"""
58+
print(f"Copying snapshots for {name}")
3659
source_snaps = source_client.describe_db_snapshots(SnapshotType="automated", DBInstanceIdentifier=name)[
3760
"DBSnapshots"
3861
]
3962
if len(source_snaps) == 0:
4063
print("Found no automated snapshots. Nothing to do")
4164
return
4265

43-
source_snap = sorted(source_snaps, key=bySnapshotId, reverse=True)[0]["DBSnapshotIdentifier"]
44-
source_snap_arn = "arn:aws:rds:{}:{}:snapshot:{}".format(SOURCE_REGION, account, source_snap)
45-
target_snap_id = "copy-of-{}".format(re.sub("rds:", "", source_snap))
46-
print("Will copy {} to {}".format(source_snap_arn, target_snap_id))
66+
source_snap = sorted(source_snaps, key=by_snapshot_id, reverse=True)[0]["DBSnapshotIdentifier"]
67+
source_snap_arn = f"arn:aws:rds:{SOURCE_REGION}:{account}:snapshot:{source_snap}"
68+
target_snap_id = f"copy-of-{re.sub('rds:', '', source_snap)}"
69+
print(f"Will copy {source_snap_arn} to {target_snap_id}")
4770

4871
try:
4972
target_client.copy_db_snapshot(
@@ -53,31 +76,34 @@ def copy_rds_snapshots(source_client, target_client, account, name):
5376
CopyTags=True,
5477
SourceRegion=SOURCE_REGION,
5578
)
56-
except botocore.exceptions.ClientError as e:
57-
raise Exception("Could not issue copy command: %s" % e)
79+
except botocore.exceptions.ClientError as ex:
80+
raise BackupException(f"Could not issue copy command: {ex}") from ex
5881

5982
copied_snaps = target_client.describe_db_snapshots(SnapshotType="manual", DBInstanceIdentifier=name)["DBSnapshots"]
6083
if len(copied_snaps) > KEEP:
61-
for snap in sorted(copied_snaps, key=byTimestamp, reverse=True)[KEEP:]:
62-
print("Will remove {}".format(snap["DBSnapshotIdentifier"]))
84+
for snap in sorted(copied_snaps, key=by_timestamp, reverse=True)[KEEP:]:
85+
print(f"Will remove {snap['DBSnapshotIdentifier']}")
6386
try:
6487
target_client.delete_db_snapshot(DBSnapshotIdentifier=snap["DBSnapshotIdentifier"])
65-
except botocore.exceptions.ClientError as e:
66-
raise Exception("Could not delete snapshot {}: {}".format(snap["DBSnapshotIdentifier"], e))
88+
except botocore.exceptions.ClientError as ex:
89+
raise BackupException(f"Could not delete snapshot {snap['DBSnapshotIdentifier']}: {ex}") from ex
6790

6891

6992
def copy_cluster_snapshots(source_client, target_client, account, cluster_name):
70-
print("Copying snapshots for {}".format(cluster_name))
93+
"""
94+
Coppies snapshots from a RDS cluster
95+
"""
96+
print(f"Copying snapshots for {cluster_name}")
7197
source_snaps = source_client.describe_db_cluster_snapshots(
7298
SnapshotType="automated", DBClusterIdentifier=cluster_name
7399
)["DBClusterSnapshots"]
74100
if len(source_snaps) == 0:
75101
print("Found no automated snapshots. Nothing to do")
76102
return
77-
source_snap = sorted(source_snaps, key=byClusterSnapshotId, reverse=True)[0]["DBClusterSnapshotIdentifier"]
78-
source_snap_arn = "arn:aws:rds:{}:{}:cluster-snapshot:{}".format(SOURCE_REGION, account, source_snap)
79-
target_snap_id = "copy-of-{}".format(re.sub("rds:", "", source_snap))
80-
print("Will copy {} to {}".format(source_snap_arn, target_snap_id))
103+
source_snap = sorted(source_snaps, key=by_cluster_snapshot_id, reverse=True)[0]["DBClusterSnapshotIdentifier"]
104+
source_snap_arn = f"arn:aws:rds:{SOURCE_REGION}:{account}:cluster-snapshot:{source_snap}"
105+
target_snap_id = f"copy-of-{re.sub('rds:', '', source_snap)}"
106+
print(f"Will copy {source_snap_arn} to {target_snap_id}")
81107

82108
target_client.copy_db_cluster_snapshot(
83109
SourceDBClusterSnapshotIdentifier=source_snap_arn,
@@ -90,16 +116,22 @@ def copy_cluster_snapshots(source_client, target_client, account, cluster_name):
90116
"DBClusterSnapshots"
91117
]
92118
if len(copied_snaps) > KEEP:
93-
for snap in sorted(copied_snaps, key=byTimestamp, reverse=True)[KEEP:]:
119+
for snap in sorted(copied_snaps, key=by_timestamp, reverse=True)[KEEP:]:
94120
snap_id = snap["DBClusterSnapshotIdentifier"]
95-
print("Will remove {}".format(snap_id))
121+
print(f"Will remove {snap_id}")
96122
try:
97123
target_client.delete_db_snapshot(DBClusterSnapshotIdentifier=snap_id)
98-
except botocore.exceptions.ClientError as e:
99-
raise Exception("Could not delete snapshot {}: {}".format(snap_id, e))
124+
except botocore.exceptions.ClientError as ex:
125+
raise BackupException(f"Could not delete snapshot {snap_id}: {ex}") from ex
100126

101127

102128
def lambda_handler(event, context):
129+
"""
130+
Entrypoint for AWS Lambda
131+
"""
132+
if context:
133+
print(f"Starting '{context.function_name}' version {context.function_version}")
134+
103135
target_region = event["region"]
104136
account = event["account"]
105137
source_client = boto3.client("rds", region_name=SOURCE_REGION)

requirements.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
boto3
2+
botocore

0 commit comments

Comments
 (0)