11import os
2+ import json
23from enum import Enum
34
45import boto3
910
1011@dataclass
1112class EnvironmentConfig :
12- subnet_id : str
13+ subnet_map : dict # Maps AZ to subnet ID
1314 security_group_id : str
1415
1516
@@ -38,7 +39,7 @@ class LifecycleActionResult(Enum):
3839
3940
4041class EnvironmentVariables (Enum ):
41- TARGET_SUBNET = "TARGET_SUBNET "
42+ TARGET_SUBNETS = "TARGET_SUBNETS "
4243 TARGET_SECURITY_GROUP_ID = "TARGET_SECURITY_GROUP_ID"
4344
4445
@@ -135,7 +136,18 @@ def __init__(self, config: EnvironmentConfig, aws_client: AwsClient):
135136 self .instance_data = {}
136137
137138 def process_event (self , event : Ec2LifecycleHookEvent ):
138- network_interface_id = self .aws_client .create_interface (self .config .subnet_id , self .config .security_group_id )
139+ # Get the AZ of the instance
140+ instance_az = self .instance_data ['Placement' ]['AvailabilityZone' ]
141+ logging .info (f"Instance { event .instance_id } is in AZ { instance_az } " )
142+
143+ # Find the matching management subnet for this AZ
144+ if instance_az not in self .config .subnet_map :
145+ raise Exception (f"No management subnet configured for AZ { instance_az } . Available AZs: { list (self .config .subnet_map .keys ())} " )
146+
147+ target_subnet_id = self .config .subnet_map [instance_az ]
148+ logging .info (f"Using management subnet { target_subnet_id } for AZ { instance_az } " )
149+
150+ network_interface_id = self .aws_client .create_interface (target_subnet_id , self .config .security_group_id )
139151 try :
140152 attachment_resp = self .aws_client .attach_interface (network_interface_id , event .instance_id )
141153 self .aws_client .modify_attachment_to_delete_on_termination (attachment_resp ["AttachmentId" ], network_interface_id )
@@ -179,21 +191,29 @@ def lambda_handler(event, context):
179191 parsed_event : Ec2LifecycleHookEvent = from_aws_event_bridge_json (event )
180192
181193 try :
194+ if not lifecycle_event_svc .should_process_event (parsed_event ):
195+ logging .error ("Event validation failed, abandoning lifecycle action" )
196+ lifecycle_event_svc .complete_lifecycle_action (parsed_event , LifecycleActionResult .ABANDON )
197+ return
198+
182199 lifecycle_event_svc .process_event (parsed_event )
183200 lifecycle_event_svc .complete_lifecycle_action (parsed_event , LifecycleActionResult .CONTINUE )
184201 logging .info ("Lifecycle action completed successfully" )
185202 except Exception as e :
186- logging .info (f"failed to process event: { e } " )
187- lifecycle_event_svc .complete_lifecycle_action (parsed_event , LifecycleActionResult .ABANDON )
203+ logging .error (f"failed to process event: { e } " )
204+ try :
205+ lifecycle_event_svc .complete_lifecycle_action (parsed_event , LifecycleActionResult .ABANDON )
206+ except Exception as complete_error :
207+ logging .error (f"Failed to complete lifecycle action with ABANDON: { complete_error } " )
188208 raise e
189209
190210
191211def parse_environment () -> EnvironmentConfig :
192- subnet = os .getenv (EnvironmentVariables .TARGET_SUBNET .value , "" )
212+ subnets_json = os .getenv (EnvironmentVariables .TARGET_SUBNETS .value , "" )
193213 security_group_id = os .getenv (EnvironmentVariables .TARGET_SECURITY_GROUP_ID .value , "" )
194214
195- if subnet == "" :
196- msg = f"environment variable ${ EnvironmentVariables .TARGET_SUBNET .value } is not defined"
215+ if subnets_json == "" :
216+ msg = f"environment variable ${ EnvironmentVariables .TARGET_SUBNETS .value } is not defined"
197217 logging .error (msg )
198218 raise Exception (msg )
199219
@@ -202,4 +222,11 @@ def parse_environment() -> EnvironmentConfig:
202222 logging .error (msg )
203223 raise Exception (msg )
204224
205- return EnvironmentConfig (subnet_id = subnet , security_group_id = security_group_id )
225+ try :
226+ subnet_map = json .loads (subnets_json )
227+ except json .JSONDecodeError as e :
228+ msg = f"Failed to parse TARGET_SUBNETS as JSON: { e } "
229+ logging .error (msg )
230+ raise Exception (msg )
231+
232+ return EnvironmentConfig (subnet_map = subnet_map , security_group_id = security_group_id )
0 commit comments