@@ -738,3 +738,115 @@ def test_function_datasource_set_with_none():
738738 api = SamGraphQLApi ("MyApi" )
739739 none_datasource = api ._construct_none_datasource ("foo" )
740740 assert none_datasource
741+
742+
743+ class TestSamFunctionRoleResolver (TestCase ):
744+ """
745+ Tests for resolving IAM role property values in SamFunction
746+ """
747+
748+ def setUp (self ):
749+ self .function = SamFunction ("foo" )
750+ self .function .CodeUri = "s3://foobar/foo.zip"
751+ self .function .Runtime = "foo"
752+ self .function .Handler = "bar"
753+ self .template = {"Conditions" : {}}
754+
755+ self .kwargs = {
756+ "intrinsics_resolver" : IntrinsicsResolver ({}),
757+ "event_resources" : [],
758+ "managed_policy_map" : {},
759+ "resource_resolver" : ResourceResolver ({}),
760+ "conditions" : self .template .get ("Conditions" , {}),
761+ }
762+
763+ def test_role_none_creates_execution_role (self ):
764+ self .function .Role = None
765+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
766+ generated_roles = [x for x in cfn_resources if isinstance (x , IAMRole )]
767+
768+ self .assertEqual (len (generated_roles ), 1 ) # Should create execution role
769+
770+ def test_role_explicit_arn_no_execution_role (self ):
771+ test_role = "arn:aws:iam::123456789012:role/existing-role"
772+ self .function .Role = test_role
773+
774+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
775+ generated_roles = [x for x in cfn_resources if isinstance (x , IAMRole )]
776+ lambda_function = next (r for r in cfn_resources if r .resource_type == "AWS::Lambda::Function" )
777+
778+ self .assertEqual (len (generated_roles ), 0 ) # Should not create execution role
779+ self .assertEqual (lambda_function .Role , test_role )
780+
781+ def test_role_fn_if_no_aws_no_value_keeps_original (self ):
782+ role_conditional = {
783+ "Fn::If" : ["Condition" , "arn:aws:iam::123456789012:role/existing-role" , {"Ref" : "iamRoleArn" }]
784+ }
785+ self .function .Role = role_conditional
786+
787+ template = {"Conditions" : {"Condition" : True }}
788+ kwargs = dict (self .kwargs )
789+ kwargs ["conditions" ] = template .get ("Conditions" , {})
790+
791+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
792+ generated_roles = [x for x in cfn_resources if isinstance (x , IAMRole )]
793+ lambda_function = next (r for r in cfn_resources if r .resource_type == "AWS::Lambda::Function" )
794+
795+ self .assertEqual (len (generated_roles ), 1 )
796+ self .assertEqual (lambda_function .Role , role_conditional )
797+
798+ def test_role_fn_if_both_no_value_creates_execution_role (self ):
799+ role_conditional = {"Fn::If" : ["Condition" , {"Ref" : "AWS::NoValue" }, {"Ref" : "AWS::NoValue" }]}
800+ self .function .Role = role_conditional
801+
802+ template = {"Conditions" : {"Condition" : True }}
803+ kwargs = dict (self .kwargs )
804+ kwargs ["conditions" ] = template .get ("Conditions" , {})
805+
806+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
807+ generated_roles = [x for x in cfn_resources if isinstance (x , IAMRole )]
808+
809+ self .assertEqual (len (generated_roles ), 1 )
810+
811+ def test_role_fn_if_first_no_value_creates_conditional_role (self ):
812+ role_conditional = {"Fn::If" : ["Condition" , {"Ref" : "AWS::NoValue" }, {"Ref" : "iamRoleArn" }]}
813+ self .function .Role = role_conditional
814+
815+ template = {"Conditions" : {"Condition" : True }}
816+ kwargs = dict (self .kwargs )
817+ kwargs ["conditions" ] = template .get ("Conditions" , {})
818+
819+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
820+ generated_roles = [x for x in cfn_resources if isinstance (x , IAMRole )]
821+ lambda_function = next (r for r in cfn_resources if r .resource_type == "AWS::Lambda::Function" )
822+
823+ self .assertEqual (len (generated_roles ), 1 )
824+ self .assertEqual (
825+ lambda_function .Role , {"Fn::If" : ["Condition" , {"Fn::GetAtt" : ["fooRole" , "Arn" ]}, {"Ref" : "iamRoleArn" }]}
826+ )
827+
828+ def test_role_fn_if_second_no_value_creates_conditional_role (self ):
829+ role_conditional = {"Fn::If" : ["Condition" , {"Ref" : "iamRoleArn" }, {"Ref" : "AWS::NoValue" }]}
830+ self .function .Role = role_conditional
831+
832+ template = {"Conditions" : {"Condition" : True }}
833+ kwargs = dict (self .kwargs )
834+ kwargs ["conditions" ] = template .get ("Conditions" , {})
835+
836+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
837+ generated_roles = [x for x in cfn_resources if isinstance (x , IAMRole )]
838+ lambda_function = next (r for r in cfn_resources if r .resource_type == "AWS::Lambda::Function" )
839+
840+ self .assertEqual (len (generated_roles ), 1 )
841+ self .assertEqual (
842+ lambda_function .Role , {"Fn::If" : ["Condition" , {"Ref" : "iamRoleArn" }, {"Fn::GetAtt" : ["fooRole" , "Arn" ]}]}
843+ )
844+
845+ def test_role_get_att_no_execution_role (self ):
846+ role_get_att = {"Fn::GetAtt" : ["MyCustomRole" , "Arn" ]}
847+ self .function .Role = role_get_att
848+
849+ cfn_resources = self .function .to_cloudformation (** self .kwargs )
850+ lambda_function = next (r for r in cfn_resources if r .resource_type == "AWS::Lambda::Function" )
851+
852+ self .assertEqual (lambda_function .Role , role_get_att )
0 commit comments