Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS cloudformation optional line

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?

like image 794
TristanMatthews Avatar asked Sep 30 '14 23:09

TristanMatthews


People also ask

What is FN :: sub in AWS?

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.

What is FN :: if?

Fn::If. Returns one value if the specified condition evaluates to true and another value if the specified condition evaluates to false .

What is NoEcho in CloudFormation?

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.

Which section of CloudFormation template does not allow for conditions?

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.


1 Answers

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

like image 175
Céline Aussourd Avatar answered Sep 28 '22 05:09

Céline Aussourd