I'm trying to setup a cloudformation template that will either launch a clean instance or one from snapshots. I'd like to be able to use an if / else type statement so that would look something like
pseudo code:
if InputSnapshotId:
"SnapshotId" : {"Ref" : "InputSnapshotId"},
else:
"Size" : 20,
In cloudformation I have tried a number of things like:
"WebserverInstanceDataVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Fn::If" : [
{"Ref" : "FromSnapshot"},
{"SnapshotId" : { "Ref" : "InputSnapshotId" }},
{"Size" : "20"}
],
"VolumeType" : "standard",
"AvailabilityZone" : { "Fn::GetAtt" : [ "WebserverInstance", "AvailabilityZone" ]},
"Tags" : [
{"Key" : "Role", "Value": "data" },
]
},
"DeletionPolicy" : "Delete"
},
Or wrapping the in Fn::If in {}:
{"Fn::If" : [
{"Ref" : "FromSnapshot"},
{"SnapshotId" : { "Ref" : "InputSnapshotId" }},
{"Size" : "20"}
]}
All of which kicks different types or errors. The first one gives a "Encountered unsupported property Fn::If" in cloudformation, the second, just isn't valid JSON. I could snapshot an empty volume and define a size parameter then always pass a SnapshotId and size but I feel like there must be a way to have an optional line in cloudformation.
Any ideas?
The intrinsic function Fn::Sub substitutes variables in an input string with values that you specify. In your templates, you can use this function to construct commands or outputs that include values that aren't available until you create or update a stack.
Fn::If. Returns one value if the specified condition evaluates to true and another value if the specified condition evaluates to false .
The NoEcho property is set to true to prevent describe stack calls, such as the aws cloudformation describe-stacks AWS CLI command, from returning the parameter value.
According to the docs, Conditions should be used at the top level of the resource you want to conditionally create. Putting a Condition inside the Instance UserData section isn't supported. To use Conditions in your situation, you'd want separate Resources conditionally created based on the Parameter.
You can do like this:
"Conditions" : {
"NotUseSnapshot" : {"Fn::Equals" : [{"Ref" : "InputSnapshotId"}, ""]}
},
"Resources" : {
"WebserverInstanceDataVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : {
"Fn::If" : [
"NotUseSnapshot",
"20",
{"Ref" : "AWS::NoValue"}
]
},
"SnapshotId" : {
"Fn::If" : [
"NotUseSnapshot",
{"Ref" : "AWS::NoValue"},
{"Ref" : "InputSnapshotId"}
]
},
"VolumeType" : "standard",
"AvailabilityZone" : { "Fn::GetAtt" : [ "WebserverInstance", "AvailabilityZone" ]},
"Tags" : [
{"Key" : "Role", "Value": "data" }
]
},
"DeletionPolicy" : "Delete"
}
}
Here is a link to a functional template: https://github.com/caussourd/public-cloudformation-templates/blob/master/conditional_volume_creation.template
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With