181
181
AWS_REGION = "ap-southeast-1"
182
182
INSTANCE_TYPE = "t4g.micro"
183
183
SECURITY_GROUPS = ["sg-0a883ca614ebfbae0" , "sg-014d326be5a1627dc" ]
184
- IAM_PROFILE = "pg-ap-southeast-1"
185
184
SSH_PORT = 22
186
185
SSH_TIMEOUT = 60
187
186
HEALTH_CHECK_TIMEOUT = 300 # 5 minutes
@@ -198,30 +197,27 @@ def decorator(func):
198
197
@wraps (func )
199
198
def wrapper (* args , ** kwargs ):
200
199
delay = initial_delay
201
- for attempt in range (max_retries ):
200
+ for i in range (max_retries ):
202
201
try :
203
202
return func (* args , ** kwargs )
204
203
except exceptions as e :
205
- if attempt == max_retries - 1 :
206
- logger .error (f"Operation failed after { max_retries } attempts: { str (e )} " )
204
+ if i == max_retries - 1 :
207
205
raise
208
- logger .warning (f"Attempt { attempt + 1 } /{ max_retries } failed: { str (e )} " )
206
+ logger .warning (
207
+ f"Attempt { i + 1 } failed: { str (e )} . Retrying in { delay } seconds..."
208
+ )
209
209
sleep (delay )
210
210
delay = min (delay * 2 , max_delay )
211
211
return None
212
212
return wrapper
213
213
return decorator
214
214
215
- def validate_aws_resources (ec2_client , iam_client ) -> None :
215
+ def validate_aws_resources (ec2_client ) -> None :
216
216
"""Validate AWS resources before instance creation."""
217
217
try :
218
218
# Check security groups
219
219
for sg in SECURITY_GROUPS :
220
220
ec2_client .describe_security_groups (GroupIds = [sg ])
221
-
222
- # Check IAM role
223
- iam_client .get_instance_profile (InstanceProfileName = IAM_PROFILE )
224
-
225
221
logger .info ("AWS resources validation successful" )
226
222
except ClientError as e :
227
223
logger .error (f"AWS resource validation failed: { str (e )} " )
@@ -246,7 +242,6 @@ def create_ec2_instance(ec2_resource, image_id: str, user_data: str) -> Any:
246
242
"HttpTokens" : "required" ,
247
243
"HttpEndpoint" : "enabled" ,
248
244
},
249
- IamInstanceProfile = {"Name" : IAM_PROFILE },
250
245
InstanceType = INSTANCE_TYPE ,
251
246
MinCount = 1 ,
252
247
MaxCount = 1 ,
@@ -309,11 +304,10 @@ def wait_for_ssh(ip_address: str) -> None:
309
304
sleep (10 )
310
305
311
306
@retry_with_backoff ()
312
- def get_ssh_connection (instance_ip : str , ssh_identity_file : str ) -> Any :
307
+ def get_ssh_connection (instance_ip : str ) -> Any :
313
308
"""Get SSH connection with retries."""
314
309
return testinfra .get_host (
315
- f"paramiko://ubuntu@{ instance_ip } ?timeout={ SSH_TIMEOUT } " ,
316
- ssh_identity_file = ssh_identity_file ,
310
+ f"paramiko://ubuntu@{ instance_ip } ?timeout={ SSH_TIMEOUT } "
317
311
)
318
312
319
313
def check_service_health (host : Any , service : str , check : Callable ) -> bool :
@@ -328,7 +322,7 @@ def check_service_health(host: Any, service: str, check: Callable) -> bool:
328
322
logger .warning (f"Connection failed during { service } check: { str (e )} " )
329
323
return False
330
324
331
- def is_healthy (host : Any , instance_ip : str , ssh_identity_file : str ) -> bool :
325
+ def is_healthy (host : Any , instance_ip : str ) -> bool :
332
326
"""Check if all services are healthy."""
333
327
health_checks = [
334
328
("postgres" , lambda h : h .run ("sudo -u postgres /usr/bin/pg_isready -U postgres" )),
@@ -350,11 +344,11 @@ def is_healthy(host: Any, instance_ip: str, ssh_identity_file: str) -> bool:
350
344
return False
351
345
return True
352
346
353
- def wait_for_healthy (host : Any , instance_ip : str , ssh_identity_file : str ) -> None :
347
+ def wait_for_healthy (host : Any , instance_ip : str ) -> None :
354
348
"""Wait for all services to be healthy with timeout."""
355
349
start_time = time .time ()
356
350
while time .time () - start_time < HEALTH_CHECK_TIMEOUT :
357
- if is_healthy (host , instance_ip , ssh_identity_file ):
351
+ if is_healthy (host , instance_ip ):
358
352
logger .info ("All services are healthy" )
359
353
return
360
354
sleep (HEALTH_CHECK_INTERVAL )
@@ -365,13 +359,12 @@ def host():
365
359
"""Create and manage an EC2 instance for testing."""
366
360
instance = None
367
361
try :
368
- # Initialize AWS clients
362
+ # Initialize AWS clients using environment variables
369
363
ec2_resource = boto3 .resource ("ec2" , region_name = AWS_REGION )
370
364
ec2_client = boto3 .client ("ec2" , region_name = AWS_REGION )
371
- iam_client = boto3 .client ("iam" , region_name = AWS_REGION )
372
365
373
- # Validate AWS resources
374
- validate_aws_resources (ec2_client , iam_client )
366
+ # Validate AWS resources (now only checks security groups)
367
+ validate_aws_resources (ec2_client )
375
368
376
369
# Get AMI
377
370
images = list (ec2_resource .images .filter (
@@ -381,10 +374,10 @@ def host():
381
374
raise ValueError (f"Expected exactly one AMI, found { len (images )} " )
382
375
image = images [0 ]
383
376
384
- # Create instance
385
377
def gzip_then_base64_encode (s : str ) -> str :
386
378
return base64 .b64encode (gzip .compress (s .encode ())).decode ()
387
379
380
+ # Modified user data to remove AWS-specific commands
388
381
user_data = f"""#cloud-config
389
382
hostname: db-aaaaaaaaaaaaaaaaaaaa
390
383
write_files:
@@ -398,49 +391,23 @@ def gzip_then_base64_encode(s: str) -> str:
398
391
- {{path: /tmp/init.json, content: { gzip_then_base64_encode (init_json_content )} , permissions: '0600', encoding: gz+b64}}
399
392
runcmd:
400
393
- 'sudo echo \" pgbouncer\" \" postgres\" >> /etc/pgbouncer/userlist.txt'
401
- - 'cd /tmp && aws s3 cp --region ap-southeast-1 s3://init-scripts-staging/project/init.sh .'
402
- - 'bash init.sh "staging"'
394
+ - 'bash /tmp/init.sh "staging"'
403
395
- 'rm -rf /tmp/*'
404
396
"""
405
-
406
397
instance = create_ec2_instance (ec2_resource , image .id , user_data )
407
398
logger .info (f"Created instance { instance .id } " )
408
399
409
400
# Wait for instance to be running
410
401
wait_for_instance_running (instance )
411
-
412
- # Set up EC2 Instance Connect
413
- ec2logger = EC2InstanceConnectLogger (debug = False )
414
- temp_key = EC2InstanceConnectKey (ec2logger .get_logger ())
415
- ec2ic = boto3 .client ("ec2-instance-connect" , region_name = AWS_REGION )
416
-
417
- @retry_with_backoff ()
418
- def send_ssh_key ():
419
- response = ec2ic .send_ssh_public_key (
420
- InstanceId = instance .id ,
421
- InstanceOSUser = "ubuntu" ,
422
- SSHPublicKey = temp_key .get_pub_key (),
423
- )
424
- if not response ["Success" ]:
425
- raise Exception ("Failed to send SSH public key" )
426
-
427
- send_ssh_key ()
428
-
429
- # Wait for public IP and SSH
430
- ip_address = wait_for_public_ip (instance )
431
- wait_for_ssh (ip_address )
402
+ instance_ip = wait_for_public_ip (instance )
403
+ wait_for_ssh (instance_ip )
432
404
433
405
# Get SSH connection
434
- host = get_ssh_connection (ip_address , temp_key .get_priv_key_file ())
435
-
436
- # Wait for services to be healthy
437
- wait_for_healthy (host , ip_address , temp_key .get_priv_key_file ())
406
+ host = get_ssh_connection (instance_ip )
407
+ wait_for_healthy (host , instance_ip )
438
408
439
409
yield host
440
410
441
- except Exception as e :
442
- logger .error (f"Error in host fixture: { str (e )} " )
443
- raise
444
411
finally :
445
412
if instance :
446
413
try :
0 commit comments