@@ -209,6 +209,9 @@ def add_default_resource_props(resource_props, stack_name, resource_name=None):
209209 if res_type == 'AWS::Lambda::EventSourceMapping' and not props .get ('StartingPosition' ):
210210 props ['StartingPosition' ] = 'LATEST'
211211
212+ if res_type == 'AWS::Lambda::Function' and not props .get ('FunctionName' ):
213+ props ['FunctionName' ] = '{}-lambda-{}' .format (stack_name [:45 ], short_uid ())
214+
212215 if res_type == 'AWS::SNS::Topic' and not props .get ('TopicName' ):
213216 props ['TopicName' ] = 'topic-%s' % short_uid ()
214217
@@ -248,8 +251,15 @@ def clean_json(resource_json, resources_map):
248251 LOG .info ('Potential circular dependency detected when resolving Ref "%s"' % resource_json ['Ref' ])
249252 return resource_json ['Ref' ]
250253 raise
251- if isinstance (result , BaseModel ):
252- if isinstance (resource_json , dict ) and 'Ref' in resource_json :
254+ if isinstance (resource_json , dict ):
255+ if isinstance (resource_json .get ('Fn::GetAtt' ), list ) and result == resource_json :
256+ # If the attribute cannot be resolved (i.e., result == resource_json), then return
257+ # an empty value, to avoid returning the original JSON struct (which otherwise
258+ # results in downstream issues, e.g., when concatenating template values).
259+ # TODO: Note that this workaround could point towards a general issue with
260+ # dependency resolution - in fact, this case should never be happening (but it does).
261+ return ''
262+ if 'Ref' in resource_json and isinstance (result , BaseModel ):
253263 entity_id = get_entity_id (result , resource_json )
254264 if entity_id :
255265 return entity_id
@@ -294,7 +304,7 @@ def _parse_and_create_resource(logical_id, resource_json, resources_map, region_
294304 return None
295305
296306 # parse and get final resource JSON
297- resource_tuple = parsing .parse_resource (logical_id , resource_json , resources_map )
307+ resource_tuple = parsing .parse_resource_and_generate_name (logical_id , resource_json , resources_map )
298308 if not resource_tuple :
299309 return None
300310 _ , resource_json , resource_name = resource_tuple
@@ -617,7 +627,9 @@ def SQS_Queue_physical_resource_id(self):
617627 result = SQS_Queue_physical_resource_id_orig .fget (self )
618628 if '://' not in result :
619629 # convert ID to queue URL
620- return aws_stack .get_sqs_queue_url (result )
630+ self ._physical_resource_id = (getattr (self , '_physical_resource_id' , None ) or
631+ aws_stack .get_sqs_queue_url (result ))
632+ return self ._physical_resource_id
621633 return result
622634
623635 SQS_Queue_physical_resource_id_orig = sqs_models .Queue .physical_resource_id
@@ -793,7 +805,7 @@ def Role_update_from_cloudformation_json(cls,
793805 if not hasattr (iam_models .Role , 'update_from_cloudformation_json' ):
794806 iam_models .Role .update_from_cloudformation_json = Role_update_from_cloudformation_json
795807
796- # patch ApiGateway Deployment
808+ # patch ApiGateway Deployment deletion
797809 @staticmethod
798810 def depl_delete_from_cloudformation_json (resource_name , resource_json , region_name ):
799811 properties = resource_json ['Properties' ]
@@ -802,7 +814,7 @@ def depl_delete_from_cloudformation_json(resource_name, resource_json, region_na
802814 if not hasattr (apigw_models .Deployment , 'delete_from_cloudformation_json' ):
803815 apigw_models .Deployment .delete_from_cloudformation_json = depl_delete_from_cloudformation_json
804816
805- # patch Lambda Version
817+ # patch Lambda Version deletion
806818 @staticmethod
807819 def vers_delete_from_cloudformation_json (resource_name , resource_json , region_name ):
808820 properties = resource_json ['Properties' ]
0 commit comments