cloudtools / cloudtools/troposphere
mutually_exclusive and exactly_one aren't clever enough to deal with AWS::NoValue
- Dominant language
- Python
- Stars
- 4.9k
- Forks
- 1.4k
- PR merge metrics
- No merged PRs in 30d
Description
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:
```python
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.
Contributor guide
Research direction
Start with the validation behavior in mutually_exclusive and exactly_one, then inspect the AWS::EC2::Route validations added in the context of #765. Clarify the expected treatment of Ref('AWS::NoValue') and conditional outcomes before deciding on a change; done means the agreed behavior is covered by regression tests without weakening ordinary validation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python
- Domain
- cloud
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100