1919from ._errors import (
2020 EC2InstanceNotFoundError ,
2121 EC2InsufficientCapacityError ,
22- EC2TooManyInstancesError ,
2322)
2423from ._models import (
2524 AWSTagKey ,
2928 EC2Tags ,
3029 Resources ,
3130)
32- from ._utils import compose_user_data , ec2_instance_data_from_aws_instance
31+ from ._utils import (
32+ check_max_number_of_instances_not_exceeded ,
33+ compose_user_data ,
34+ ec2_instance_data_from_aws_instance ,
35+ )
3336
3437_logger = logging .getLogger (__name__ )
3538
@@ -127,34 +130,29 @@ async def launch_instances(
127130
128131 Arguments:
129132 instance_config -- The EC2 instance configuration
130- min_number_of_instances -- the minimal number of instances needed (fails if this amount cannot be reached)
133+ min_number_of_instances -- the minimal number of instances required (fails if this amount cannot be reached)
131134 number_of_instances -- the ideal number of instances needed (it it cannot be reached AWS will return a number >=min_number_of_instances)
132-
133- Keyword Arguments:
134- max_total_number_of_instances -- The total maximum allowed number of instances for this given instance_config (default: {10})
135+ max_total_number_of_instances -- The total maximum allowed number of instances for this given instance_config
135136
136137 Raises:
137138 EC2TooManyInstancesError:
138139
139140 Returns:
140141 The created instance data infos
141142 """
143+
142144 with log_context (
143145 _logger ,
144146 logging .INFO ,
145147 msg = f"launch { number_of_instances } AWS instance(s) { instance_config .type .name } with { instance_config .tags = } " ,
146148 ):
147149 # first check the max amount is not already reached
148- current_instances = await self .get_instances (
149- key_names = [instance_config .key_name ], tags = instance_config .tags
150+ await check_max_number_of_instances_not_exceeded (
151+ self ,
152+ instance_config ,
153+ required_number_instances = number_of_instances ,
154+ max_total_number_of_instances = max_total_number_of_instances ,
150155 )
151- if (
152- len (current_instances ) + number_of_instances
153- > max_total_number_of_instances
154- ):
155- raise EC2TooManyInstancesError (
156- num_instances = max_total_number_of_instances
157- )
158156
159157 resource_tags : list [TagTypeDef ] = [
160158 {"Key" : tag_key , "Value" : tag_value }
@@ -215,9 +213,7 @@ async def launch_instances(
215213 continue
216214 # For any other ClientError, re-raise to let the decorator handle it
217215 raise
218- except Exception :
219- # For any other error (not AWS-related), fail immediately
220- raise
216+
221217 else :
222218 # All subnets failed with capacity errors
223219 _logger .error (
@@ -231,32 +227,25 @@ async def launch_instances(
231227 instance_type = instance_config .type .name ,
232228 )
233229 instance_ids = [i ["InstanceId" ] for i in instances ["Instances" ]]
234- _logger .info (
235- "%s New instances launched: %s, waiting for them to start now..." ,
236- len (instance_ids ),
237- instance_ids ,
238- )
239-
240- # wait for the instance to be in a pending state
241- # NOTE: reference to EC2 states https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html
242- waiter = self .client .get_waiter ("instance_exists" )
243- await waiter .wait (InstanceIds = instance_ids )
244- _logger .debug ("instances %s exists now." , instance_ids )
230+ with log_context (
231+ _logger ,
232+ logging .INFO ,
233+ msg = f"{ len (instance_ids )} instances: { instance_ids = } launched. Wait to reach pending state" ,
234+ ):
235+ # wait for the instance to be in a pending state
236+ # NOTE: reference to EC2 states https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html
237+ waiter = self .client .get_waiter ("instance_exists" )
238+ await waiter .wait (InstanceIds = instance_ids )
245239
246- # NOTE: waiting for pending ensure we get all the IPs back
240+ # NOTE: waiting for pending ensures we get all the IPs back
247241 described_instances = await self .client .describe_instances (
248242 InstanceIds = instance_ids
249243 )
250244 assert "Instances" in described_instances ["Reservations" ][0 ] # nosec
251- instance_datas = [
245+ return [
252246 await ec2_instance_data_from_aws_instance (self , i )
253247 for i in described_instances ["Reservations" ][0 ]["Instances" ]
254248 ]
255- _logger .info (
256- "%s are pending now" ,
257- f"{ instance_ids = } " ,
258- )
259- return instance_datas
260249
261250 @ec2_exception_handler (_logger )
262251 async def get_instances (
0 commit comments