Repository navigation
Expand file tree
/
Copy pathlambda_function.py
More file actions
54 lines (44 loc) · 2.2 KB
/
Copy pathlambda_function.py
File metadata and controls
54 lines (44 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import urllib.parse
import boto3
import json
from datetime import datetime
print('Loading function')
s3 = boto3.resource('s3')
s3_client = boto3.client('s3')
def lambda_handler(event, context):
sns_message = json.loads(event['Records'][0]['Sns']['Message'])
record = sns_message['Records'][0]
target_bucket = context.function_name[:-1]
source_bucket = str(record['s3']['bucket']['name'])
key = str(urllib.parse.unquote_plus(record['s3']['object']['key']))
# Stop cascading deletes: ignore S3 delete events triggered by a delete Lambda (e.g. "...:bahaimedia-sgd")
principal_id = record.get('userIdentity', {}).get('principalId', '')
if principal_id.endswith(f":{source_bucket}d"):
print(f"Skipping cascading delete of {key} from {source_bucket}: triggered by Lambda ({principal_id})")
return
# Parse S3 eventTime (e.g. "2026-10-15T02:41:38.123Z") as timezone-aware UTC datetime
event_time = datetime.fromisoformat(record['eventTime'].replace('Z', '+00:00'))
obj = s3.Object(target_bucket, key)
try:
obj.load()
except Exception as e:
print(f"Did not delete {key} from {target_bucket} because target object does not exist: {e}")
return
# 1. Only delete if the object in target_bucket is older than the delete event
if obj.last_modified >= event_time:
print(f"Skipping delete of {key} in {target_bucket}: target object ({obj.last_modified}) is newer than or equal to delete event ({event_time})")
return
# 2. Check if source_bucket now has a live/newer file (e.g. quick re-upload after delete)
try:
src_head = s3_client.head_object(Bucket=source_bucket, Key=key)
if src_head['LastModified'] >= event_time:
print(f"Skipping delete of {key} in {target_bucket}: source bucket {source_bucket} has a newer object ({src_head['LastModified']})")
return
except Exception:
# 404 NotFound (or 403 Forbidden without s3:ListBucket) in source_bucket is expected when the file is genuinely deleted
pass
print(f"Deleting {key} from bucket {target_bucket}")
try:
obj.delete()
except Exception as e:
print("Did not delete because of error", e)