10
10
from cfnlint .template import Template
11
11
from cfnlint .template .transforms ._language_extensions import (
12
12
_ForEach ,
13
+ _ForEachCollection ,
13
14
_ForEachValue ,
14
15
_ForEachValueFnFindInMap ,
15
- _ForEachValueRef ,
16
16
_ResolveError ,
17
17
_Transform ,
18
18
_TypeError ,
@@ -27,6 +27,7 @@ def test_valid(self):
27
27
_ForEach (
28
28
"key" , [{"Ref" : "Parameter" }, {"Ref" : "AWS::NotificationArns" }, {}], {}
29
29
)
30
+ _ForEach ("key" , ["AccountId" , {"Ref" : "AccountIds" }, {}], {})
30
31
31
32
def test_wrong_type (self ):
32
33
with self .assertRaises (_TypeError ):
@@ -54,6 +55,32 @@ def test_output_type(self):
54
55
_ForEach ("key" , ["foo" , ["bar" ], []], {})
55
56
56
57
58
+ class TestForEach (TestCase ):
59
+ def setUp (self ) -> None :
60
+ super ().setUp ()
61
+ self .cfn = Template (
62
+ "" ,
63
+ {
64
+ "Parameters" : {
65
+ "AccountIds" : {
66
+ "Type" : "CommaDelimitedList" ,
67
+ },
68
+ },
69
+ },
70
+ regions = ["us-west-2" ],
71
+ )
72
+
73
+ def test_valid (self ):
74
+ fec = _ForEachCollection ({"Ref" : "AccountIds" })
75
+ self .assertListEqual (
76
+ list (fec .values (self .cfn , {})),
77
+ [
78
+ {"Fn::Select" : [0 , {"Ref" : "AccountIds" }]},
79
+ {"Fn::Select" : [1 , {"Ref" : "AccountIds" }]},
80
+ ],
81
+ )
82
+
83
+
57
84
class TestRef (TestCase ):
58
85
def setUp (self ) -> None :
59
86
self .template_obj = convert_dict (
@@ -75,6 +102,9 @@ def setUp(self) -> None:
75
102
"Type" : "List<AWS::EC2::Subnet::Id>" ,
76
103
"AllowedValues" : ["sg-12345678, sg-87654321" ],
77
104
},
105
+ "AccountIds" : {
106
+ "Type" : "CommaDelimitedList" ,
107
+ },
78
108
},
79
109
}
80
110
)
@@ -115,6 +145,15 @@ def test_ref(self):
115
145
fe = _ForEachValue .create ({"Ref" : "SecurityGroups" })
116
146
self .assertEqual (fe .value (self .cfn ), ["sg-12345678" , "sg-87654321" ])
117
147
148
+ fe = _ForEachValue .create ({"Ref" : "AccountIds" })
149
+ self .assertEqual (
150
+ fe .value (self .cfn ),
151
+ [
152
+ {"Fn::Select" : [0 , {"Ref" : "AccountIds" }]},
153
+ {"Fn::Select" : [1 , {"Ref" : "AccountIds" }]},
154
+ ],
155
+ )
156
+
118
157
119
158
class TestFindInMap (TestCase ):
120
159
def setUp (self ) -> None :
@@ -416,6 +455,76 @@ def test_transform_findinmap_function(self):
416
455
result ,
417
456
)
418
457
458
+ def test_transform_list_parameter (self ):
459
+ template_obj = deepcopy (self .template_obj )
460
+ parameters = {"AccountIds" : {"Type" : "CommaDelimitedList" }}
461
+ template_obj ["Parameters" ] = parameters
462
+
463
+ nested_set (
464
+ template_obj ,
465
+ [
466
+ "Resources" ,
467
+ "Fn::ForEach::SpecialCharacters" ,
468
+ 1 ,
469
+ ],
470
+ {"Ref" : "AccountIds" },
471
+ )
472
+ nested_set (
473
+ template_obj ,
474
+ [
475
+ "Resources" ,
476
+ "Fn::ForEach::SpecialCharacters" ,
477
+ 2 ,
478
+ ],
479
+ {
480
+ "S3Bucket&{Identifier}" : {
481
+ "Type" : "AWS::S3::Bucket" ,
482
+ "Properties" : {
483
+ "BucketName" : {"Ref" : "Identifier" },
484
+ "Tags" : [
485
+ {"Key" : "Name" , "Value" : {"Fn::Sub" : "Name-${Identifier}" }},
486
+ ],
487
+ },
488
+ }
489
+ },
490
+ )
491
+ cfn = Template (filename = "" , template = template_obj , regions = ["us-east-1" ])
492
+ matches , template = language_extension (cfn )
493
+ self .assertListEqual (matches , [])
494
+
495
+ result = deepcopy (self .result )
496
+ result ["Parameters" ] = parameters
497
+ result ["Resources" ]["S3Bucket5096" ] = {
498
+ "Properties" : {
499
+ "BucketName" : {"Fn::Select" : [1 , {"Ref" : "AccountIds" }]},
500
+ "Tags" : [
501
+ {
502
+ "Key" : "Name" ,
503
+ "Value" : "Name-5096" ,
504
+ },
505
+ ],
506
+ },
507
+ "Type" : "AWS::S3::Bucket" ,
508
+ }
509
+ result ["Resources" ]["S3Bucketa72a" ] = {
510
+ "Properties" : {
511
+ "BucketName" : {"Fn::Select" : [0 , {"Ref" : "AccountIds" }]},
512
+ "Tags" : [
513
+ {
514
+ "Key" : "Name" ,
515
+ "Value" : "Name-a72a" ,
516
+ },
517
+ ],
518
+ },
519
+ "Type" : "AWS::S3::Bucket" ,
520
+ }
521
+ del result ["Resources" ]["S3Bucketab" ]
522
+ del result ["Resources" ]["S3Bucketcd" ]
523
+ self .assertDictEqual (
524
+ template ,
525
+ result ,
526
+ )
527
+
419
528
def test_bad_collection_ref (self ):
420
529
template_obj = deepcopy (self .template_obj )
421
530
nested_set (
0 commit comments