1
1
import os
2
2
import boto3
3
3
import time
4
- from ec2instanceconnectcli import EC2InstanceConnectCLI
4
+ import socket
5
+ import logging
6
+ from ec2instanceconnectcli .EC2InstanceConnectLogger import EC2InstanceConnectLogger
7
+ from ec2instanceconnectcli .EC2InstanceConnectKey import EC2InstanceConnectKey
5
8
6
9
# Initialize boto3 clients
7
- ec2_client = boto3 .client ('ec2' )
8
- ec2_resource = boto3 .resource ('ec2' )
10
+ ec2_client = boto3 .client ('ec2' , region_name = "ap-southeast-1" )
11
+ ec2_resource = boto3 .resource ('ec2' , region_name = "ap-southeast-1" )
12
+
13
+ # Set up logging
14
+ logger = logging .getLogger ("ami-resize" )
15
+ handler = logging .StreamHandler ()
16
+ formatter = logging .Formatter ('%(asctime)s %(name)-12s %(levelname)-8s %(message)s' )
17
+ handler .setFormatter (formatter )
18
+ logger .addHandler (handler )
19
+ logger .setLevel (logging .DEBUG )
9
20
10
21
def launch_temporary_instance ():
11
- # Describe the AMI
12
22
AMI_NAME = os .environ .get ('PRE_AMI_NAME' )
23
+ logger .info (f"Searching for AMI with name: { AMI_NAME } " )
13
24
images = ec2_client .describe_images (Owners = ['self' ], Filters = [{'Name' : 'name' , 'Values' : [AMI_NAME ]}])
25
+ logger .debug (f"Describe images response: { images } " )
14
26
if not images ['Images' ]:
15
27
raise Exception (f"No AMI found with name: { AMI_NAME } " )
16
28
image_id = images ['Images' ][0 ]['ImageId' ]
29
+ logger .info (f"Found AMI: { image_id } " )
17
30
18
- # Launch the instance
19
31
instance = ec2_resource .create_instances (
20
32
ImageId = image_id ,
21
33
InstanceType = 't4g.micro' ,
@@ -24,20 +36,57 @@ def launch_temporary_instance():
24
36
TagSpecifications = [
25
37
{
26
38
'ResourceType' : 'instance' ,
27
- 'Tags' : [{'Key' : 'Name' , 'Value' : 'AMI-Resize-Temp' }]
39
+ 'Tags' : [
40
+ {'Key' : 'Name' , 'Value' : 'AMI-Resize-Temp' },
41
+ {'Key' : 'creator' , 'Value' : 'ami-resize-script' },
42
+ {'Key' : 'resize-run-id' , 'Value' : os .environ .get ("GITHUB_RUN_ID" , "local-run" )}
43
+ ]
28
44
}
29
- ]
45
+ ],
46
+ NetworkInterfaces = [
47
+ {
48
+ 'DeviceIndex' : 0 ,
49
+ 'AssociatePublicIpAddress' : True ,
50
+ 'Groups' : ["sg-0a883ca614ebfbae0" , "sg-014d326be5a1627dc" ],
51
+ }
52
+ ],
30
53
)[0 ]
31
54
32
- print (f"Launched instance: { instance .id } " )
55
+ logger . info (f"Launched instance: { instance .id } " )
33
56
return instance .id
34
57
35
58
def wait_for_instance_running (instance_id ):
36
59
instance = ec2_resource .Instance (instance_id )
37
60
instance .wait_until_running ()
38
- print (f"Instance { instance_id } is now running" )
61
+ logger .info (f"Instance { instance_id } is now running" )
62
+
63
+
64
+ while not instance .public_ip_address :
65
+ logger .warning ("Waiting for IP to be available" )
66
+ time .sleep (5 )
67
+ instance .reload ()
68
+
69
+ while True :
70
+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
71
+ if sock .connect_ex ((instance .public_ip_address , 22 )) == 0 :
72
+ break
73
+ else :
74
+ logger .warning ("Waiting for SSH to be available" )
75
+ time .sleep (10 )
76
+
77
+ return instance .public_ip_address
39
78
40
79
def resize_filesystem (instance_id ):
80
+ ec2logger = EC2InstanceConnectLogger (debug = False )
81
+ temp_key = EC2InstanceConnectKey (ec2logger .get_logger ())
82
+ ec2ic = boto3 .client ("ec2-instance-connect" , region_name = "ap-southeast-1" )
83
+ response = ec2ic .send_ssh_public_key (
84
+ InstanceId = instance_id ,
85
+ InstanceOSUser = "ubuntu" ,
86
+ SSHPublicKey = temp_key .get_pub_key (),
87
+ )
88
+ assert response ["Success" ]
89
+
41
90
cli = EC2InstanceConnectCLI ()
42
91
command = "sudo e2fsck -f /dev/sda1 && sudo resize2fs /dev/sda1 8G && sudo sync"
43
92
cli .start_session (instance_id = instance_id , command = command )
@@ -50,13 +99,13 @@ def create_new_ami(instance_id):
50
99
Description = "Resized AMI"
51
100
)
52
101
new_ami_id = response ['ImageId' ]
53
- print (f"Created new AMI: { new_ami_id } with name: { new_ami_name } " )
102
+ logger . info (f"Created new AMI: { new_ami_id } with name: { new_ami_name } " )
54
103
return new_ami_id , new_ami_name
55
104
56
105
def wait_for_ami_available (ami_id ):
57
106
waiter = ec2_client .get_waiter ('image_available' )
58
107
waiter .wait (ImageIds = [ami_id ])
59
- print (f"AMI { ami_id } is now available" )
108
+ logger . info (f"AMI { ami_id } is now available" )
60
109
61
110
def modify_ami_block_device_mapping (ami_id ):
62
111
ec2_client .modify_image_attribute (
@@ -68,16 +117,16 @@ def modify_ami_block_device_mapping(ami_id):
68
117
}
69
118
]
70
119
)
71
- print (f"Modified block device mapping for AMI { ami_id } " )
120
+ logger . info (f"Modified block device mapping for AMI { ami_id } " )
72
121
73
122
def terminate_instance (instance_id ):
74
123
ec2_resource .Instance (instance_id ).terminate ()
75
- print (f"Terminated instance { instance_id } " )
124
+ logger . info (f"Terminated instance { instance_id } " )
76
125
77
126
def main ():
78
127
try :
79
128
instance_id = launch_temporary_instance ()
80
- wait_for_instance_running (instance_id )
129
+ public_ip = wait_for_instance_running (instance_id )
81
130
resize_filesystem (instance_id )
82
131
new_ami_id , new_ami_name = create_new_ami (instance_id )
83
132
wait_for_ami_available (new_ami_id )
0 commit comments