CloudFormation: Conditionals in Resource Parameters

Our organization has been doing a bunch of AWS CloudFormation lately. Recently I’d stumbled across a method for doing conditional logic within any Resource’s Parameters array.

Conditional logic within a Resource’s Parameters comes up often when it’s something like an RDS Database instance.   In that Resource type, there are explicit Parameters (like AllocatedStorage),  but there are also Parameters which contain an array, like VPCSecurityGroups.

There are many options to configure, and if you modularize your CloudFormation templates as we do, you’ll find it necessary to completely change, or even omit certain Parameter array elements depending on other parts of your template.

The method for doing so is something I hadn’t found documented in the official AWS CloudFormation material on Conditionals, so figured I’d put it here to help my other DevOps brethren.

Take the following example snippet:

Conditions:
  conditions !Equals [ !Ref parameterEnv, "Prod" ]

Resources:
  createDatabase:
    Type: "AWS::RDS::DBInstance"
    Properties:
      AllocatedStorage: "5"
      Engine: "MySQL"
      EngineVersion: "5.6"
      DBInstanceClass: "db.t2.small"
      MasterUsername: "someuser"
      MasterUserPassword: "somepassword"
      VPCSecurityGroups:
        - sg-abc12345
        - sg-def67890

In the above example, we’re creating a basic RDS instance that has two security groups.   In addition, there is a Conditions statement checking whether the CloudFormation template is used for a production environment.

Let’s say there is now a requirement to omit SecurityGroup “sg-def67890” because that allows access from the developer network.

In some examples I saw accomplished it this way, rather inelegantly:

Conditions:
  conditionIsProd !Equals [ !Ref parameterEnv, "Prod" ]

Resources:
  createDatabase:
  Type: "AWS::RDS::DBInstance"
  Condition: !Not conditionIsProd
  Properties:
    AllocatedStorage: "5"
    Engine: "MySQL"
    EngineVersion: "5.6"
    DBInstanceClass: "db.t2.small"
    MasterUsername: "someuser"
    MasterUserPassword: "somepassword"
    VPCSecurityGroups:
      - sg-abc12345
      - sg-def67890

  createDatabase:
    Type: "AWS::RDS::DBInstance"
    Condition: conditionIsProd
    Properties:
      AllocatedStorage: "5"
      Engine: "MySQL"
      EngineVersion: "5.6"
      DBInstanceClass: "db.t2.small"
      MasterUsername: "someuser"
      MasterUserPassword: "somepassword"
      VPCSecurityGroups:
        - sg-abc1234

Doing it in the way above is also limiting.  If you have multiple permutations of options in your CloudFormation template, you’d need to build out a Resource stanza for each situation.  Not very extensible.

Instead, try this (it works):

Conditions:
  conditionIsProd !Equals [ !Ref parameterEnv, "Prod" ]

Resources:
  createDatabase:
    Type: "AWS::RDS::DBInstance"
    Properties:
      AllocatedStorage: "5"
      Engine: "MySQL"
      EngineVersion: "5.6"
      DBInstanceClass: "db.t2.small"
      MasterUsername: "someuser"
      MasterUserPassword: "somepassword"
      VPCSecurityGroups:
        - sg-abc12345
        - !If
            - conditionIsProd
            -
              !Ref "AWS::NoValue"
            - sg-def67890

This strays from the official documenation examples because the Fn::If function is being leveraged within an array element.   Even though it seems counter-intuitive, the key is to place the If statement after the array delimiter for the parent object, which in this YAML example is the hypen, i.e.

- !If

The only caveat here is that you’re limited to one array item within the conditional statement.   So if you need multiple array lines to accomplish your goals, you’ll need an Fn::If for each.

However,  if your scenario requires multiple lines within one element, putting them in one Fn::If works fine.

Now go automate everything in your AWS environments!

The American Wagon Needs a Comeback

If you’re an American chances are you depend on a car.

The United States is a big country and we Americans enjoy trekking across it.  The Beach Boys sang, “I get around” and they couldn’t be more right.

Some say it is the physical manifestation of individual freedom.   Cars seem to be ingrained in everything we do.   We visit the ATM and do banking while in our cars.   We order food and eat in our cars.   Though it’s not popular now, we even watched movies from our cars.   We also do, uhm, “other” stuff in our cars.   Heck,  some people even live out of their cars and to lead a life on the road.  We like cars here.

I was raised in Detroit and both my parents worked in the auto industry.  As my eyesight got fuzzier and what I wanted out of life got clearer,  a move to northern California happened.   That was eleven years ago, and the natives have fully integrated me into their lands.   Like, dude,  I can say “Hella”, “rad”, and “gnarly”, ya know?    Other than a hard-wired tendency to use short vowels with a sickly nasal twang, I blend in.

Mostly.

During the west coast integration process I’ve learned that Californians are just as nutty about cars as Detroiters.    One could even say they’re nuttier, for certain natives of the Golden State have written more songs about cars.   The point is, between both Detroit and California  I’ve lived in two of the most car-crazy places on planet Earth.   So with some authority on the topic I’m declaring:   American cars currently suck.

Yeah, I know how these posts usually go.  Probably expecting a rant on how things were better in the old days, before cars had computers, sensors, remote start,  tune-ups, etc.  You’ll comment that I’m living in the past and opinions are dated.    But I’m not going to say any of that.   The fact is I agree. Today’s cars, mechanically speaking at least, are great.

Instead this is about lack of choice.    And there really is a severe lack of choice today.    For better or worse,  body options in the American car market today are:

  • Four-door sedans
  • Two-door coupes
  • SUVs or “Crossovers”
  • Pickup trucks

You might think that list covers just about every type of car someone might want to buy, but it doesn’t.    What’s missing is the wagon.   “Wagons!?”, you’re undoubtedly saying. “Wagons are old, gross, and died in the 1980s.  Good riddance!”

But you’re wrong.   And because this is my blog I’m right, dog gone it.

Hear me out:  SUVs are overcooked.  I was driving in the 1990s when the Bronco II gave way to the Ford Explorer SUV.  The SUV was a “cool” answer to boring, beige & wood-grain wagons and minivans.  Why get one of those old fashioned wagon things when  a sporty off-road fun mobile was there for the taking?   A cool SUV could do all the things your dad’s wagon did:   carry lots of people, cargo, get horrible mileage, and play cassette tapes.

The SUV has reigned nearly 25 years, and that’s long enough.   In my not-so-humble opinion, like the wagons of the 1990’s, SUVs should die.   It may be happening slowly already, but not fast enough.   The big, tall SUV is getting squashed flatter and flatter, slowly, into a hell-spawn called the “Crossover”.   I feel gross just saying “Crossover”.   Let’s all do ourselves a favor,  admit the body proportions on Crossovers is just hella wrong (see, integrated)  and admit the great American Wagon is making a come back.   Sure, they might not be called wagons when it finally happens.   They’ll be called something like “extended wheelbase sportback sedan” because the word “wagon” brings back bad memories of stale french fries and brown paint tones.   But they’ll be back,  trust me.

I’m welcoming those wagons back with open arms.   In California, where gas is regularly $3.00/gallon, the SUV or Crossover (I’m about to throw up) makes no sense.     Crossovers are ugly and bloated things.   It’s like Andre the Giant trying to look tidy and trim.   Besides awkward proportions, they handle like shit, are just too big, and the high-up driving position of those things is awkward and disconnecting from the driving experience.   Nothing like carving up the mountain roads in your crossover.   Kill me now.

If I want to sit up high, I’ll drive the Ford pickup.   If it’s a long windy road trip to the California coast or the wide open road to Las Vegas, a firm-but-not-harsh riding, low-slung wagon please.   All the luggage in the back.  Hold the woodgrain.   A 45 MPG hybrid would be great.   Can I get a tasteful extension off the rear roof too?

Sadly, to my knowledge and research there isn’t an affordable midsize wagon option available on the American market today.   Affordable choices are “quasi-SUV” compacts like the Subaru Outback or the Volkswagen Golf Sportswagen (I’ll argue those are compact hatchbacks).     From there it’s into things like the 23-MPG Ford Flex, a “I’m higher than you” Crossover (I just threw up).

But there’s the Volvo V90,  and it’s perfect.   Good mid-size!  Low-slung! Tastefully sporty!  Quick!  And  $50,000.   The BMW 5-series wagon is just about perfect,  too.    But one catch:  Must go to Europe to buy.   Both of those things are a tad out of reach.

Frankly, the American car market sucks if you want a wagon.   What I’ve learned is Americans on a budget tend to drive pretend-trucks, while wealthy people drive wagons…I guess?   Because of a rather distinct lack of wealthy,  I suppose it is a matter of waiting for the SUV and Crossover to die, and none too soon.

Or move to Europe.