Jinja2 templates are essential for handling tasks that involve advanced file modifications. When you use templates, target files on discovered hosts are automatically customized using variables and Ansible facts. A variable defined in a template is replaced with the correct value when the Jinja2 template is rendered to the target file on a managed host.
[ Download the Jinja2 cheat sheet. ]
This article demonstrates using Jinja2 templates and Ansible. To follow along, you need at least two virtual machines (VMs) managed by Ansible and one Ansible control node. I'm running Red Hat Enterprise Linux (RHEL) on one VM and CentOS Stream on the other.
Prepare your Ansible control node by installing Ansible, configuring ansible.cfg, and creating an inventory file for the hosts managed by Ansible.
Configure Ansible
In the ansible.cfg file, define a string called ansible_managed to prevent administrators from overwriting files managed by Ansible. It doesn't exist yet, but later an {{ ansible_managed }} variable, placed at the top of a Jinja2 template, will refer to the string defined here:
[defaults]
retry_files_enabled = False
timeout = 60
connection = smart
interpreter_python = auto
forks = 10
inventory = /home/vcirrus-consulting/RHCE-Ansible/inventory-gather-facts.yml
roles_path = /home/vcirrus-consulting/RHCE-Ansible/roles:/usr/share/ansible/roles
remote_user = ansible-devops
host_key_checking = False
command_warnings = False
deprecation_warnings = False
ansible_managed = Caution: This File is Managed By Ansible - DO NOT EDIT MANUALLY.
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
Next, create a static inventory file in a project directory with a list of hosts. I store mine in ~/RHCE-Ansible/inventory-gather-facts.yml, and here are its contents:
all:
children:
mombasa_one_dc:
hosts:
ansible01.test.lab:
nairobi_one_dc:
hosts:
ansible13.test.lab:
prod:
hosts:
ansible01.test.lab:
ansible02.test.lab:
ansible12.test.lab:
ansible13.test.lab:
ungrouped: {}
[ Learn more about server and configuration management by downloading Ansible for DevOps. ]
Create a Jinja2 template
Create a Jinja2 template file named rhel_managed_infra_report.j2. Jinja2 expressions in this file refer to the ansible_facts variable. The expressions also implement error handling by using the Jinja2 default filter, which ensures no unnecessary errors are returned as a result of running the playbook. In this case, the playbook displays NONE when the variable defined does not exist:
{{ ansible_managed }}
INVENTORY_HOSTNAME = {{ inventory_hostname | default('NONE',true) }}
OS_DISTRO_VERSION = {{ ansible_distribution_version | default('NONE',true) }}
Next, create a playbook called rhel_managed_infra_report.yml and use the template module to inject the Jinja2 template file into the playbook.
After executing the playbook on the Ansible-managed remote nodes, the dest element stores the results. The src element defines the Jinja2 template for Ansible to use.
Note that the src path in the playbook can be a relative path, which means the file exists in your current working directory, or it can be expressed as an absolute path.
---
- hosts: 'prod,&mombasa_one_dc'
tasks:
- name: Deploying Template to Gather and Save info from Remote Systems
ansible.builtin.template:
src: rhel_managed_infra_report.j2
dest: /root/hwreport.txt
mode: preserve
- hosts: 'prod,&nairobi_one_dc'
tasks:
- name: Deploying Template to Gather and Save info from Remote Systems
ansible.builtin.template:
src: rhel_managed_infra_report.j2
dest: /root/hwreport.txt
mode: preserve
[…]
Run the Ansible playbook using ansible-navigator. It consists of two tasks, the first of which must run on hosts that belong to the groups prod and mombasa_one_dc. The second task must run on hosts belonging to the groups prod and nairobi_one_dc.
$ ansible-navigator run --mode stdout rhel_managed_infra_report.yml
PLAY [prod,&mombasa_one_dc] *********************
TASK [Gathering Facts] *******************************
ok: [ansible01.test.lab]
TASK [Deploying Template to Gather and Save info from Remote Systems] ***
changed: [ansible01.test.lab]
PLAY [prod,&nairobi_one_dc] ************************
TASK [Gathering Facts] *********************************************************
ok: [ansible13.test.lab]
TASK [Deploying Template to Gather and Save info from Remote Systems] **********
changed: [ansible13.test.lab]
PLAY RECAP *********************************************************************
ansible01.test.lab: ok=2 changed=1 unreachable=0 failed=0...
ansible13.test.lab: ok=2 changed=1 unreachable=0 failed=0...
Notice that out of all the hosts listed in my hosts file, only ansible01 and ansible13 are affected. This is because they are the only ones that satisfied the playbook's group requirements.
[ Download now: Advanced Linux commands cheat sheet. ]
Verify success
Run an Ansible ad hoc command to verify that the information has been recorded to the specific remote directory defined in the playbook. These results display all information translated from the Jinja2 template file on ansible13.test.lab running RHEL:
$ ansible ansible13.test.lab -a "cat /root/hwreport.txt"
ansible13.test.lab | CHANGED | rc=0 >>
Caution: This File is Managed By Ansible - DO NOT EDIT MANUALLY.
INVENTORY_HOSTNAME = ansible13.test.lab
OS_DISTRO_VERSION = Plow
The information for ansible01.test.lab, running CentOS Stream:
$ ansible ansible01.test.lab -a "cat /root/hwreport.txt"
ansible01.test.lab | CHANGED | rc=0 >>
Caution: This File is Managed By Ansible - DO NOT EDIT MANUALLY.
INVENTORY_HOSTNAME = ansible01.test.lab
OS_DISTRO_VERSION = Stream
Notice that the values of OS_DISTRO_VERSION are unique in the rendered files, even though the same playbook generated both. That's the power of statements like OS_DISTRO_VERSION = {{ ansible_distribution_release | default('NONE',true) }}, which uses local data to generate content.
[ Get a cheat sheet of Linux utilities and commands for managing servers and networks. ]
Use Ansible facts in Jinja2
You can expand the information you gather by using other built-in ansible_facts variables for Jinja2. Modify your rhel_managed_infra_report.j2 template file:
{{ ansible_managed }}
INVENTORY_HOSTNAME = {{ inventory_hostname | default('NONE',true) }}
OS_DISTRO_VERSION = {{ ansible_distribution_version | default('NONE',true) }}
PYTHON_VERSION = {{ ansible_python_version | default('NONE',true) }}
SELINUX_STATUS = {{ ansible_selinux | default('NONE',true) }}
BIOS_VERSION = {{ ansible_bios_version | default('NONE',true) }}
BIOS_DATE = {{ ansible_bios_date | default('NONE',true) }}
TOTAL_MEMORY = {{ ansible_memtotal_mb | default('NONE',true) }}
CURRENT_MEMORY_USAGE = {{ ansible_memory_mb['real']['used']}} mb out of {{ ansible_memory_mb['real']['total']}} mb
OS_FAMILY = {{ ansible_os_family | default('NONE',true) }}
OS_DISTRO = {{ ansible_distribution | default('NONE',true) }}
OS_KERNEL_VERSION = {{ ansible_kernel | default('NONE',true) }}
OS_ARCHITECTURE = {{ ansible_architecture | default('NONE',true) }}
PROCESSOR = {{ ansible_processor | default('NONE',true) }}
VIRT_TYPE = {{ ansible_virtualization_type | default('NONE',true) }}
VDA_SIZE = {% if ansible_devices.vda is defined %}
{{ ansible_devices.vdb.size }}{% else %}
NONE
{% endif %}
VDB_SIZE = {% if ansible_devices.vdb is defined %}
{{ ansible_devices.vdb.size }}{% else %}
NONE
{% endif %}
Run that and look at the output. That's a lot of useful information about each system, and all it takes is one template file and a playbook!
To get a list of all the ansible_facts variables for a Jinja2 template file, use this ad hoc command on any managed node:
$ ansible <managed_host_fqdn or managed_host_ipaddress> -m setup -a "filter=ansible_*"
The power of templates
This article touches on the power of using Jinja2 templates with Ansible. Explore further and see how you can implement the lessons learned from this article to extract valuable information configured in your remote systems. For example, try tinkering with your remote storage configuration or collecting information in a multivendor hybrid environment.
À propos de l'auteur
Robert is a Linux enthusiast and an open source advocate, currently transitioning into a site reliability engineering (SRE) role. Always striving to learn more, he's pursuing Red Hat Certified Architect - Infrastructure path certification. Besides his love for Linux, he believes in helping others and is compassionate about giving back to the community. When he's not on a Linux terminal, he likes hiking, mountain biking, and exploring nature.
Plus de résultats similaires
Slash VM provisioning time on Red Hat Openshift Virtualization using Red Hat Ansible Automation Platform
Red Hat Ansible Automation Platform: Measuring Business Impact with Dashboard and Analytics
Technically Speaking | Taming AI agents with observability
Lightspeed automation with generative AI | Technically Speaking
Parcourir par canal
Automatisation
Les dernières nouveautés en matière d'automatisation informatique pour les technologies, les équipes et les environnements
Intelligence artificielle
Actualité sur les plateformes qui permettent aux clients d'exécuter des charges de travail d'IA sur tout type d'environnement
Cloud hybride ouvert
Découvrez comment créer un avenir flexible grâce au cloud hybride
Sécurité
Les dernières actualités sur la façon dont nous réduisons les risques dans tous les environnements et technologies
Edge computing
Actualité sur les plateformes qui simplifient les opérations en périphérie
Infrastructure
Les dernières nouveautés sur la plateforme Linux d'entreprise leader au monde
Applications
À l’intérieur de nos solutions aux défis d’application les plus difficiles
Virtualisation
L'avenir de la virtualisation d'entreprise pour vos charges de travail sur site ou sur le cloud