Skip to content

Commit b025060

Browse files
feat: enhance Lambda logging and fix CDK deployment
- Add comprehensive JSON-structured logging to Lambda function - Log configuration and thresholds at startup - Add execution_id tracking throughout - Include policy match statistics and performance metrics - Structured extras for CloudWatch JSON parsing - Fix CDK deployment without Docker - Add bundle-lambda command to justfile - Install dependencies directly with uv pip --target - Update deploy commands to include bundling step - Update .gitignore for Lambda dependencies - Exclude build-time dependencies and dist-info folders - Keep lambda source code tracked - Fix Lambda handler bugs - Change request_id to aws_request_id for context - Ensure proper module imports with bundled dependencies
1 parent c4e66c5 commit b025060

File tree

6 files changed

+252
-50
lines changed

6 files changed

+252
-50
lines changed

IaC/cdk/aws-resources-cleanup/.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,32 @@ Thumbs.db
5353
*.zip
5454
/tmp/
5555

56+
# Lambda dependencies (installed at build time)
57+
lambda/*.dist-info/
58+
lambda/bin/
59+
lambda/boto3/
60+
lambda/boto3-*.dist-info/
61+
lambda/botocore/
62+
lambda/botocore-*.dist-info/
63+
lambda/aws_lambda_powertools/
64+
lambda/aws_lambda_powertools-*.dist-info/
65+
lambda/aws_xray_sdk/
66+
lambda/aws_xray_sdk-*.dist-info/
67+
lambda/s3transfer/
68+
lambda/s3transfer-*.dist-info/
69+
lambda/jmespath/
70+
lambda/jmespath-*.dist-info/
71+
lambda/dateutil/
72+
lambda/python_dateutil-*.dist-info/
73+
lambda/urllib3/
74+
lambda/urllib3-*.dist-info/
75+
lambda/six.py
76+
lambda/six-*.dist-info/
77+
lambda/typing_extensions.py
78+
lambda/typing_extensions-*.dist-info/
79+
lambda/wrapt/
80+
lambda/wrapt-*.dist-info/
81+
lambda/.lock
82+
5683
# Logs
5784
*.log

IaC/cdk/aws-resources-cleanup/justfile

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,20 @@ bootstrap:
6666
--region {{region}}
6767

6868
# Synthesize CloudFormation template
69-
synth:
69+
synth: bundle-lambda
7070
@echo "Synthesizing CloudFormation template..."
7171
uv run cdk synth --profile {{profile}} --region {{region}}
7272

7373
# Deploy in DRY_RUN mode (default, safe)
74-
deploy:
74+
deploy: bundle-lambda
7575
@echo "Deploying in DRY_RUN mode (safe)..."
7676
uv run cdk deploy \
7777
--profile {{profile}} \
7878
--region {{region}} \
7979
--require-approval never
8080

8181
# Deploy in LIVE mode (destructive, requires confirmation)
82-
deploy-live:
82+
deploy-live: bundle-lambda
8383
@echo "⚠️ WARNING: Deploying in LIVE mode (will delete resources!)"
8484
@echo "Press Ctrl+C to cancel, or Enter to continue..."
8585
@read _
@@ -90,7 +90,7 @@ deploy-live:
9090
--require-approval never
9191

9292
# Deploy with custom parameters
93-
deploy-custom DRY_RUN="true" THRESHOLD="30" EMAIL="":
93+
deploy-custom DRY_RUN="true" THRESHOLD="30" EMAIL="": bundle-lambda
9494
@echo "Deploying with custom parameters..."
9595
uv run cdk deploy \
9696
--profile {{profile}} \
@@ -224,10 +224,17 @@ list-lambdas:
224224
--query 'Functions[?starts_with(FunctionName, `Lambda`)].{Name:FunctionName,Runtime:Runtime,Size:CodeSize,Modified:LastModified}' \
225225
--output table
226226

227+
# Bundle Lambda with dependencies
228+
bundle-lambda:
229+
@echo "Bundling Lambda with dependencies..."
230+
@echo "Installing dependencies in lambda directory..."
231+
uv pip install -r lambda/aws_resource_cleanup/requirements.txt --target lambda/
232+
@echo "✓ Lambda bundled with dependencies"
233+
227234
# Update Lambda code only (faster than full deploy)
228-
update-code:
235+
update-code: bundle-lambda
229236
@echo "Building Lambda package..."
230-
cd lambda && zip -r /tmp/lambda-code.zip aws_resource_cleanup/
237+
cd lambda && zip -r /tmp/lambda-code.zip .
231238
@echo "Updating Lambda function code..."
232239
aws lambda update-function-code \
233240
--function-name {{lambda_function}} \

IaC/cdk/aws-resources-cleanup/lambda/aws_resource_cleanup/ec2/instances.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,36 @@ def execute_cleanup_action(action: CleanupAction, region: str) -> bool:
107107
if action.action == "TERMINATE":
108108
if DRY_RUN:
109109
logger.info(
110-
"Would TERMINATE instance",
110+
"[DRY-RUN] Would TERMINATE instance",
111111
extra={
112+
"action_type": "TERMINATE",
112113
"dry_run": True,
113-
"instance_id": action.instance_id,
114+
"resource": {
115+
"type": "instance",
116+
"id": action.instance_id,
117+
"name": action.name,
118+
"billing_tag": action.billing_tag,
119+
},
114120
"region": region,
115121
"reason": action.reason,
122+
"days_overdue": round(action.days_overdue, 2) if action.days_overdue else 0,
116123
},
117124
)
118125
else:
119126
logger.info(
120-
"TERMINATE instance",
127+
"EXECUTING: TERMINATE instance",
121128
extra={
122-
"instance_id": action.instance_id,
129+
"action_type": "TERMINATE",
130+
"dry_run": False,
131+
"resource": {
132+
"type": "instance",
133+
"id": action.instance_id,
134+
"name": action.name,
135+
"billing_tag": action.billing_tag,
136+
},
123137
"region": region,
124138
"reason": action.reason,
139+
"days_overdue": round(action.days_overdue, 2) if action.days_overdue else 0,
125140
},
126141
)
127142
ec2.terminate_instances(InstanceIds=[action.instance_id])
@@ -251,21 +266,36 @@ def execute_cleanup_action(action: CleanupAction, region: str) -> bool:
251266
elif action.action == "STOP":
252267
if DRY_RUN:
253268
logger.info(
254-
"Would STOP instance",
269+
"[DRY-RUN] Would STOP instance",
255270
extra={
271+
"action_type": "STOP",
256272
"dry_run": True,
257-
"instance_id": action.instance_id,
273+
"resource": {
274+
"type": "instance",
275+
"id": action.instance_id,
276+
"name": action.name,
277+
"billing_tag": action.billing_tag,
278+
},
258279
"region": region,
259280
"reason": action.reason,
281+
"days_overdue": round(action.days_overdue, 2) if action.days_overdue else 0,
260282
},
261283
)
262284
else:
263285
logger.info(
264-
"STOP instance",
286+
"EXECUTING: STOP instance",
265287
extra={
266-
"instance_id": action.instance_id,
288+
"action_type": "STOP",
289+
"dry_run": False,
290+
"resource": {
291+
"type": "instance",
292+
"id": action.instance_id,
293+
"name": action.name,
294+
"billing_tag": action.billing_tag,
295+
},
267296
"region": region,
268297
"reason": action.reason,
298+
"days_overdue": round(action.days_overdue, 2) if action.days_overdue else 0,
269299
},
270300
)
271301
ec2.stop_instances(InstanceIds=[action.instance_id])

IaC/cdk/aws-resources-cleanup/lambda/aws_resource_cleanup/ec2/policies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def check_untagged(
193193
days_running = minutes_running / 1440
194194
name = tags_dict.get("Name", "N/A")
195195

196-
reason = f"Missing billing tag. Running {minutes_running:.0f} minutes (threshold: {UNTAGGED_THRESHOLD_MINUTES})"
196+
reason = f"Missing billing tag. Running {minutes_running:.0f} minutes (threshold: {UNTAGGED_THRESHOLD_MINUTES} minutes)"
197197

198198
return CleanupAction(
199199
instance_id=instance["InstanceId"],

IaC/cdk/aws-resources-cleanup/lambda/aws_resource_cleanup/ec2/volumes.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,19 @@ def delete_volume(action: CleanupAction, region: str) -> bool:
171171

172172
if DRY_RUN:
173173
logger.info(
174-
"Would DELETE volume",
174+
"[DRY-RUN] Would DELETE volume",
175175
extra={
176+
"action_type": "DELETE_VOLUME",
176177
"dry_run": True,
177-
"volume_id": action.volume_id,
178+
"resource": {
179+
"type": "volume",
180+
"id": action.volume_id,
181+
"name": action.name,
182+
"billing_tag": action.billing_tag,
183+
},
178184
"region": region,
179185
"reason": action.reason,
186+
"days_old": round(action.days_overdue, 2) if action.days_overdue else 0,
180187
},
181188
)
182189
return True
@@ -211,11 +218,19 @@ def delete_volume(action: CleanupAction, region: str) -> bool:
211218
# Delete volume
212219
ec2.delete_volume(VolumeId=action.volume_id)
213220
logger.info(
214-
"DELETE volume",
221+
"EXECUTING: DELETE volume",
215222
extra={
216-
"volume_id": action.volume_id,
223+
"action_type": "DELETE_VOLUME",
224+
"dry_run": False,
225+
"resource": {
226+
"type": "volume",
227+
"id": action.volume_id,
228+
"name": action.name,
229+
"billing_tag": action.billing_tag,
230+
},
217231
"region": region,
218232
"reason": action.reason,
233+
"days_old": round(action.days_overdue, 2) if action.days_overdue else 0,
219234
},
220235
)
221236
return True

0 commit comments

Comments
 (0)