resolving parameter values via Fn::Sub inside of Fn::ForEach is throwing an error
Community Note
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
- Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
Tell us about the bug
I'm trying out the new Fn::ForEach capability to create a set of nested stacks (i.e. Type: AWS::CloudFormation::Stack).
I'm running into an odd issue when using Fn::Sub to define the TemplateURL property value. The Fn::Sub has no problem resolving a pseudo parameter (AWS::URLSuffix), along with a value imported from another stack via Fn::ImportValue, but it does not seem able to resolve parameters defined within the template. If I replace the internally defined parameters with hard-coded equivalents, a stack creation succeeds.
The disparity in behavior between the 2 template versions is specific to usage of Fn::ForEach. When not using Fn::ForEach, both approaches work fine.
Expected behavior
I expect both versions of the below template to work.
Observed behavior
The former works, while the latter fails with the error ...
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Template format error: Unresolved resource dependencies [path, version] in the Resources block of the template
Test cases
An aws cloudformation deploy of the following template succeeds ...
---
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::LanguageExtensions
Description: test new Fn::Foreach capability (composite)
Parameters:
StackNameTemplates:
Type: String
Default: build-artifacts
TopicNames:
Type: CommaDelimitedList
Default: TestTopic1,TestTopic2
Resources:
Fn::ForEach::Topics:
- TopicName
- !Ref TopicNames
- SnsTopic${TopicName}:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
TemplateURL: !Sub
- https://s3.${urlsuffix}/${bucketname}/cloudformation-component-sns-topic/3b8fb142918369d46e4344a212f17b4f50ca15c9/template.yaml
- bucketname:
Fn::ImportValue: !Sub ${StackNameTemplates}:bucket:name
urlsuffix: !Ref AWS::URLSuffix
In the below, I enhance the above by parameterizing 2 strings in the TemplateURL value (ComponentSnsTopicPath and ComponentSnsTopicVersion). You'll see that the Default value for each new parameter is equivalent to what was previously hard-coded into the TemplateURL value.
An aws cloudformation deploy of the following template fails ...
---
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::LanguageExtensions
Description: test new Fn::Foreach capability (composite)
Parameters:
ComponentSnsTopicPath:
Type: String
Default: cloudformation-component-sns-topic
ComponentSnsTopicVersion:
Type: String
Default: 3b8fb142918369d46e4344a212f17b4f50ca15c9
StackNameTemplates:
Type: String
Default: build-artifacts
TopicNames:
Type: CommaDelimitedList
Default: TestTopic1,TestTopic2
Resources:
Fn::ForEach::Topics:
- TopicName
- !Ref TopicNames
- SnsTopic${TopicName}:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
TemplateURL: !Sub
- https://s3.${urlsuffix}/${bucketname}/${path}/${version}/template.yaml
- bucketname:
Fn::ImportValue: !Sub ${StackNameTemplates}:bucket:name
path: !Ref ComponentSnsTopicPath
urlsuffix: !Ref AWS::URLSuffix
version: !Ref ComponentSnsTopicVersion
Additional context
n/a