In configuration management and automation, templates play a very important role. They allow you to create dynamic, reusable file content by using variables and other expressions in text files. In the context of Ansible, the template engine of choice is Jinja2. You will create mostly configuration templates in Jinja2 format, and address them in your playbooks with the ansible.builtin.template module. In this lesson you will also learn how can you use expressions in the template files.
What are templates?
Templates are like blueprints for generating configuration files, scripts, or any other text-based content. Instead of hardcoding values directly into files, you use placeholders (variables) that get replaced with the actual data during runtime.
This approach offers several advantages:
- Reusability: Templates allow you to create a single configuration file that adapts to different environments or scenarios. For instance, you can use the same template to generate Nginx configurations for development, staging, and production servers.
- Dynamic content: With templates, you can inject dynamic information such as hostnames, IP addresses, and version numbers. This flexibility ensures that your configurations remain up-to-date and relevant.
- Separation of concerns: By separating the template logic from the actual content, you can maintain cleaner, more readable configuration files. Changes to variables or expressions are isolated to the template, not scattered throughout the entire file.
Jinja2: the template engine
Jinja2 is a powerful and flexible template engine written in Python.
Ansible uses Jinja2 to process templates and generate files.
Here’s how it works:
- Expressions: Jinja2 allows you to embed expressions within double curly braces (
{{ ... }}). These expressions can be variables, filters, or even complex calculations. For example:My name is {{ ansible_facts['hostname'] }}In this snippet,ansible_facts['hostname']retrieves the hostname of the target machine. - Filters: Jinja2 provides a rich set of filters for transforming data. Filters allow you to manipulate variables before rendering them. For instance, we can capitalize strings, format dates, or extract specific elements from lists.
- Control Structures: You can use control structures like loops and conditionals in Jinja2 templates. These structures enable dynamic decision-making within the template.
Using templates in Ansible
Simple template files and the template module
The primary way to use Jinja2 in Ansible is through the template module.
Here’s an example playbook that uses the ansible.builtin.template module and creates a file called template.txt:
- name: Learning about Ansible templates
hosts: all
tasks:
- name: Using a template
ansible.builtin.template:
src: 1-template.j2
dest: /home/tmolnar/ansible/lesson07/template.txt
The template file 1-template.j2 that will you use for rendering the template.txt outcome looks like this:
Hello, we are running on {{ inventory_hostname }},
The OS family is {{ ansible_facts["os_family"] }}.
The Linux distribution is {{ ansible_facts["distribution"] }} {{ ansible_facts["distribution_major_version"] }}.
Note that the file extension of the template file is .j2!
Running the playbook will use the variables (Ansible Facts here) and create the following rendered file:
Hello, we are running on 192.168.1.91,
The OS family is Debian.
The Linux distribution is Debian 12.
This is a basic example of using Jinja2 templates with Ansible playbooks.
The placeholder variables enclosed by {{ and }} are substituted by the data from the Facts.
You can do more with the templates, like creating dynamic file rendering with loops and conditionals.
Loops and control structures in templates
In Jinja2 loops are formed with the for keyword.
Let’s investigate the following template file:
Hello,
Here you can use loops in Jinja2 templates!
The users from the vars are:
{% for u in template_users %}
- {{ u }}
{% endfor %}
Some hashes:
{% for h in t_data %}
- {{ h.name }} uses {{ h.system }}
{% endfor %}
If you feed this template file with the following set of variables from the playbook:
vars:
template_users:
- Joe
- John
- Jake
t_data:
- { name: Tom, system: Linux }
- { name: Tim, system: Windows }
The above template will render the expected output using a list and a list of hashes.
Try out, and run the playbook, check its output!
Conditional statements can be incorporated in templates using the if keyword.
You can render the templates based on different conditions like the existence of variables.
If the section variable is true the
following text will be rendered:
{% if section is true %}
The section variable was true.
{% endif %}
Templates are very powerful elements of your Ansible toolset. With this knowledge you can cover the 99% of the beginner tasks to automate basic configuration.
Now you are ready to learn more about variables, and about securing them with Ansible Vault!
If you want to discuss the topic with other technology-minded people, join my Discord: https://discord.gg/YbSYGsQYES
Now we have an IRC channel as well: irc.libera.chat / #tomsitcafe
very interesting
LikeLike