@znemz/cfn-include 1.6.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Nicholas McCready
3
+ Copyright (c) 2015 Moritz Onken
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,5 +1,3 @@
1
- [![npm](http://img.shields.io/npm/v/cfn-include.svg?style=flat-square)](https://npmjs.org/package/cfn-include) [![npm](http://img.shields.io/npm/dm/cfn-include.svg?style=flat-square)](https://npmjs.org/package/cfn-include) [![Build Status](https://img.shields.io/travis/nmccready/cfn-include/master.svg?style=flat-square)](https://travis-ci.org/nmccready/cfn-include) ![license](https://img.shields.io/badge/license-mit-blue.svg?style=flat-square)
2
-
3
1
  # cfn-include
4
2
 
5
3
  `cfn-include` is a preprocessor for CloudFormation templates which extends CloudFormation's [intrinsic functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html).
@@ -8,17 +6,50 @@ For example, [`Fn::Include`](#fninclude) provides a convenient way to include fi
8
6
  `cfn-include` tries to be minimally invasive, meaning that the template will still look and feel like an ordinary CloudFormation template. This is what sets `cfn-include` apart from other CloudFormation preprocessors such as [CFNDSL](https://github.com/stevenjack/cfndsl), [StackFormation](https://github.com/AOEpeople/StackFormation) and [AWSBoxen](https://github.com/mozilla/awsboxen). There is no need to use a scripting language or adjust to new syntax. Check them out though, they might be a better fit for you.
9
7
 
10
8
  **Functions**
11
- * [`Fn::Include`](#fninclude)
12
- * [`Fn::Flatten`](#fnflatten)
13
- * [`Fn::GetEnv`](#fngetenv)
14
- * [`Fn::Length`](#fnlength)
15
- * [`Fn::Map`](#fnmap)
16
- * [`Fn::Merge`](#fnmerge)
17
- * [`Fn::DeepMerge`](#fnmerge)
18
- * [`Fn::Outputs`](#fnoutputs)
19
- * [`Fn::Sequence`](#fnsequence)
20
- * [`Fn::Stringify`](#fnstringify)
21
- * [`Fn::UpperCamelCase`](#fnuppercamelcase) and `Fn::LowerCamelCase`
9
+ - [cfn-include](#cfn-include)
10
+ - [Installation](#installation)
11
+ - [Synopsis](#synopsis)
12
+ - [CLI](#cli)
13
+ - [Example](#example)
14
+ - [Fn::Include](#fninclude)
15
+ - [Examples](#examples)
16
+ - [Include a file from a URL](#include-a-file-from-a-url)
17
+ - [Include a file in the same folder](#include-a-file-in-the-same-folder)
18
+ - [Include an AWS API response](#include-an-aws-api-response)
19
+ - [Include Globs](#include-globs)
20
+ - [Include Inject State](#include-inject-state)
21
+ - [Fn::Map](#fnmap)
22
+ - [Fn::Flatten](#fnflatten)
23
+ - [Fn::FlattenDeep](#fnflattendeep)
24
+ - [Fn::GetEnv](#fngetenv)
25
+ - [Fn::Length](#fnlength)
26
+ - [Fn::Merge](#fnmerge)
27
+ - [Fn::DeepMerge](#fndeepmerge)
28
+ - [Fn::Sequence](#fnsequence)
29
+ - [Fn::Stringify](#fnstringify)
30
+ - [Fn::Uniq](#fnuniq)
31
+ - [Fn::Compact](#fncompact)
32
+ - [Fn::Concat](#fnconcat)
33
+ - [Fn::Sort](#fnsort)
34
+ - [Fn::SortedUniq](#fnsorteduniq)
35
+ - [Fn::SortBy](#fnsortby)
36
+ - [Fn::SortObject](#fnsortobject)
37
+ - [Fn::ObjectKeys](#fnobjectkeys)
38
+ - [Fn::ObjectValues](#fnobjectvalues)
39
+ - [Fn::Filenames](#fnfilenames)
40
+ - [Fn::StringSplit](#fnstringsplit)
41
+ - [Fn::Without](#fnwithout)
42
+ - [Fn::Omit](#fnomit)
43
+ - [Fn::OmitEmpty](#fnomitempty)
44
+ - [Fn::Eval](#fneval)
45
+ - [Fn::IfEval](#fnifeval)
46
+ - [Fn::JoinNow](#fnjoinnow)
47
+ - [Fn::ApplyTags](#fnapplytags)
48
+ - [Fn::Outputs](#fnoutputs)
49
+ - [More Examples](#more-examples)
50
+ - [Proxy Support](#proxy-support)
51
+ - [Compatibility](#compatibility)
52
+ - [Web Service](#web-service)
22
53
 
23
54
  Tag-based syntax is available in YAML templates. For example,`Fn::Include` becomes `!Include`.
24
55
 
@@ -57,9 +88,10 @@ Options:
57
88
  * `--version` print version and exit
58
89
  * `--context` template full path. only utilized for stdin when the template is piped to this script
59
90
  example: `cat examples/base.template | ./bin/cli.js --context examples/base.template`
60
- * `--enable` different options / toggles: ['env'] [string] [choices: "env"]
91
+ * `--enable` different options / toggles: ['env','eval'] [string] [choices: 'env','eval','env.eval' etc...]
61
92
  * `env` pre-process env vars and inject into templates as they are processed looks for $KEY or ${KEY} matches
62
-
93
+ * `-i, --inject` JSON string payload to use for template injection. (Takes precedence over process.env (if enabled) injection and will be merged on top of process.env)
94
+ * `--doLog` console log out include options in recurse step.
63
95
  `cfn-include` also accepts a template passed from stdin
64
96
 
65
97
  ```
@@ -133,9 +165,18 @@ The output will be something like this:
133
165
  Place `Fn::Include` anywhere in the template and it will be replaced by the contents it is referring to. The function accepts an object. Parameters are:
134
166
 
135
167
  - **location**: The location to the file can be relative or absolute. A relative location is interpreted relative to the template. Included files can in turn include more files, i.e. recursion is supported.
168
+ - **ignoreMissingVar**: If set to `true` the function will not throw an error if a variable is not found (unset). Instead, the variable will be replaced by an empty string. Defaults to `false`.
169
+ - **ignoreMissingFile**: If set to `true` the function will not throw an error if the file is not found. Instead, the function will be replaced by an empty string. Defaults to `false`.
136
170
  - **type** (optional): either `json`, `string` or `api`. Defaults to `json`. `string` will include the file literally which is useful in combination with `Fn::Sub`. `api` will call any AWS API and return the response which can be included in the template. Choose `json` for both JSON and YAML files. The `literal` type is deprecated and uses the infamous `Fn::Join` syntax.
137
171
  - **context** (optional, deprecated): If `type` is `literal` a context object with variables can be provided. The object can contain plain values or references to parameters or resources in the CloudFormation template (e.g. `{ "Ref": "StackId" }`). Use Mustache like syntax in the file. This option is deprecated in favor of the `Fn::Sub` syntax (see examples below).
138
- - **query** (optional): If `type` is `json` a [JMESPath](http://jmespath.org/) query can be provided. The file to include is then queried using the value as a JMESPath expression.
172
+ - **parser** (optional):
173
+ - string: default is `"jmespath"`
174
+ - object `{location, query, parser}`: default is `"jmespath"`
175
+ - array: `[location, query, parser]`: default is `"lodash"`
176
+ - string (split |) `location|query|parser`: default is `"lodash"`
177
+ - **query** (optional): If `type` is `json`, `array`, or `string split |`
178
+ - [JMESPath](http://jmespath.org/) query can be provided. The file to include is then queried using the value as a JMESPath expression.
179
+ - [Lodash _.get](https://lodash.com/docs/4.17.15#get) query
139
180
 
140
181
  Only applicable if **type** is `api`:
141
182
 
@@ -143,12 +184,38 @@ Only applicable if **type** is `api`:
143
184
  - **action**: Action to call (case sensitive, e.g. `updateStack`, `describeRegions`)
144
185
  - **parameters** (optional): Parameters passed to **action** (e.g. `{ StackName: "MyStack" }`)
145
186
  - **region** (optional): Either `AWS_DEFAULT_REGION` or this parameter have to be set which specifies the region where the API call is made.
146
-
147
187
  You can also use a plain string if you want the default behavior, which is simply including a JSON file.
188
+ - **isGlob** (optional): Forces the usage of [glob](https://www.npmjs.com/package/glob) to spit out an array of includes
189
+ - **inject** (optional): Pass in localized env / options to be injected into a template
148
190
 
149
191
  ### Examples
150
192
 
151
- Include a file from a URL
193
+ #### Include via Query
194
+
195
+ ```yaml
196
+ # all equivalent
197
+ Fn::Include:
198
+ location: ./t/includes/complex.json
199
+ query: bulb[1].c
200
+
201
+ Fn::Include:
202
+ location: ./t/includes/complex.json
203
+ query: bulb.1.c
204
+ parser: lodash
205
+
206
+ # Array parser is lodash
207
+ Fn::Include: [./t/includes/complex.json, bulb.1.c]
208
+
209
+ # Array default parser is lodash
210
+ Fn::Include:
211
+ - ./t/includes/complex.json
212
+ - bulb.1.c
213
+
214
+ # string split "|" default parser is lodash
215
+ Fn::Include: ./t/includes/complex.json|bulb.1.c
216
+ ```
217
+
218
+ #### Include a file from a URL
152
219
 
153
220
  ```yaml
154
221
  !Include https://example.com/include.json
@@ -166,7 +233,7 @@ Include a file from an S3 bucket. Authentication is handled by `aws-sdk`. See [S
166
233
  !Include s3://bucket-name/include1.json
167
234
  ```
168
235
 
169
- Include a file in the same folder
236
+ #### Include a file in the same folder
170
237
 
171
238
  ```yaml
172
239
  !Include include.json
@@ -181,7 +248,9 @@ Fn::Sub:
181
248
  location: https://example.com/userdata.txt
182
249
  ```
183
250
 
184
- Include an AWS API response, e.g. loop through all regions and return the image id of a specific AMI:
251
+ #### Include an AWS API response
252
+
253
+ IE: loop through all regions and return the image id of a specific AMI:
185
254
 
186
255
  ```yaml
187
256
  Fn::Merge:
@@ -216,9 +285,80 @@ Output as JSON:
216
285
  }
217
286
  ```
218
287
 
288
+ #### Include Globs
289
+
290
+ Essentially imagine if you had several yaml or json files you wanted to include.
291
+
292
+ ```
293
+ ./src/
294
+ files/
295
+ - one.yml
296
+ - two.yml
297
+ - three.yml
298
+ - four.yml
299
+ main.yml
300
+ ```
301
+
302
+ Before Glob you would have to do:
303
+
304
+ main.yml
305
+
306
+ ```yml
307
+ Fn::Map:
308
+ - [one, two, three]
309
+ - [FILE]
310
+ - Fn::Include: ./files/${FILE}.yml
311
+ ```
312
+
313
+ With Glob
314
+
315
+ main.yml
316
+
317
+ ```yml
318
+ Fn::Include: ./files/*.yml
319
+ ```
320
+
321
+ or (say you need to ignore something)
322
+
323
+ ```yml
324
+ Fn::Include:
325
+ location: ./files/!(four).yml
326
+ isGlob: true
327
+ ```
328
+
329
+ #### Include Inject State
330
+
331
+ This feature uses the exact same logic as doEnv in that all env variables are traversed and replaced however this is
332
+ with localized state for the included file.
333
+
334
+ File to inject to:
335
+
336
+ `toInject.yml` - your include file
337
+
338
+ ```yml
339
+ SomeResource:
340
+ Name: ${LOCALIZED_NAME}
341
+ ```
342
+
343
+ Consume it and add some custom state
344
+
345
+ ```yml
346
+ Fn::Include:
347
+ location: ./toInject.yml
348
+ inject:
349
+ LOCALIZED_NAME: CustomName
350
+ ```
351
+
352
+ yields
353
+
354
+ ```yml
355
+ SomeResource:
356
+ Name: CustomName
357
+ ```
358
+
219
359
  ## Fn::Map
220
360
 
221
- `Fn::Map` is the equivalent of the JavaScript `map()` function allowing for the transformation of an input array to an output array.
361
+ `Fn::Map` is the equivalent of the lodash [`map()`](https://lodash.com/docs/4.17.15#map) function allowing for the transformation of an input array or object to an output array.
222
362
  By default the string `_` is used as the variable in the map function. A custom variable can be provided as a second parameter, see [`Fn::Flatten`](#fnflatten) for an example. If a custom variable is used, the variable will also be replaced if found in the object key, see [`Fn::Merge`](#fnmerge) for an example.
223
363
 
224
364
  ```yaml
@@ -346,6 +486,108 @@ Results in:
346
486
  }
347
487
  ```
348
488
 
489
+ ## Fn::FlattenDeep
490
+
491
+ This function flattens an array as many levels as possible. This is useful for flattening out nested [`Fn::Map`](#fnmap) calls.
492
+
493
+ ```yaml
494
+ SecurityGroupIngress:
495
+ Fn::FlattenDeep:
496
+ Fn::Map:
497
+ - [80, 443]
498
+ - $
499
+ - Fn::Map:
500
+ - [10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16]
501
+ - Fn::Map:
502
+ - [tcp, udp]
503
+ - PROTOCOL
504
+ - CidrIp: _
505
+ FromPort: $
506
+ ToPort: $
507
+ IpProtocol: PROTOCOL
508
+ ```
509
+
510
+ Results in:
511
+
512
+ ```json
513
+ {
514
+ "SecurityGroupIngress": [
515
+ {
516
+ "CidrIp": "10.0.0.0/8",
517
+ "FromPort": "80",
518
+ "ToPort": "80",
519
+ "IpProtocol": "tcp"
520
+ },
521
+ {
522
+ "CidrIp": "10.0.0.0/8",
523
+ "FromPort": "80",
524
+ "ToPort": "80",
525
+ "IpProtocol": "udp"
526
+ },
527
+ {
528
+ "CidrIp": "172.16.0.0/12",
529
+ "FromPort": "80",
530
+ "ToPort": "80",
531
+ "IpProtocol": "tcp"
532
+ },
533
+ {
534
+ "CidrIp": "172.16.0.0/12",
535
+ "FromPort": "80",
536
+ "ToPort": "80",
537
+ "IpProtocol": "udp"
538
+ },
539
+ {
540
+ "CidrIp": "192.168.0.0/16",
541
+ "FromPort": "80",
542
+ "ToPort": "80",
543
+ "IpProtocol": "tcp"
544
+ },
545
+ {
546
+ "CidrIp": "192.168.0.0/16",
547
+ "FromPort": "80",
548
+ "ToPort": "80",
549
+ "IpProtocol": "udp"
550
+ },
551
+ {
552
+ "CidrIp": "10.0.0.0/8",
553
+ "FromPort": "443",
554
+ "ToPort": "443",
555
+ "IpProtocol": "tcp"
556
+ },
557
+ {
558
+ "CidrIp": "10.0.0.0/8",
559
+ "FromPort": "443",
560
+ "ToPort": "443",
561
+ "IpProtocol": "udp"
562
+ },
563
+ {
564
+ "CidrIp": "172.16.0.0/12",
565
+ "FromPort": "443",
566
+ "ToPort": "443",
567
+ "IpProtocol": "tcp"
568
+ },
569
+ {
570
+ "CidrIp": "172.16.0.0/12",
571
+ "FromPort": "443",
572
+ "ToPort": "443",
573
+ "IpProtocol": "udp"
574
+ },
575
+ {
576
+ "CidrIp": "192.168.0.0/16",
577
+ "FromPort": "443",
578
+ "ToPort": "443",
579
+ "IpProtocol": "tcp"
580
+ },
581
+ {
582
+ "CidrIp": "192.168.0.0/16",
583
+ "FromPort": "443",
584
+ "ToPort": "443",
585
+ "IpProtocol": "udp"
586
+ }
587
+ ]
588
+ }
589
+ ```
590
+
349
591
  ## Fn::GetEnv
350
592
 
351
593
  ```yaml
@@ -498,6 +740,345 @@ cfn-include stack.config.yml > stack.config.json
498
740
  aws cloudformation create-stack --cli-input-json file://stack.config.json
499
741
  ```
500
742
 
743
+ ## Fn::Uniq
744
+
745
+ This function filters only the unique elements of an array
746
+
747
+ ```yaml
748
+ SecurityGroupIngress:
749
+ Fn::Uniq:
750
+ Fn::Flatten:
751
+ - [1, 2]
752
+ - [3, 4]
753
+ - [1, 4, 6]
754
+ ```
755
+
756
+ Results in:
757
+
758
+ ```json
759
+ {
760
+ "SecurityGroupIngress": [
761
+ 1,
762
+ 2,
763
+ 3,
764
+ 4,
765
+ 6
766
+ ]
767
+ }
768
+ ```
769
+
770
+ ## Fn::Compact
771
+
772
+ This function removes falsy elements same as [lodash](https://lodash.com/docs/4.17.15#compact)
773
+
774
+ ```yaml
775
+ SecurityGroupIngress:
776
+ Fn::Compact:
777
+ - 1
778
+ - a
779
+ - ""
780
+ - false
781
+ - true
782
+ ```
783
+
784
+ Results in:
785
+
786
+ ```json
787
+ {
788
+ "SecurityGroupIngress": [
789
+ 1,
790
+ "a",
791
+ true
792
+ ]
793
+ }
794
+ ```
795
+
796
+ ## Fn::Concat
797
+
798
+ _.concat
799
+
800
+ ```yaml
801
+ Fn::Concat:
802
+ - [a, b, c]
803
+ - d
804
+ ```
805
+
806
+ Results in:
807
+
808
+ ```json
809
+ [
810
+ "a",
811
+ "b",
812
+ "c",
813
+ "d"
814
+ ]
815
+ ```
816
+
817
+ ## Fn::Sort
818
+
819
+ `$ ./bin/cli.js [examples/sort.yaml](examples/sort.yaml)`
820
+
821
+ ```json
822
+ [
823
+ 1,
824
+ 20,
825
+ 22,
826
+ 30,
827
+ 30,
828
+ 33.3,
829
+ 40,
830
+ 5.5,
831
+ 50,
832
+ 50
833
+ ]
834
+ ```
835
+
836
+ ## Fn::SortedUniq
837
+
838
+ `$ ./bin/cli.js [examples/sortedUniq.yaml](examples/sortedUniq.yaml)`
839
+
840
+ ```json
841
+ [
842
+ 1,
843
+ 20,
844
+ 22,
845
+ 30,
846
+ 33.3,
847
+ 40,
848
+ 5.5,
849
+ 50
850
+ ]
851
+ ```
852
+
853
+ ## Fn::SortBy
854
+
855
+ `$ ./bin/cli.js [examples/sortBy.yaml](examples/sortBy.yaml)`
856
+
857
+ ```json
858
+ [
859
+ {
860
+ "name": "Ana",
861
+ "age": 12
862
+ },
863
+ {
864
+ "name": "Ana",
865
+ "age": 31
866
+ },
867
+ {
868
+ "name": "Bob",
869
+ "age": 17
870
+ },
871
+ {
872
+ "name": "Colby",
873
+ "age": 35
874
+ },
875
+ {
876
+ "name": "Fred",
877
+ "age": 50
878
+ },
879
+ {
880
+ "name": "Jack",
881
+ "age": 40
882
+ },
883
+ {
884
+ "name": "Ted",
885
+ "age": 20
886
+ },
887
+ {
888
+ "name": "Zed",
889
+ "age": 90
890
+ }
891
+ ]
892
+ ```
893
+
894
+ ## Fn::SortObject
895
+
896
+ See: [examples/sortObject.yaml](examples/sortObject.yaml)
897
+
898
+ `$ ./bin/cli.js examples/sortObject.yaml`
899
+
900
+ ```json
901
+ {
902
+ "a": "hi",
903
+ "c": "z",
904
+ "h": 20,
905
+ "i": true,
906
+ "z": 1
907
+ }
908
+ ```
909
+
910
+ ## Fn::ObjectKeys
911
+
912
+ This function uses [Object.keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys)
913
+
914
+ ```yaml
915
+ FamilyNames:
916
+ Fn::ObjectKeys:
917
+ Ted: 18
918
+ Lucy: 5
919
+ Tom: 10
920
+ ```
921
+
922
+ Results in:
923
+
924
+ ```yaml
925
+ FamilyNames:
926
+ - Ted
927
+ - Lucy
928
+ - Tom
929
+ ```
930
+
931
+ ## Fn::ObjectValues
932
+
933
+ This function uses [Object.values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values)
934
+
935
+ ```yaml
936
+ FamilyAges:
937
+ Fn::ObjectValues:
938
+ Ted: 18
939
+ Lucy: 5
940
+ Tom: 10
941
+ ```
942
+
943
+ Results in:
944
+
945
+ ```yaml
946
+ FamilyAges:
947
+ - 18
948
+ - 5
949
+ - 10
950
+ ```
951
+
952
+ ## Fn::Filenames
953
+
954
+ ```yaml
955
+ Fn::Filenames:
956
+ location: "../t/fixtures"
957
+ omitExtension: true
958
+ ```
959
+
960
+ ```json
961
+ [
962
+ "deep",
963
+ "foobar",
964
+ "subfolder",
965
+ "synopsis",
966
+ "verydeep",
967
+ "include1",
968
+ "include2"
969
+ ]
970
+ ```
971
+
972
+ ## Fn::StringSplit
973
+
974
+ Useful for injected Includes which you need to run `Fn::Map` upon.
975
+
976
+ ```yaml
977
+ Fn::StringSplit:
978
+ string: "A,B,C"
979
+ separator: "," # defaults to this so it can be omitted
980
+ ```
981
+
982
+ ```yaml
983
+ - A
984
+ - B
985
+ - C
986
+ ```
987
+
988
+ ## Fn::Without
989
+
990
+ ```yaml
991
+ Fn::Without:
992
+ - ["a", "b", "c", "d"]
993
+ - ["b", "c"]
994
+ ```
995
+
996
+ ```yaml
997
+ - "a",
998
+ - "d"
999
+ ```
1000
+
1001
+ ## Fn::Omit
1002
+
1003
+ [omit_object](t/includes/omit_object.json)
1004
+ [omit_array](t/includes/omit_array.json)
1005
+
1006
+ ```yaml
1007
+ b: b
1008
+ ```
1009
+
1010
+ ## Fn::OmitEmpty
1011
+
1012
+ See [omitEmpty test file](t/omitEmpty.json), file and expectations (output).
1013
+
1014
+ In summary falsy values are omitted from an object except `false` and `0`.
1015
+
1016
+ ## Fn::Eval
1017
+
1018
+ Opt in to use `eval` in your templates. This is disabled by default.
1019
+
1020
+ `--enable eval` is required to turn on options.doEval in the include function.
1021
+
1022
+ ```yaml
1023
+ Fn::Eval:
1024
+ state: [1, 2, 3]
1025
+ script: >
1026
+ state.map((v) => 2 * v);
1027
+ ```
1028
+
1029
+ ```yaml
1030
+ - 2
1031
+ - 4
1032
+ - 6
1033
+ ```
1034
+
1035
+ ## Fn::IfEval
1036
+
1037
+ Opt in to use `eval` in your templates. This is disabled by default.
1038
+
1039
+ `--enable eval` is required to turn on options.doEval in the include function.
1040
+
1041
+ ```yaml
1042
+ Fn::IfEval:
1043
+ inject:
1044
+ lastName: bear
1045
+ # doLog: true
1046
+ evalCond: ('$lastName' === 'bear')
1047
+ truthy:
1048
+ Name: Yogi
1049
+ LastName: Bear
1050
+ falsy:
1051
+ Name: Fred
1052
+ LastName: Flint
1053
+ ```
1054
+
1055
+ ```yaml
1056
+ Name: Yogi
1057
+ LastName: Bear
1058
+ ```
1059
+
1060
+ ## Fn::JoinNow
1061
+
1062
+ ```yaml
1063
+ Fn::JoinNow:
1064
+ - ""
1065
+ - - "arn:aws:s3:::c1-acme-iam-cache-engine-"
1066
+ - ${AWS::AccountId}
1067
+ - "-us-east-1$CFT_STACK_SUFFIX"
1068
+ ```
1069
+
1070
+ ```yaml
1071
+ arn:aws:s3:::c1-acme-iam-cache-engine-${AWS::AccountId}-us-east-1$CFT_STACK_SUFFIX
1072
+ ```
1073
+
1074
+ ## Fn::ApplyTags
1075
+
1076
+ See [ApplyTags test file](t/tests/applyTags.yml).
1077
+
1078
+ Fields:
1079
+ `(T|t)ags`: sequence of {Key, Value} objects to me merged in as Tags properties of a taggable resource.
1080
+ `resources`: Object mapping of resources, this is usually your root `CFT.Resources` block.
1081
+
501
1082
  ## Fn::UpperCamelCase
502
1083
 
503
1084
  ```yaml