When deploying infrastructure with CloudFormation, at some point you will reach a moment when your CloudFormation JSON or YAML file is just too big. It will be too long to get a good overview of what’s in it, manage parameters and all dependencies between resources within the template. Nested stacks may be a solution, but if sometimes you can’t/won' t/don’t use them for whatever reason (for example, it will get to complicated to manage tested stacks or their contents are not reusable between other stacks).
Even if you’re using troposphere to generate your templates, you’ll face the same issue - a very long Python file. Luckily, if you are using troposphere, you’re inherently using Python - which means you can take advantage of it.
Pawel have already written about magical dictionaries in Python before. In essence, they allow you to iterate over properties of a Python object as if it was a dictionary. That means, you can use the object within your code and get all the goodies that come with it - code completion within your IDE and simple referencing, refactoring, etc., and then iterate over that object to add all its properties to your troposphere template.
As a reminder, an example MagicDict
class:
|
|
I include that as magicdict.py
in a directory. To use it, create a file next to it with the part of your
infrastructure, for example let’s say you want to create a VPC in vpc.py
:
|
|
I tend to create __main__.py
with contents like this:
|
|
That’s it! Run python your_directory_name
where “your_directory_name” is the directory holding all those 3 files.
You’ll get your CloudFormation template in return.
Obviously, this example is very short, so on its own it doesn’t help too much. In general, your vpc.py
would be quite
long - including all subnets, route tables, NACLs, etc. So, let’s assume you’d like to add an ELB to that stack as well.
Instead of adding it to the already long vpc.py
, create loadbalancer.py
with this content:
|
|
and your __main__.py
changes to this:
|
|
The load balancer relies on the VPC resources - which is clearly visible now in the __main__.py
file. Inside
the loadbalancer.py
you can very easily use those resources, like when specifying the
subnets: Subnets=[Ref(vpc.public_subnet_1), Ref(vpc.public_subnet_2)]
. Any reasonable Python IDE will be able to
code-complete the vpc resources for you inside the load balancer file, so you can easily reference them where needed.
You can obviously add more files and more resources to the template!
For example, almost every CloudFormation stack needs parameters. Create parameters.py
:
|
|
and add this to __main__.py
under the template description:
|
|
Simple. Your parameters are now in the template and you can pass in the parameters
object into other objects (like vpc
or load balancer). How to reference the parameter? The same as usual:
Ref(parameters.key_pair)
One note: in the above example you’ll see this where the load balancer is defined:
DependsOn=vpc.internet_gateway_attachment.title
the .title
suffix is needed here so that troposphere inserts the name of the internet gateway attachment object and
not the whole object definition. You don’t need to use .title
with Ref()
because it does that automatically for you.
But for DependsOn
we specifically need to insert the name of the resource - which is exposed under title
property.
**
If you want to see this in action, check out our cloudformation-examples repository on GitHub with a full example , which creates a VPC with Auto scaling group and an RDS instance.
**