Skip to content

Commit c1f90b8

Browse files
authored
Better logic of FindInMap resolution when ref isn't resolved (#4162)
1 parent 6bf9c96 commit c1f90b8

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

src/cfnlint/template/transforms/_language_extensions.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -368,24 +368,23 @@ def value(
368368
t_map[1].value(cfn, params, only_params)
369369
except _ResolveError:
370370
try:
371-
t_map[2].value(cfn, params)
371+
t_map_2_value = t_map[2].value(cfn, params, only_params)
372372
max_length = -1
373373
for k, v in mapping.items():
374374
if isinstance(v, dict):
375-
if t_map[2].value(cfn, params, only_params) in v:
375+
if t_map_2_value in v:
376376
if (
377-
len(v[t_map[2].value(cfn, params, only_params)])
378-
<= max_length
377+
isinstance(v[t_map_2_value], list)
378+
and len(v[t_map_2_value]) <= max_length
379379
):
380380
continue
381381
if isinstance(t_map[1], _ForEachValueRef):
382382
if t_map[1]._ref._value == "AWS::AccountId":
383383
global _ACCOUNT_ID
384384
_ACCOUNT_ID = k
385385
t_map[1] = _ForEachValue.create(k)
386-
max_length = len(
387-
v[t_map[2].value(cfn, params, only_params)]
388-
)
386+
if isinstance(v[t_map_2_value], list):
387+
max_length = len(v[t_map_2_value])
389388
except _ResolveError:
390389
pass
391390

@@ -444,7 +443,7 @@ class _ForEachValueRef(_ForEachValue):
444443
def __init__(self, _hash: str, obj: Any) -> None:
445444
super().__init__(_hash)
446445
if not isinstance(obj, (str, dict)):
447-
raise _TypeError("Fn::FindInMap should be a list", obj)
446+
raise _TypeError("Fn::Ref should be a list", obj)
448447

449448
self._ref = _ForEachValue.create(obj)
450449
self._obj = obj

test/unit/module/template/transforms/test_language_extensions.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,3 +1222,86 @@ def test_transform(self):
12221222
self.result,
12231223
template,
12241224
)
1225+
1226+
1227+
class TestTransformValueIsStringInMap(TestCase):
1228+
def setUp(self) -> None:
1229+
self.template_obj = convert_dict(
1230+
{
1231+
"Transform": ["AWS::LanguageExtensions"],
1232+
"Mappings": {
1233+
"EngineMap": {
1234+
"8.0.mysql-aurora.3.07.0": {
1235+
"Engine": "aurora-mysql",
1236+
"EngineVersion": "8.0.mysql_aurora.3.07.0",
1237+
},
1238+
"aurora-postgresql-15.10": {
1239+
"Engine": "aurora-postgresql",
1240+
"EngineVersion": "15.10",
1241+
},
1242+
}
1243+
},
1244+
"Resources": {
1245+
"DBCluster": {
1246+
"Type": "AWS::RDS::DBCluster",
1247+
"Properties": {
1248+
"Engine": {
1249+
"Fn::FindInMap": [
1250+
"EngineMap",
1251+
{"Ref": "Engine"},
1252+
"Engine",
1253+
]
1254+
},
1255+
"EngineVersion": {
1256+
"Fn::FindInMap": [
1257+
"EngineMap",
1258+
{"Ref": "Engine"},
1259+
"EngineVersion",
1260+
]
1261+
},
1262+
},
1263+
}
1264+
},
1265+
}
1266+
)
1267+
1268+
self.result = {
1269+
"Mappings": {
1270+
"EngineMap": {
1271+
"8.0.mysql-aurora.3.07.0": {
1272+
"Engine": "aurora-mysql",
1273+
"EngineVersion": "8.0.mysql_aurora.3.07.0",
1274+
},
1275+
"aurora-postgresql-15.10": {
1276+
"Engine": "aurora-postgresql",
1277+
"EngineVersion": "15.10",
1278+
},
1279+
}
1280+
},
1281+
"Resources": {
1282+
"DBCluster": {
1283+
"Type": "AWS::RDS::DBCluster",
1284+
"Properties": {
1285+
"Engine": "aurora-postgresql",
1286+
"EngineVersion": "15.10",
1287+
},
1288+
}
1289+
},
1290+
"Transform": ["AWS::LanguageExtensions"],
1291+
}
1292+
1293+
def test_transform(self):
1294+
self.maxDiff = None
1295+
with mock.patch(
1296+
"cfnlint.template.transforms._language_extensions._ACCOUNT_ID", None
1297+
):
1298+
cfn = Template(
1299+
filename="", template=self.template_obj, regions=["us-east-1"]
1300+
)
1301+
matches, template = language_extension(cfn)
1302+
self.assertListEqual(matches, [])
1303+
self.assertDictEqual(
1304+
template,
1305+
self.result,
1306+
template,
1307+
)

0 commit comments

Comments
 (0)