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

Open
#1,098 0 comments 0 reactions 0 assignees View on GitHub
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
~~~~

bug-cf

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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.