如何在AWS::CloudFormation::Init的files键中用!Sub/!Join动态生成路径
Great question! The core issue here is that YAML mapping keys can't directly use CloudFormation intrinsic functions like !Sub or !Join—the YAML parser treats the function syntax as part of the literal key name, rather than letting CloudFormation evaluate it dynamically.
Here are two proven solutions to achieve your goal of using a project-specific directory in AWS::CloudFormation::Init's files section:
Solution 1: Use !Sub to generate the entire files block as a YAML string
CloudFormation will automatically parse the YAML string returned by !Sub into a valid mapping for the files property. This lets you dynamically define file paths using your PROJECT_NAME parameter.
AWS::CloudFormation::Init: configSets: default: - projectFileConfig projectFileConfig: files: !Sub - | "/${PROJECT_NAME}/myfile2.txt": content: | some shell commands some shell commands some shell commands mode: "100644" - {} # No need to pass variables here—!Sub automatically references template parameters
If you need to build more complex paths (like nested directories), you can extend this by defining variables in the !Sub context:
files: !Sub - | "${targetDir}/myfile2.txt": content: | some shell commands mode: "100644" - targetDir: !Sub "/${PROJECT_NAME}/scripts"
Solution 2: Merge static and dynamic files with Fn::Merge
If you have a mix of static files and dynamic paths, use Fn::Merge to combine a static files mapping with your dynamically generated one:
files: !Fn::Merge - # Static file configuration (unchanged across projects) /tmp/static-setup.txt: content: "This file is the same for all projects" mode: "100644" - !Sub - | "${PROJECT_NAME}/myfile2.txt": content: | Project-specific commands go here mode: "100644" - {}
Key Notes & Best Practices
- Fix your mode value: You had
"120644"in your example—this is invalid. Use standard octal permissions like"100644"(read/write for owner, read-only for others). - Test early: Use the AWS CLI command
aws cloudformation validate-template --template-body file://your-template.yamlto catch syntax errors before deployment. - Reuse with mappings: For multi-project setups, store common paths or configurations in a
Mappingssection, then reference them in!Subto keep your template clean and reusable.
Content of the question comes from stack exchange, asked by Lukas

