CfnInclude: Support lazy mappings, allow more user control
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the feature
I have a template I am importing via CfnInclude with many mappings. I get a lot of the following errors:
```
[Info at /JobExecutor-626488381203-us-east-1/Import/ImportIMP0/$Mappings/PrefixListId] Consider making this CfnMapping a lazy mapping by providing `lazy: true`: either no findInMap was called or every findInMap could be immediately resolved without using Fn::FindInMap
```
I'd like an option in CfnInclude that would allow me to create lazy mappings.
But more than that, I'd like to have a way to resolve ANY token created by CfnInclude myself, via an interface.
### Use Case
I'm always frustrated when...
1. I'm importing a template using CfnInclude and there is an ImportValue that I'd like to replace. As is, I need to create my own Bootstrap stack that exports the value so I can use this template in another account. Pre-processing the template to remove the ImportValue is not really an option.
2. I'm importing a template using CfnInclude and there is a custom token, like "{{IMAGE}}" to specify an ECR image link, and Id like to resolve that without having to pre-process the template. Currently, pre-processing requires reading the template in, replacing the custom tokens with my own IResolvable, then writing it out to a TEMP file. I have to do this because CfnInclude requires a file name, not template JSON).
3. I'd like to resolve mappings with a call to a function in my Stack class instead of using the mapping in the template.
4. I'd like to resolve Fn::If statements based on context.
### Proposed Solution
An interface based on the Fn statics that can be passed to CfnInclude that allows me to resolve tokens myself (e.g. by returning my own IResolvable or just a value).
Might be something like this:
```
// In the below, context parameter would be the path to the Fn in the template
// Context may not be necessary, but it would be nice.
interface FnResolver {
importValue(sharedValueToImport: string, context: string[]): string
// You could just pass any unknown token to ref, and then the customToken functions below would not be necessary.
ref(logicalName: string, context: string[]): string
findInMap(mapName: string, topLevelKey: string, secondLevelKey: string): string
get customTokens() : string[] // I can return a list of custom tokens here
resolveCustomToken(customToken: string, context: string[])
}
```
### Other Information
My current solutions are:
1. Alter the template before I import it. But that makes my import tool non-generic.
2. Add a bootstrap stack to export values needed by the template I wish to import.
### Acknowledgements
- [ ] I may be able to implement this feature request
- [ ] This feature might incur a breaking change
### CDK version used
2.41.0
### Environment details (OS name and version, etc.)
AL2
Contributor guide
Research direction
Start with the CfnInclude implementation and the Fn statics referenced in the proposal, then trace how imported mappings, ImportValue, Ref, custom tokens, and Fn::If are currently handled. Define an interface that supports caller-controlled token resolution and lazy mappings. Done means the listed use cases are supported without preprocessing templates or bootstrap exports.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, infrastructure
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100