From e9b7498595f047b35774a5cca29ecc00733c005c Mon Sep 17 00:00:00 2001 From: Kevin DeJong Date: Tue, 27 Aug 2024 13:37:14 -0700 Subject: [PATCH 1/2] Add params to findinmap value --- src/cfnlint/template/transforms/_language_extensions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cfnlint/template/transforms/_language_extensions.py b/src/cfnlint/template/transforms/_language_extensions.py index 3733542626..4e81a48d35 100644 --- a/src/cfnlint/template/transforms/_language_extensions.py +++ b/src/cfnlint/template/transforms/_language_extensions.py @@ -339,7 +339,7 @@ def value( ): for k, v in cfn.template.get("Mappings", {}).items(): if isinstance(v, dict): - if t_map[1].value(cfn) in v: + if t_map[1].value(cfn, params) in v: t_map[0] = _ForEachValue.create(k) mapping = v break @@ -367,7 +367,7 @@ def value( t_map[1].value(cfn, params, only_params) except _ResolveError: try: - t_map[2].value(cfn) + t_map[2].value(cfn, params) for k, v in mapping.items(): if isinstance(v, dict): if t_map[2].value(cfn, params, only_params) in v: @@ -417,7 +417,7 @@ def value( ) -> Any: if params is None: params = {} - v = self._ref.value(cfn) + v = self._ref.value(cfn, params) if not isinstance(v, str): raise _ResolveError("Can't resolve Fn::Ref", self._obj) From 42e8ad79aea5c1cc014de9ca70b1ca737c0770f1 Mon Sep 17 00:00:00 2001 From: Kevin DeJong Date: Tue, 27 Aug 2024 13:55:50 -0700 Subject: [PATCH 2/2] Add some tests --- .../transforms/test_language_extensions.py | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/test/unit/module/template/transforms/test_language_extensions.py b/test/unit/module/template/transforms/test_language_extensions.py index 7c9e31d26e..da4fa1871b 100644 --- a/test/unit/module/template/transforms/test_language_extensions.py +++ b/test/unit/module/template/transforms/test_language_extensions.py @@ -663,6 +663,168 @@ def test_bad_mapping(self): ) +class TestTransformValues(TestCase): + def setUp(self) -> None: + self.template_obj = convert_dict( + { + "Transform": ["AWS::LanguageExtensions"], + "Mappings": { + "111111111111": { + "A": {"AppName": "appa-dev"}, + "B": {"AppName": "appb-dev"}, + }, + "222222222222": { + "A": {"AppName": "appa-qa"}, + "B": {"AppName": "appb-qa"}, + }, + }, + "Resources": { + "Fn::ForEach::Regions": [ + "Region", + ["A"], + { + "${Region}Role": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": { + "Fn::Sub": [ + "${appname}", + { + "appname": { + "Fn::FindInMap": [ + {"Ref": "AWS::AccountId"}, + {"Ref": "Region"}, + "AppName", + ] + } + }, + ] + }, + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": ["ec2.amazonaws.com"] + }, + "Action": ["sts:AssumeRole"], + } + ], + }, + "Path": "/", + }, + } + }, + ], + "Fn::ForEach::NewRegions": [ + "Region", + ["B"], + { + "${Region}Role": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": { + "Fn::Sub": [ + "${appname}", + { + "appname": { + "Fn::FindInMap": [ + {"Ref": "AWS::AccountId"}, + {"Ref": "Region"}, + "AppName", + ] + } + }, + ] + }, + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": ["ec2.amazonaws.com"] + }, + "Action": ["sts:AssumeRole"], + } + ], + }, + "Path": "/", + }, + } + }, + ], + }, + } + ) + + self.result = { + "Mappings": { + "111111111111": { + "A": {"AppName": "appa-dev"}, + "B": {"AppName": "appb-dev"}, + }, + "222222222222": { + "A": {"AppName": "appa-qa"}, + "B": {"AppName": "appb-qa"}, + }, + }, + "Resources": { + "ARole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": ["sts:AssumeRole"], + "Effect": "Allow", + "Principal": {"Service": ["ec2.amazonaws.com"]}, + } + ], + "Version": "2012-10-17", + }, + "Path": "/", + "RoleName": { + "Fn::Sub": ["${appname}", {"appname": "appa-dev"}] + }, + }, + "Type": "AWS::IAM::Role", + }, + "BRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": ["sts:AssumeRole"], + "Effect": "Allow", + "Principal": {"Service": ["ec2.amazonaws.com"]}, + } + ], + "Version": "2012-10-17", + }, + "Path": "/", + "RoleName": { + "Fn::Sub": ["${appname}", {"appname": "appb-dev"}] + }, + }, + "Type": "AWS::IAM::Role", + }, + }, + "Transform": ["AWS::LanguageExtensions"], + } + + def test_transform(self): + self.maxDiff = None + cfn = Template(filename="", template=self.template_obj, regions=["us-east-1"]) + matches, template = language_extension(cfn) + self.assertListEqual(matches, []) + self.assertDictEqual( + template, + self.result, + template, + ) + + def nested_set(dic, keys, value): for key in keys[:-1]: if isinstance(key, str):