Introducción
En este laboratorio, explorarás Jinja2, el potente motor de plantillas utilizado por Ansible. Jinja2 te permite crear contenido dinámico, lo que hace que tus playbooks de Ansible sean más flexibles y adaptables. Al final de este laboratorio, entenderás cómo utilizar la sintaxis de Jinja2 en Ansible, incluyendo variables, filtros, condicionales y bucles. Este conocimiento te permitirá crear playbooks y roles de Ansible más dinámicos y eficientes.
Comprendiendo los conceptos básicos de Jinja2
Jinja2 es un lenguaje de plantillas moderno y amigable con el diseñador para Python, inspirado en las plantillas de Django. En Ansible, Jinja2 se utiliza para crear plantillas de archivos, estructuras de play dinámicas y más.
Comencemos creando una plantilla Jinja2 simple. Primero, navega hasta el directorio de tu proyecto:
cd ~/project
Ahora, creemos un directorio para nuestras plantillas:
mkdir templates
cd templates
Crea un nuevo archivo llamado hello.j2:
nano hello.j2
Agrega el siguiente contenido:
Hello, {{ name }}!
Today is {{ ansible_date_time.date }}.
Your home directory is {{ ansible_env.HOME }}.
Guarda y sale del editor nano (Ctrl+X, luego Y, luego Enter).
En esta plantilla:
{{ name }}es una variable que se reemplazará con un valor real cuando se renderice la plantilla.{{ ansible_date_time.date }}y{{ ansible_env.HOME }}son hechos (facts) de Ansible que se llenarán automáticamente.
Ahora, creemos un playbook para usar esta plantilla. Regresa a la raíz del proyecto y crea un nuevo archivo llamado use_template.yml:
cd ~/project
nano use_template.yml
Agrega el siguiente contenido:
---
- name: Use Jinja2 template
hosts: localhost
vars:
name: "Ansible Learner"
tasks:
- name: Create file from template
template:
src: templates/hello.j2
dest: /tmp/hello.txt
Este playbook utiliza el módulo template para renderizar nuestra plantilla Jinja2 y crear un archivo en /tmp/hello.txt.
Ejecuta el playbook:
ansible-playbook use_template.yml
Después de ejecutar el playbook, verifica el contenido del archivo creado:
cat /tmp/hello.txt
Deberías ver la plantilla renderizada con la variable y los hechos reemplazados por valores reales.
Usando filtros de Jinja2
Los filtros de Jinja2 son funciones que se pueden aplicar a variables. Se separan de la variable por un símbolo de tubería (|). Ansible incluye muchos filtros integrados, y también puedes crear tus propios filtros personalizados.
Creemos una nueva plantilla que demuestre algunos filtros comunes. Crea un nuevo archivo llamado filters.j2:
cd ~/project/templates
nano filters.j2
Agrega el siguiente contenido:
1. Uppercase filter: {{ name | upper }}
2. Length filter: {{ name | length }}
3. Default filter: {{ optional_var | default('No value provided') }}
4. Join filter: {{ fruits | join(', ') }}
5. Random item: {{ fruits | random }}
6. First item: {{ fruits | first }}
7. JSON encode: {{ complex_data | to_json }}
Ahora, creemos un playbook para usar esta plantilla. Regresa a la raíz del proyecto y crea un nuevo archivo llamado use_filters.yml:
cd ~/project
nano use_filters.yml
Agrega el siguiente contenido:
---
- name: Use Jinja2 filters
hosts: localhost
vars:
name: "ansible learner"
fruits:
- apple
- banana
- cherry
complex_data:
key1: value1
key2:
- item1
- item2
tasks:
- name: Create file from template
template:
src: templates/filters.j2
dest: /tmp/filters.txt
- name: Display file contents
command: cat /tmp/filters.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.stdout_lines
Este playbook aplica varios filtros de Jinja2 a nuestras variables y muestra los resultados.
Ejecuta el playbook:
ansible-playbook use_filters.yml
La salida te mostrará cómo cada filtro modifica los datos de entrada. Esto demuestra cómo se pueden usar los filtros para manipular datos dentro de tus plantillas.
Condicionales de Jinja2
Jinja2 te permite utilizar declaraciones condicionales en tus plantillas. Esto es especialmente útil cuando necesitas incluir o excluir contenido basado en ciertas condiciones.
Crea un nuevo archivo de plantilla llamado conditionals.j2:
cd ~/project/templates
nano conditionals.j2
Agrega el siguiente contenido:
{% if user_type == 'admin' %}
Welcome, Administrator!
You have full access to the system.
{% elif user_type == 'user' %}
Welcome, User!
You have limited access to the system.
{% else %}
Welcome, Guest!
You have read-only access to the system.
{% endif %}
{% if fruits %}
Available fruits:
{% for fruit in fruits %}
- {{ fruit }}
{% endfor %}
{% else %}
No fruits available.
{% endif %}
Ahora, creemos un playbook para usar esta plantilla. Regresa a la raíz del proyecto y crea un nuevo archivo llamado use_conditionals.yml:
cd ~/project
nano use_conditionals.yml
Agrega el siguiente contenido:
---
- name: Use Jinja2 conditionals
hosts: localhost
vars:
user_type: "admin"
fruits:
- apple
- banana
- cherry
tasks:
- name: Create file from template (admin)
template:
src: templates/conditionals.j2
dest: /tmp/conditionals_admin.txt
- name: Create file from template (user)
template:
src: templates/conditionals.j2
dest: /tmp/conditionals_user.txt
vars:
user_type: "user"
- name: Create file from template (guest)
template:
src: templates/conditionals.j2
dest: /tmp/conditionals_guest.txt
vars:
user_type: "guest"
fruits: []
- name: Display file contents
command: "cat {{ item }}"
loop:
- /tmp/conditionals_admin.txt
- /tmp/conditionals_user.txt
- /tmp/conditionals_guest.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.results[item].stdout_lines
loop: [0, 1, 2]
Este playbook crea tres archivos diferentes utilizando la misma plantilla pero con diferentes valores de variables, demostrando cómo funcionan las declaraciones condicionales en la plantilla.
Ejecuta el playbook:
ansible-playbook use_conditionals.yml
La salida te mostrará cómo cambia el contenido de la plantilla en función de las diferentes condiciones.
Bucles de Jinja2
Jinja2 proporciona estructuras de bucle que te permiten iterar sobre listas y diccionarios. Esto es especialmente útil cuando necesitas generar contenido repetitivo basado en datos variables.
Crea un nuevo archivo de plantilla llamado loops.j2:
cd ~/project/templates
nano loops.j2
Agrega el siguiente contenido:
1. Simple loop:
{% for item in simple_list %}
- {{ item }}
{% endfor %}
2. Loop with index:
{% for item in simple_list %}
{{ loop.index }}. {{ item }}
{% endfor %}
3. Loop over a dictionary:
{% for key, value in simple_dict.items() %}
{{ key }}: {{ value }}
{% endfor %}
4. Nested loop:
{% for category, items in nested_dict.items() %}
{{ category }}:
{% for item in items %}
- {{ item }}
{% endfor %}
{% endfor %}
5. Conditional in loop:
{% for item in simple_list %}
{% if loop.first %}First item: {% endif %}
{% if loop.last %}Last item: {% endif %}
{{ item }}
{% endfor %}
Ahora, creemos un playbook para usar esta plantilla. Regresa a la raíz del proyecto y crea un nuevo archivo llamado use_loops.yml:
cd ~/project
nano use_loops.yml
Agrega el siguiente contenido:
---
- name: Use Jinja2 loops
hosts: localhost
vars:
simple_list:
- apple
- banana
- cherry
simple_dict:
name: John Doe
age: 30
city: New York
nested_dict:
fruits:
- apple
- banana
vegetables:
- carrot
- potato
tasks:
- name: Create file from template
template:
src: templates/loops.j2
dest: /tmp/loops.txt
- name: Display file contents
command: cat /tmp/loops.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.stdout_lines
Este playbook demuestra varias formas de usar bucles en plantillas Jinja2.
Ejecuta el playbook:
ansible-playbook use_loops.yml
La salida te mostrará cómo las diferentes estructuras de bucle en la plantilla generan contenido basado en las variables proporcionadas.
Técnicas avanzadas de Jinja2
En este último paso, exploraremos algunas técnicas avanzadas de Jinja2, incluyendo macros y filtros. Las macros son fragmentos de plantilla reutilizables, similares a las funciones en los lenguajes de programación.
Crea un nuevo archivo de plantilla llamado advanced.j2:
cd ~/project/templates
nano advanced.j2
Agrega el siguiente contenido:
{% macro render_list(title, items) %}
{{ title }}:
{% for item in items %}
- {{ item }}
{% endfor %}
{% endmacro %}
1. Using a macro:
{{ render_list("Fruits", fruits) }}
{{ render_list("Vegetables", vegetables) }}
2. Using set:
{% set greeting = "Hello, " + name + "!" %}
{{ greeting }}
3. Custom filter (defined in playbook):
{{ complex_data | to_nice_json }}
4. Whitespace control:
{% for item in fruits -%}
{{ item }}
{%- if not loop.last %}, {% endif %}
{%- endfor %}
5. Raw block (no processing):
{% raw %}
This {{ will_not_be_processed }}
{% endraw %}
6. Include another template:
{% include 'simple_include.j2' %}
Ahora, creemos el archivo de inclusión simple. Crea un nuevo archivo llamado simple_include.j2:
nano simple_include.j2
Agrega el siguiente contenido:
This is content from an included template.
Current user: {{ ansible_user_id }}
Ahora, creemos un playbook para usar esta plantilla avanzada. Regresa a la raíz del proyecto y crea un nuevo archivo llamado use_advanced.yml:
cd ~/project
nano use_advanced.yml
Agrega el siguiente contenido:
---
- name: Use advanced Jinja2 techniques
hosts: localhost
vars:
name: "Ansible Expert"
fruits:
- apple
- banana
- cherry
vegetables:
- carrot
- potato
- broccoli
complex_data:
key1: value1
key2:
- item1
- item2
custom_filters:
to_nice_json: "{{ '(' ~ ((complex_data | to_json) | replace('\"', '\\\"')) ~ ')' | from_json | to_nice_json }}"
tasks:
- name: Create file from template
template:
src: templates/advanced.j2
dest: /tmp/advanced.txt
- name: Display file contents
command: cat /tmp/advanced.txt
register: file_contents
- name: Show file contents
debug:
var: file_contents.stdout_lines
Este playbook demuestra técnicas avanzadas de Jinja2, incluyendo macros, filtros personalizados, control de espacios en blanco e inclusión de otras plantillas.
Ejecuta el playbook:
ansible-playbook use_advanced.yml
La salida te mostrará cómo funcionan estas técnicas avanzadas de Jinja2 en la práctica.
Resumen
En este laboratorio, has explorado las plantillas de Jinja2 en Ansible, cubriendo una amplia gama de características y técnicas. Estos son los puntos clave:
- Sintaxis básica de Jinja2: Aprendiste cómo usar variables y hechos (facts) de Ansible en plantillas.
- Filtros de Jinja2: Exploraste varios filtros integrados para manipular datos dentro de las plantillas.
- Condicionales: Usaste declaraciones if-elif-else para crear contenido dinámico basado en condiciones.
- Bucles: Aprendiste cómo iterar sobre listas y diccionarios, incluyendo bucles anidados y controles de bucle.
- Técnicas avanzadas: Exploraste macros, filtros personalizados, control de espacios en blanco, bloques raw e inclusión de plantillas.
Estas características de Jinja2 te permiten crear plantillas altamente dinámicas y flexibles en Ansible. Te permiten generar archivos de configuración, scripts y otro contenido que puede adaptarse a diferentes escenarios y entradas de datos.
A medida que sigas trabajando con Ansible, descubrirás que dominar las plantillas de Jinja2 es crucial para crear playbooks y roles eficientes y adaptables. Te permite escribir código más conciso y mantenible, reduciendo la repetición y haciendo que tus proyectos de Ansible sean más escalables.
Recuerda que aunque Jinja2 es poderoso, es importante equilibrar la flexibilidad con la legibilidad. Las plantillas demasiado complejas pueden ser difíciles de mantener, así que siempre busca la claridad en el diseño de tus plantillas.
Practica el uso de estas características de Jinja2 en tus proyectos de Ansible, y podrás manejar tareas de automatización cada vez más complejas con facilidad.


