So as part of #765 I was asked to add some validations to AWS::EC2::Route, which makes sense, however it turns out this validation is too naïve to deal with a property being set, and it's value is either Ref('AWS::NoValue') or an even more complex scenario inside a conditional where one of the possible values might be Ref('AWS::NoValue'). Such things appear to be perfectly legitimate in CloudFormation because if the property has no value, then CloudFormation will simply ignore it after its conditionals have been satisfied.
For a real world example of why one might need this, consider a stack that configures a VPC, and in setting up the Routes also needs to set up NAT, but the value of some property may determine if the stack creates a NAT Gateway, or NAT instances. Inside the Route object you may need something like:
Route(
'Route66',
DestinationCidrBlock='0.0.0.0/0',
RouteTableId=Ref('RouteTable66'),
InstanceId=If(
'UseNat',
Ref('AWS::NoValue'),
Ref('UseNat')
),
NatGatewayId=If(
'UseNat',
Ref('UseNat'),
Ref('AWS::NoValue')
)
)
I see a few potential options to solve this:
- Rip out the validation from
AWS::EC2::Route. This is the simplest but makes foot-gunning easier, not harder.
- Extend the validation in mutually_exclusive to not count properties that have either
Ref('AWS::NoValue') or any type of conditional that has at least one outcome value as Ref('AWS::NoValue'). This would add complexity, and it would still remain somewhat non-deterministic if the correct value would be applied.
- Some other option my non-caffienated brain has yet to conjur up.
So as part of #765 I was asked to add some validations to
AWS::EC2::Route, which makes sense, however it turns out this validation is too naïve to deal with a property being set, and it's value is eitherRef('AWS::NoValue')or an even more complex scenario inside a conditional where one of the possible values might beRef('AWS::NoValue'). Such things appear to be perfectly legitimate in CloudFormation because if the property has no value, then CloudFormation will simply ignore it after its conditionals have been satisfied.For a real world example of why one might need this, consider a stack that configures a VPC, and in setting up the Routes also needs to set up NAT, but the value of some property may determine if the stack creates a NAT Gateway, or NAT instances. Inside the Route object you may need something like:
I see a few potential options to solve this:
AWS::EC2::Route. This is the simplest but makes foot-gunning easier, not harder.Ref('AWS::NoValue')or any type of conditional that has at least one outcome value asRef('AWS::NoValue'). This would add complexity, and it would still remain somewhat non-deterministic if the correct value would be applied.