11

We are adapting our applications CloudFormation template to make use of VPC. Within this template we need to programmatically generate the CIDR blocks used for our VPC subnets, in order to ensure they do not conflict between CloudFormation stacks.

My initial plan had been to generate the CIDRs by concatenating strings together, for example:

"ProxyLoadBalancerSubnetA" : {
  "Type" : "AWS::EC2::Subnet",
  "Properties" : {
    "VpcId" : { "Ref" : "Vpc" },
    "AvailabilityZone" : "eu-west-1a",
    "CidrBlock" : { "Fn::Join" : [ ".", [ { "Ref" : "VpcCidrPrefix" }, "0.0/24" ] ] }
  }
},

Upon further consideration however, we need to use a single VPC rather than having a VPC for each of our stacks.

AWS restrict VPCs to using a maximum of a /16 CIDR block (we have asked for this limit to be raised, but it is apparently not possible). This means it is no longer possible for us to use this concatenation method as each of our stacks require subnets that span more than 255 addresses in total.

I'd like to generate the CIDR blocks on-the-fly rather than having to define them as parameters to the CloudFormation template,

One idea I had was each stack having a "base integer" and adding to that for each subnet's CIDR block.

For example:

    "CidrBlock" : { "Fn::Join" : [ ".", [ { "Ref" : "VpcCidrPrefix" }, { "Fn::Sum", [ { "Ref" : "VpcCidrStart" }, 3 ] }, "0/24 ] ] }

Where VpcCidrStart is an integer that sets the value that the third CIDR octet should start from within the script, and 3 is the subnet number.

Obviously the Fn::Sum intrinsic function doesn't exist though, so I wanted to know if anyone had a solution to adding integers in VPC (it seems like something that shouldn't be possible, as CloudFormation is string oriented), or a better solution to this conundrum in general.

2 Answers2

7

I faced a similar situation. I wanted to control everything from the template without generating the template using some script. My input range is also limited as in your case. I ended up putting a horrible horrible hack. I am kind of ashamed to post it here but if it helps one more person, it may be worth it.

Have a mapping table which will do the math for you and define it for all possible inputs

"Mappings" : { 
    "HorribleHackForSubtraction" : { 
        "1" : {"SubtractOne" : "0"},
        "2" : {"SubtractOne" : "1"},
        "3" : {"SubtractOne" : "2"},
        "4" : {"SubtractOne" : "3"},
        "5" : {"SubtractOne" : "4"},
        "6" : {"SubtractOne" : "5"},
        "7" : {"SubtractOne" : "6"},
        "8" : {"SubtractOne" : "7"},
        "9" : {"SubtractOne" : "8"},
        "10" : {"SubtractOne" : "9"},
        "11" : {"SubtractOne" : "10"},
        "12" : {"SubtractOne" : "11"},
        "13" : {"SubtractOne" : "12"},
        "14" : {"SubtractOne" : "13"},
        "15" : {"SubtractOne" : "14"},
        "16" : {"SubtractOne" : "15"},
    }   
},  

You can refer to the computed value as

{ "Fn::FindInMap" : [ "HorribleHackForSubtraction", { "Ref" : "MyInputParam"}, "SubtractOne" ] }
sunil
  • 3,507
  • 18
  • 25
3

My solution for these kinds of issues was to use a legitimate programming language to compile a template into a CloudFormation JSON document. I used PHP 5.4, Twig and Symfony Console, but YMMV.

Essentially, you do the math ahead of time in the programming language, then use that data as you write-out your JSON document.

Ryan Parman
  • 6,855
  • 1
  • 29
  • 43
  • I had already started working on a "Stack Manager" application to handle conditions where staging and production environments need a slightly different setup, and to automate "lights-out" of non-production environments at night - so I think this solution makes sense for us. A shame that CloudFormation lacks these features natively though. –  Jul 26 '13 at 13:09
  • If you haven't already, it'd probably be a good idea to describe your use-case and make your feature request on the official [AWS CloudFormation forum](https://forums.aws.amazon.com/forum.jspa?forumID=92). I know that the development team handles support there. – Ryan Parman Jul 26 '13 at 19:18
  • I know it's been a while, but I did implement this and recently [published it on GitHub](https://github.com/royaloperahouse/stack-manager). AWS did recently add basic logic and math to CloudFormation, but it is rather cumbersome. –  Feb 08 '15 at 17:42