Understanding Ansible templates

A common automation requirement is to set a value in a configuration file, or even to deploy a new configuration file, based on some given parameters. Ansible provides modules that can perform similar functions to the venerable sed and awk utilities, and of course, these are valid ways to modify an existing configuration file. Let's suppose we have a small Apache virtual host configuration file, containing the following code:

<VirtualHost *:80>
DocumentRoot "/var/www/automation"
ServerName www.example.com
</VirtualHost>

We want to deploy this configuration, but customize the DocumentRoot parameter for each host. Naturally, we could just deploy the preceding file, exactly as it is, to every host, and then use a regular expression, in conjunction with the Ansible replace module, to find the DocumentRoot line and modify it (similar to using the sed command-line utility). The resulting playbook might look like this:

---
- name: Deploy and customize an Apache configuration
hosts: localhost
become: true

vars:
docroot: "/var/www/myexample"

tasks:
- name: Copy static configuration file to remote host
copy:
src: files/vhost.conf
dest: /etc/apache2/sites-available/my-vhost.conf

- name: Replace static DocumentRoot with variable contents
replace:
path: /etc/apache2/sites-available/my-vhost.conf
regexp: '^(s+DocumentRoot)s+.*$'
replace: '1 {{ docroot }}'

If we create our sample static virtual host configuration file in files/vhost.conf with the preceding contents shown and run this playbook, we can see that it works, as follows:

However, this is an inelegant solution. First of all, we're using two tasks, and if we wanted to customize ServerName as well, we'd need even more. Secondly, those who are familiar with regular expressions will know it wouldn't take much to trip up the simple one used here. Writing good robust regular expressions for tasks such as this is an art in itself.

Luckily, Ansible has inherited from the Python in which it is written a technology called Jinja2 templating. This is perfect for scenarios such as this (and many other deployment-related automation scenarios). Instead of a cumbersome multistep approach such as this, we now define our starting virtual host configuration file as a template in templates/vhost.conf.j2, as follows:

<VirtualHost *:80>
DocumentRoot {{ docroot }}
ServerName www.example.com
</VirtualHost>

As you can see, this is almost identical to our original configuration file, except that we have now replaced one of the static values with one of our variables, surrounded by pairs of curly braces, just as we would do in the playbook itself. Before we proceed with this example, it is worth mentioning that Jinja2 is an incredibly powerful templating system that goes far beyond simple variable substitution into a flat file. It is capable of conditional statements, such as if...else and for loops, and includes a wide array of filters that can be used to manipulate content (for example, to convert a string to uppercase, or to join the members of a list together to form a string). 

With that said, this book is not intended as a complete language reference for either Ansible or Jinja2—rather, it is intended as a practical guide to show you how to build up your SOE using Ansible. Please refer to the Further reading section at the end of this chapter for some references, which will give you a more complete overview of both Ansible and Jinja2.

Returning to our example, we will modify the playbook to deploy this example, as follows:

---
- name: Deploy and customize an Apache configuration
hosts: localhost
become: true

vars:
docroot: "/var/www/myexample"

tasks:
- name: Copy across and populate the template configuration
template:
src: templates/vhost.conf.j2
dest: /etc/apache2/sites-available/my-vhost.conf

Notice how much more elegant this playbook is—the template module copies the configuration template to the remote host, just as the copy module did in the prior example, and also populates any variables we have specified. This is an incredibly powerful way to deploy configuration files in a repeatable, common manner, and it is highly recommended that you adopt this approach where possible. When human beings edit files, they often do so in an inconsistent manner, and that can be the enemy of automation, as you have to build a really robust regular expression to ensure you catch all possible edge cases. Deploying from templates with Ansible creates repeatable, reliable results that can easily be validated in a production environment. Running this playbook yields identical results to our previous, more complex example, as follows:

That concludes our look at variables for now, and indeed, our crash course in Ansible. In the next section, we tie up everything we have learned, before drawing this chapter to a close. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset