Templates Jinja2
Jinja2 est le moteur de templating utilisé dans Ansible, aussi bien dans les fichiers .j2 que dans les valeurs de variables directement dans les playbooks. Maîtriser Jinja2 permet de générer des fichiers de configuration dynamiques, d'écrire des conditions expressives, et d'éviter la duplication de playbooks pour des environnements légèrement différents.
Module template
Le module template traite un fichier source Jinja2 et dépose le résultat rendu sur la cible :
- ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: "0644"
validate: nginx -t -c %s # validation avant déploiementPar convention, les templates sont placés dans templates/ avec l'extension .j2. Le chemin src est relatif au répertoire du playbook ou du rôle.
Syntaxe Jinja2
# Substitution de variable
server_name {{ app_domain }};
# Condition
{% if ssl_enabled %}
listen 443 ssl;
ssl_certificate /etc/ssl/certs/{{ app_domain }}.pem;
{% else %}
listen 80;
{% endif %}
# Boucle
upstream backend {
{% for host in groups['app'] %}
server {{ hostvars[host]['ansible_default_ipv4']['address'] }}:{{ app_port }};
{% endfor %}
}Filtres essentiels
Les filtres transforment une valeur. Syntaxe : {{ valeur | filtre }}.
# Valeur par défaut si variable non définie ou vide
{{ app_timeout | default(30) }}
{{ app_name | default('myapp') | upper }}
# Manipulation de chaînes
{{ app_name | upper }} # MYAPP
{{ app_name | lower }} # myapp
{{ app_name | replace('-', '_') }}
{{ app_domain | regex_replace('\.', '_') }}
# Listes
{{ mylist | join(', ') }}
{{ mylist | length }}
{{ mylist | sort }}
{{ mylist | unique }}
{{ mylist | select('match', '^web') | list }}
# Dictionnaires
{{ mydict | dict2items }} # convertit en liste de {key, value}
{{ items_list | items2dict }} # inverse
# Nombres
{{ memory_mb | int * 1024 * 1024 }}
{{ value | round(2) }}
# Réseau
{{ '192.168.1.0/24' | ansible.utils.ipaddr('network') }}
# JSON
{{ myvar | to_json }}
{{ myvar | to_nice_json }}Tests Jinja2
Les tests retournent un booléen, utilisables dans when ou {% if %} :
{% if app_port is defined %}
listen {{ app_port }};
{% endif %}
{% if myvar is none %}
# variable non définie ou nulle
{% endif %}
{% if myvar is string %}
# c'est une chaîne
{% endif %}
{% if myvar is iterable %}
# c'est une liste ou un dict
{% endif %}Exemple concret : configuration nginx
# templates/nginx.conf.j2
worker_processes {{ nginx_worker_processes | default(ansible_processor_vcpus) }};
events {
worker_connections {{ nginx_worker_connections | default(1024) }};
}
http {
upstream {{ app_name }}_backend {
{% for host in groups[app_group | default('app')] %}
server {{ hostvars[host]['ansible_default_ipv4']['address'] }}:{{ app_port }};
{% endfor %}
}
server {
listen 80;
server_name {{ app_domain }};
{% if redirect_to_https | default(false) %}
return 301 https://$host$request_uri;
{% else %}
location / {
proxy_pass http://{{ app_name }}_backend;
}
{% endif %}
}
}Le filtre default : éviter les erreurs
Sans default(), une variable non définie lève une erreur. Avec default(), on définit un comportement de repli :
# Valeur de secours fixe
{{ timeout | default(30) }}
# Valeur de secours dynamique
{{ workers | default(ansible_processor_vcpus * 2) }}
# Comportement si false ou vide (deuxième argument à true)
{{ myvar | default('fallback', true) }}