@@ -195,6 +195,7 @@ def _handle_create_cfn_template_request(self, app_id, semver, key, logical_id):
195
195
ApplicationId = self ._sanitize_sar_str_param (app_id ), SemanticVersion = self ._sanitize_sar_str_param (semver )
196
196
)
197
197
response = self ._sar_service_call (create_cfn_template , logical_id , app_id , semver )
198
+
198
199
LOG .info ("Requested to create CFN template {}/{} in serverless application repo." .format (app_id , semver ))
199
200
self ._applications [key ] = response [self .TEMPLATE_URL_KEY ]
200
201
if response ["Status" ] != "ACTIVE" :
@@ -303,57 +304,73 @@ def on_after_transform_template(self, template):
303
304
:param dict template: Dictionary of the SAM template
304
305
:return: Nothing
305
306
"""
306
- if self ._wait_for_template_active_status and not self ._validate_only :
307
- start_time = time ()
308
- while (time () - start_time ) < self .TEMPLATE_WAIT_TIMEOUT_SECONDS :
309
- temp = self ._in_progress_templates
310
- self ._in_progress_templates = []
311
-
312
- # Check each resource to make sure it's active
313
- LOG .info ("Checking resources in serverless application repo..." )
314
- for application_id , template_id in temp :
315
- get_cfn_template = (
316
- lambda application_id , template_id : self ._sar_client .get_cloud_formation_template (
317
- ApplicationId = self ._sanitize_sar_str_param (application_id ),
318
- TemplateId = self ._sanitize_sar_str_param (template_id ),
319
- )
320
- )
321
- response = self ._sar_service_call (get_cfn_template , application_id , application_id , template_id )
322
- self ._handle_get_cfn_template_response (response , application_id , template_id )
323
- LOG .info ("Finished checking resources in serverless application repo." )
307
+ if not self ._wait_for_template_active_status or self ._validate_only :
308
+ return
324
309
325
- # Don't sleep if there are no more templates with PREPARING status
326
- if len (self ._in_progress_templates ) == 0 :
327
- break
310
+ start_time = time ()
311
+ while (time () - start_time ) < self .TEMPLATE_WAIT_TIMEOUT_SECONDS :
312
+ # Check each resource to make sure it's active
313
+ LOG .info ("Checking resources in serverless application repo..." )
314
+ idx = 0
315
+ while idx < len (self ._in_progress_templates ):
316
+ application_id , template_id = self ._in_progress_templates [idx ]
317
+ get_cfn_template = lambda application_id , template_id : self ._sar_client .get_cloud_formation_template (
318
+ ApplicationId = self ._sanitize_sar_str_param (application_id ),
319
+ TemplateId = self ._sanitize_sar_str_param (template_id ),
320
+ )
328
321
329
- # Sleep a little so we don't spam service calls
330
- sleep (self .SLEEP_TIME_SECONDS )
322
+ try :
323
+ response = self ._sar_service_call (get_cfn_template , application_id , application_id , template_id )
324
+ except ClientError as e :
325
+ error_code = e .response ["Error" ]["Code" ]
326
+ if error_code == "TooManyRequestsException" :
327
+ LOG .debug ("SAR call timed out for application id {}" .format (application_id ))
328
+ break # We were throttled by SAR, break out to a sleep
329
+ else :
330
+ raise e
331
+
332
+ if self ._is_template_active (response , application_id , template_id ):
333
+ self ._in_progress_templates .remove ((application_id , template_id ))
334
+ else :
335
+ idx += 1 # check next template
336
+
337
+ LOG .info ("Finished checking resources in serverless application repo." )
338
+
339
+ # Don't sleep if there are no more templates with PREPARING status
340
+ if len (self ._in_progress_templates ) == 0 :
341
+ break
342
+
343
+ # Sleep a little so we don't spam service calls
344
+ sleep (self ._get_sleep_time_sec ())
345
+
346
+ # Not all templates reached active status
347
+ if len (self ._in_progress_templates ) != 0 :
348
+ application_ids = [items [0 ] for items in self ._in_progress_templates ]
349
+ raise InvalidResourceException (
350
+ application_ids , "Timed out waiting for nested stack templates " "to reach ACTIVE status."
351
+ )
331
352
332
- # Not all templates reached active status
333
- if len (self ._in_progress_templates ) != 0 :
334
- application_ids = [items [0 ] for items in self ._in_progress_templates ]
335
- raise InvalidResourceException (
336
- application_ids , "Timed out waiting for nested stack templates " "to reach ACTIVE status."
337
- )
353
+ def _get_sleep_time_sec (self ):
354
+ return self .SLEEP_TIME_SECONDS
338
355
339
- def _handle_get_cfn_template_response (self , response , application_id , template_id ):
356
+ def _is_template_active (self , response , application_id , template_id ):
340
357
"""
341
- Handles the response from the SAR service call
358
+ Checks the response from a SAR service call; returns True if the template is active,
359
+ throws an exception if the request expired and returns False in all other cases.
342
360
343
361
:param dict response: the response dictionary from the app repo
344
362
:param string application_id: the ApplicationId
345
363
:param string template_id: the unique TemplateId for this application
346
364
"""
347
- status = response ["Status" ]
348
- if status != "ACTIVE" :
349
- # Other options are PREPARING and EXPIRED.
350
- if status == "EXPIRED" :
351
- message = (
352
- "Template for {} with id {} returned status: {}. Cannot access an expired "
353
- "template." .format (application_id , template_id , status )
354
- )
355
- raise InvalidResourceException (application_id , message )
356
- self ._in_progress_templates .append ((application_id , template_id ))
365
+ status = response ["Status" ] # options: PREPARING, EXPIRED or ACTIVE
366
+
367
+ if status == "EXPIRED" :
368
+ message = "Template for {} with id {} returned status: {}. Cannot access an expired " "template." .format (
369
+ application_id , template_id , status
370
+ )
371
+ raise InvalidResourceException (application_id , message )
372
+
373
+ return status == "ACTIVE"
357
374
358
375
@cw_timer (prefix = "External" , name = "SAR" )
359
376
def _sar_service_call (self , service_call_lambda , logical_id , * args ):
@@ -372,9 +389,6 @@ def _sar_service_call(self, service_call_lambda, logical_id, *args):
372
389
error_code = e .response ["Error" ]["Code" ]
373
390
if error_code in ("AccessDeniedException" , "NotFoundException" ):
374
391
raise InvalidResourceException (logical_id , e .response ["Error" ]["Message" ])
375
-
376
- # 'ForbiddenException'- SAR rejects connection
377
- LOG .exception (e )
378
392
raise e
379
393
380
394
def _resource_is_supported (self , resource_type ):
0 commit comments