aws-cloudformation / aws-cloudformation/cloudformation-cli
CF cannot preprocess the stack when a module parameter appears in the conditions block and using a !Ref or !GetAtt function
- Dominant language
- Python
- Stars
- 336
- Forks
- 172
- Avg merge
- 3d 5m
- Merged PRs (30d)
- 3
Description
## Description
When using a CF module, if you use an intrincic function expression to assign the value of module parameter, and the template source of the module uses the parameter name in a condition, CF cannot preprocess the stack and exits with error
~~~~
CloudFormation failed to preprocess the stack:
Template format error:
Unresolved dependencies [resSampleModule1resSourceQueue]. Cannot reference resources in the Conditions block of the template
~~~~
## Steps to reproduce
### 1. Create a module called `Fujitsu::CF::SampleModule1::MODULE` using the template `module1.yml` as fragment:
~~~~
module1.yml
===========
AWSTemplateFormatVersion: 2010-09-09
Description: "Template to generate an example module with name Fujitsu::CF::SampleModule1::MODULE"
Parameters:
parMaxReceiveCount:
Description: Number of times a message is received by a consumer of the source queue before being moved to the dead-letter queue
Type: Number
Default: 3
Resources:
resDeadLetterQueue:
Type: AWS::SQS::Queue
resSourceQueue:
Type: AWS::SQS::Queue
Properties:
RedrivePolicy:
deadLetterTargetArn:
Fn::GetAtt:
- "resDeadLetterQueue"
- "Arn"
maxReceiveCount: !Ref parMaxReceiveCount
~~~~
Commands:
~~~~
mkdir module1
cd module1
cfn init -t Fujitsu::CF::SampleModule1::MODULE -a MODULE --region eu-west-1
Replace fragmets/sample.json with module1.yml
cfn validate
cfn submit --region eu-west-1 --set-default
~~~~
### 2. Create a module called `Fujitsu::CF::SampleModule2::MODULE` using the template `module2.yml` as fragment:
~~~~
module2.yml
===========
AWSTemplateFormatVersion: 2010-09-09
Description: "Template to generate a samplemodule with name Fujitsu::CF::SampleModule2::MODULE"
Parameters:
parBucketName:
Description: S3 bucket name. If not specified, the S3 service assigns a name
Type: String
parVersioningConfiguration:
Description: If versioning is enabled (Enabled) or disabled (Suspended)
Type: String
AllowedValues: ["Enabled","Suspended"]
Conditions:
cndIsBucketNameSpecified: !Not
- !Equals
- ""
- !Ref parBucketName
Resources:
resS3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !If
- cndIsBucketNameSpecified
- !Sub ${parBucketName}-${AWS::Region}-${AWS::AccountId}
- !Ref AWS::NoValue
VersioningConfiguration:
Status: !Ref parVersioningConfiguration
Outputs:
outBucketName:
Description: S3 bucket name
Value: !Ref resS3Bucket
~~~~
Commands:
~~~~
mkdir module2
cd module2
cfn init -t Fujitsu::CF::SampleModule2::MODULE -a MODULE --region eu-west-1
Replace fragmets/sample.json with module2.yml
cfn validate
cfn submit --region eu-west-1 --set-default
~~~~
### 3. Create a stack (called `test` in the image), from this template:
~~~~
AWSTemplateFormatVersion: 2010-09-09
Description: "Sample parent template that uses Fujitsu::CF::SampleModule1::MODULE and Fujitsu::CF::SampleModule2::MODULE"
Parameters:
parMaxReceiveCount:
Description: Number of times a message is received by a consumer of the source queue before being moved to the dead-letter queue
Type: Number
Default: 3
Resources:
resSampleModule1:
Type: Fujitsu::CF::SampleModule1::MODULE
Properties:
parMaxReceiveCount: !Ref parMaxReceiveCount
resSampleModule2:
Type: Fujitsu::CF::SampleModule2::MODULE
Properties:
parBucketName: !GetAtt [resSampleModule1, resSourceQueue.QueueName]
parVersioningConfiguration: "Suspended"
~~~~
I will refer to this as the 'parent template'.
## Expected behavior
The stack is created without errors.
## Actual behavior
CF reports an error:
~~~~
CloudFormation failed to preprocess the stack:
Template format error:
Unresolved dependencies [resSampleModule1resSourceQueue]. Cannot reference resources in the Conditions block of the template
~~~~
The problem is the parent template uses an intrinsic function expression to assign value to a module parameter (`parBucketName: !GetAtt [resSampleModule1, resSourceQueue.QueueName]`), and the template fragment of the module uses the name of the assigned parameter (`parBucketName`) in a condition (`cndIsBucketNameSpecified`).
I think this is a bug because `parBucketName` in template fragment must be a name internal to the module.
Contributor guide
Assessment
This issue has not been assessed yet.