Skip to content

Commit 41061fd

Browse files
authored
Update language extensions for empty lists (#3764)
1 parent 0d7df03 commit 41061fd

File tree

2 files changed

+198
-2
lines changed

2 files changed

+198
-2
lines changed

src/cfnlint/template/transforms/_language_extensions.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,15 +370,23 @@ def value(
370370
except _ResolveError:
371371
try:
372372
t_map[2].value(cfn, params)
373+
max_length = -1
373374
for k, v in mapping.items():
374375
if isinstance(v, dict):
375376
if t_map[2].value(cfn, params, only_params) in v:
377+
if (
378+
len(v[t_map[2].value(cfn, params, only_params)])
379+
<= max_length
380+
):
381+
continue
376382
if isinstance(t_map[1], _ForEachValueRef):
377383
if t_map[1]._ref._value == "AWS::AccountId":
378384
global _ACCOUNT_ID
379385
_ACCOUNT_ID = k
380386
t_map[1] = _ForEachValue.create(k)
381-
break
387+
max_length = len(
388+
v[t_map[2].value(cfn, params, only_params)]
389+
)
382390
except _ResolveError:
383391
pass
384392

@@ -529,7 +537,7 @@ def values(
529537
if self._fn:
530538
try:
531539
values = self._fn.value(cfn, {}, False)
532-
if values:
540+
if values is not None:
533541
if isinstance(values, list):
534542
for value in values:
535543
if isinstance(value, (str, dict)):

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

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,3 +971,191 @@ def test_transform(self):
971971
self.result,
972972
template,
973973
)
974+
975+
976+
class TestTransformValueEmptyList(TestCase):
977+
def setUp(self) -> None:
978+
979+
cfnlint.template.transforms._language_extensions._ACCOUNT_ID = None
980+
981+
self.template_obj = convert_dict(
982+
{
983+
"Transform": ["AWS::LanguageExtensions"],
984+
"Mappings": {
985+
"Accounts": {
986+
"111111111111": {"AppName": []},
987+
},
988+
},
989+
"Resources": {
990+
"Fn::ForEach::Regions": [
991+
"AppName",
992+
{
993+
"Fn::FindInMap": [
994+
"Accounts",
995+
{"Ref": "AWS::AccountId"},
996+
"AppName",
997+
]
998+
},
999+
{
1000+
"${AppName}Role": {
1001+
"Type": "AWS::IAM::Role",
1002+
"Properties": {
1003+
"RoleName": {"Ref": "AppName"},
1004+
"AssumeRolePolicyDocument": {
1005+
"Version": "2012-10-17",
1006+
"Statement": [
1007+
{
1008+
"Effect": "Allow",
1009+
"Principal": {
1010+
"Service": ["ec2.amazonaws.com"]
1011+
},
1012+
"Action": ["sts:AssumeRole"],
1013+
}
1014+
],
1015+
},
1016+
"Path": "/",
1017+
},
1018+
}
1019+
},
1020+
],
1021+
},
1022+
}
1023+
)
1024+
1025+
self.result = {
1026+
"Mappings": {
1027+
"Accounts": {
1028+
"111111111111": {"AppName": []},
1029+
},
1030+
},
1031+
"Resources": {},
1032+
"Transform": ["AWS::LanguageExtensions"],
1033+
}
1034+
1035+
def test_transform(self):
1036+
self.maxDiff = None
1037+
with mock.patch(
1038+
"cfnlint.template.transforms._language_extensions._ACCOUNT_ID", None
1039+
):
1040+
cfn = Template(
1041+
filename="", template=self.template_obj, regions=["us-east-1"]
1042+
)
1043+
matches, template = language_extension(cfn)
1044+
self.assertListEqual(matches, [])
1045+
self.assertDictEqual(
1046+
template,
1047+
self.result,
1048+
template,
1049+
)
1050+
1051+
1052+
class TestTransformValueOneEmpty(TestCase):
1053+
def setUp(self) -> None:
1054+
self.template_obj = convert_dict(
1055+
{
1056+
"Transform": ["AWS::LanguageExtensions"],
1057+
"Mappings": {
1058+
"Accounts": {
1059+
"111111111111": {"AppName": []},
1060+
"222222222222": {"AppName": ["C", "D"]},
1061+
"333333333333": {"AppName": []},
1062+
},
1063+
},
1064+
"Resources": {
1065+
"Fn::ForEach::Regions": [
1066+
"AppName",
1067+
{
1068+
"Fn::FindInMap": [
1069+
"Accounts",
1070+
{"Ref": "AWS::AccountId"},
1071+
"AppName",
1072+
]
1073+
},
1074+
{
1075+
"${AppName}Role": {
1076+
"Type": "AWS::IAM::Role",
1077+
"Properties": {
1078+
"RoleName": {"Ref": "AppName"},
1079+
"AssumeRolePolicyDocument": {
1080+
"Version": "2012-10-17",
1081+
"Statement": [
1082+
{
1083+
"Effect": "Allow",
1084+
"Principal": {
1085+
"Service": ["ec2.amazonaws.com"]
1086+
},
1087+
"Action": ["sts:AssumeRole"],
1088+
}
1089+
],
1090+
},
1091+
"Path": "/",
1092+
},
1093+
}
1094+
},
1095+
],
1096+
},
1097+
}
1098+
)
1099+
1100+
self.result = {
1101+
"Mappings": {
1102+
"Accounts": {
1103+
"111111111111": {"AppName": []},
1104+
"222222222222": {"AppName": ["C", "D"]},
1105+
"333333333333": {"AppName": []},
1106+
},
1107+
},
1108+
"Resources": {
1109+
"CRole": {
1110+
"Properties": {
1111+
"AssumeRolePolicyDocument": {
1112+
"Statement": [
1113+
{
1114+
"Action": ["sts:AssumeRole"],
1115+
"Effect": "Allow",
1116+
"Principal": {"Service": ["ec2.amazonaws.com"]},
1117+
}
1118+
],
1119+
"Version": "2012-10-17",
1120+
},
1121+
"Path": "/",
1122+
"RoleName": "C",
1123+
},
1124+
"Type": "AWS::IAM::Role",
1125+
},
1126+
"DRole": {
1127+
"Properties": {
1128+
"AssumeRolePolicyDocument": {
1129+
"Statement": [
1130+
{
1131+
"Action": ["sts:AssumeRole"],
1132+
"Effect": "Allow",
1133+
"Principal": {"Service": ["ec2.amazonaws.com"]},
1134+
}
1135+
],
1136+
"Version": "2012-10-17",
1137+
},
1138+
"Path": "/",
1139+
"RoleName": "D",
1140+
},
1141+
"Type": "AWS::IAM::Role",
1142+
},
1143+
},
1144+
"Transform": ["AWS::LanguageExtensions"],
1145+
}
1146+
1147+
def test_transform(self):
1148+
self.maxDiff = None
1149+
with mock.patch(
1150+
"cfnlint.template.transforms._language_extensions._ACCOUNT_ID", None
1151+
):
1152+
cfn = Template(
1153+
filename="", template=self.template_obj, regions=["us-east-1"]
1154+
)
1155+
matches, template = language_extension(cfn)
1156+
self.assertListEqual(matches, [])
1157+
self.assertDictEqual(
1158+
template,
1159+
self.result,
1160+
template,
1161+
)

0 commit comments

Comments
 (0)