¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Plantillas Jinja2 y handlers en Ansible

Después de esta lección: Puedo rellenar una plantilla con variables y explicar cuántas veces se ejecuta un handler.

Lección de 60 min10 comandosLaboratorio de roles de Ansible: un rol, handlers y Vault en una VM Ubuntu

Plantilla que se rellena, handler que espera

Una plantilla de Ansible es un archivo de texto con huecos que se rellenan con variables, escrito en el lenguaje Jinja2. Un handler es una tarea que solo se ejecuta cuando otra avisa de que cambió algo.

Juntos reescriben un archivo de configuración y avisan a un servicio solo cuando el archivo ha cambiado de verdad. Aquí el archivo es el recibo de una librería.

Al final de esta lección

Nota

Puedo rellenar una plantilla con variables y explicar cuántas veces se ejecuta un handler.

Palabras clave

PalabraQué significaEjemplo
Plantillaun archivo de texto con huecos para variablesrecibo.txt.j2
Jinja2el lenguaje de las plantillas de Ansible
Bucle forrepite un trozo de la plantilla por cada elemento{% for l in lineas %}
Condición ifescribe un trozo solo si algo es cierto{% if envio %}
Handleruna tarea que espera un aviso y corre una sola vez
notifyla palabra con que una tarea avisa a un handler

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Jinja2 rellena huecos, repite y decide

En una plantilla, {{ tienda }} es un hueco que se sustituye por el valor de la variable. {% for l in lineas %} repite lo que sigue, hasta {% endfor %}, una vez por elemento.

{% if envio %} escribe el trozo hasta {% endif %} solo si la variable es cierta. Las etiquetas con {% no escriben nada: el módulo template quita su línea.

Crea una carpeta de trabajo

Comando
mkdir -p ~/recibos

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Entra en ella

Comando
cd ~/recibos

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe la plantilla del recibo

Comando
printf '%s\n' 'Recibo de {{ tienda }}' '{% for l in lineas %}' '{{ l.nombre }}: {{ l.precio }} {{ moneda }}' '{% endfor %}' '{% if envio %}' 'Incluye envio' '{% endif %}' > recibo.txt.j2

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lee la plantilla

Comando
cat recibo.txt.j2

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejemplo: de la plantilla al recibo

Línea de la plantillaCon los datos de la tiendaResultado
Recibo de {{ tienda }}tienda = Libreria SolRecibo de Libreria Sol
{{ l.nombre }}: {{ l.precio }} {{ moneda }}Cuaderno, 3 y EURCuaderno: 3 EUR
Lo mismo, otra vuelta del forBoligrafo, 2 y EURBoligrafo: 2 EUR
Incluye envio, dentro del ifenvio = falseNo se escribe

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una ejecución en seco muestra los cambios

El playbook guarda las variables en su play y usa la plantilla con el módulo template. La tarea avisa con notify a un handler llamado Avisar a caja. Otra tarea escribe un sello y avisa al mismo.

La opción --check --diff hace una ejecución en seco: no escribe nada y muestra qué cambiaría. El grep deja solo las líneas que se añadirían.

Escribe el playbook con su handler

Comando
printf -- '---\n- hosts: all\n  gather_facts: false\n  vars:\n    tienda: Libreria Sol\n    moneda: EUR\n    lineas:\n      - {nombre: Cuaderno, precio: 3}\n      - {nombre: Boligrafo, precio: 2}\n    envio: false\n  tasks:\n    - name: Escribir el recibo\n      ansible.builtin.template:\n        src: recibo.txt.j2\n        dest: /tmp/iac-recibo.txt\n        mode: "0644"\n      notify: Avisar a caja\n    - name: Poner un sello\n      ansible.builtin.copy:\n        content: "sello\\n"\n        dest: /tmp/iac-sello.txt\n        mode: "0644"\n      notify: Avisar a caja\n  handlers:\n    - name: Avisar a caja\n      ansible.builtin.debug:\n        msg: caja avisada\n' > site.yml

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Haz una ejecución en seco

Comando
ansible-playbook -i localhost, -c local site.yml --check --diff | grep -E "^\+[A-Za-z]"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un handler corre una sola vez, al final

Un handler no corre cuando se le avisa, sino al final del play, una sola vez aunque varias tareas hayan avisado. Y solo corre si alguna de ellas cambió algo.

Si una tarea necesita antes el trabajo del handler, la tarea especial meta: flush_handlers lo ejecuta en ese punto. Las órdenes siguientes ejecutan el playbook y cuentan.

Ejecuta el playbook por primera vez

Comando
ansible-playbook -i localhost, -c local site.yml | grep -E "RUNNING HANDLER|changed="

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lee el recibo que escribió

Comando
cat /tmp/iac-recibo.txt

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecútalo otra vez

Comando
ansible-playbook -i localhost, -c local site.yml | grep -E "RUNNING HANDLER|changed="

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un error frecuente

Advertencia

Mucha gente cree que un handler corre cada vez que una tarea le avisa. No es así. Corre una vez al final, y solo si algo cambió. Si ejecutas el playbook por segunda vez y nada cambia, el handler no corre ninguna vez.

Cambia una variable desde la orden

Comando
ansible-playbook -i localhost, -c local site.yml -e envio=true | grep -E "RUNNING HANDLER|changed="

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejemplo: tres ejecuciones y sus handlers

EjecuciónTareas que cambianVeces que corre el handler
La primeraLas dos: el recibo y el sello1
La segunda, igualNinguna0
Con -e envio=trueUna: el recibo, con la línea nueva1

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Para ir más lejos

Cambia en site.yml la línea envio: false por envio: true y ejecuta el playbook. Antes de pulsar, di cuántos handlers correrán.

Después añade una tercera tarea que avise al mismo handler y comprueba que sigue corriendo una sola vez.

Sobre este laboratorio y su código: Laboratorio de roles de Ansible: un rol, handlers y Vault en una VM Ubuntu

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.