Python templates in GCP Deployment Manager

Imagine we have Deployment Manager’s config file that creates a virtual machine from certain image and assigns an ephemeral public IP address to it. Something like this:

If I decided to create 5 other VMs, similar to this one, I’d probably have to copy-paste the config, changing just the tiny pieces: the name and probably the zone with the image.

However, Deployment manager supports Jinja and Python templates, so we can move a repetitive blocks into those, leaving only customizable parts on the surface. Let’s see is how it works for Python.

How it works

Instead of using predefined resource types, like compute.v1.instance (see line #3 in YAML above) or others, we can create a custom template file and use that one as a type. Then, when executed, template will take the ‘surrounding’ YAML properties from a config file, process it using whatever rules that you define, and produce actual resource(es) YAML to be deployed. It’s way simple than it sounds, trust me. To prove the point, let’s have a look at an example.

Moving VM config to a template

Here’s the task. I want to turn the original config into a template, which will accept only four parameters: a name, a zone, a source image and whether or not to create an external IP address. Everything else should come predefined. In other words, I want the template which will make the following config YAML possible:

This config simply creates two virtual machines with different OSes and in different availability zones. What’s more, one VM will have an external IP, while the other one will not. This is how the template for it might look like:

The template is pretty straightforward. create_config function is the one that receives ‘surrounding’ YAML config as input parameter (context) and returns a dictionary, which would turned out to be a perfectly valid YAML config, if we’d ever bothered to serialize it.

As you can see, some of template parameters (e.g. zone) are coming from the context.properties dictionary, whereas the other (name) from the context.env. There’s no special magical reason for that. context.properties maps one to one to config’s YAML properties and this is where customizable parameters usually come from. env['name'] on the other hand is one of predefined environmental variables, which in this case carries the resource name (- name: first-vm). That was a shortcut that allowed me to avoid adding one more property to properties collection and reuse the resource name as a VM name.

Everything else is trivial. We populate the properties, check if assign_public_ip was provided, and if yes, populate  accessConfig network section, etc.

Unfortunately, at the moment of writing deployment manager can’t preprocess templates and show resulting YAML, so we could validate if a template we’re developing actually makes sense. gcloud deployment-manager deployments create has a --preview option, but it has a different purpose.

After deploying new config with gcloud deployment-manager deployment my-cluster --config templated-deployment.yaml we’ll see two new VMs coming to life, plus all the details about what resulting configuration looks like and which templates were involved.

instances

templated deployment

Summary

Deployment Manager templates are incredibly powerful. Not only they save the keystrokes and lines of otherwise repeatable configuration, but because it’s backed by the power of general purpose language, we could do all sorts of crazy tricks with them. Generate more than one resource per config entry, nest templates, combine multiple resources and their configuration as a single building block – just to name a few.

Google also has a few dozens of samples. Though somewhat messy and out of date, they are still very good aid for getting started. Plus, there’s new branch under active development, which has newer, cleaner and more powerful templates. But it’s just about one month old, so there’s not much to choose from yet.

Leave a Reply

Your email address will not be published. Required fields are marked *