Cómo trabajar con diccionarios key value jinja2

Todo lo que necesitas saber de iteraciones en Ansible,YAML y Jinja2 (loops)

Hace ya bastante empecé a trastear con Ansible. Esto marcó un antes y un después en mi forma de hacer instalaciones de equipos y también puestas en producción y pruebas de servidores y contenedores.  Algunas cosas son confusas, y por eso te quiero enseñar cómo hacer iteraciones en jinja2 y cómo puedes usarlas en Ansible con YAML.

Lo primero, es avisarte de que estas tres cosas son independientes, por si has llegado aquí buscando información solo de jinja2 e iteraciones en diccionarios (objetos key:value) que sepas que también te vale.

Cómo funcionan los loops en jinja2

Solo hay dos tipos de loops, los que se hacen sobre un array [uno, dos, tres], y los que se hacen sobre un objeto {clave1: valor1, clave2: valor2, clave3: valor3}.

Si tu lenguaje de programación principal es Php y no sueles tocar otros, a diferencia de Php, en los demás lenguajes los arrays no tienen keys, es decir, solo se identifican por la posición en el array, de 0 a x.

Una vez dicho esto podemos ponernos manos a la obra para escribir cómo representar dos loops.

Cómo iterar en un array en jinja2

Si lo estás poniendo en un archivo YAML, un array se representa dentro de una clave por líneas indentadas precedidas por un guión:

- hosts:
    - 192.168.0.1
    - 192.168.0.2
    - 192.168.0.3
    - 192.168.0.4

Como ves, la variable hosts tiene dentro una lista que contiene lo que sería un array sin claves.

Para poder representar esta lista, digamos que en un archivo de texto plano y un host por línea, sería algo similar a esto:

{% for host in hosts %}
{{host}}
{% endfor %}

Esto devolvería un archivo de texto plano con este contenido:

Léete también  Los 30 añs de Dragon Ball, Raspberry Pi 3 y Humm, el Spotify gratis español. No te pierdas lo mejor de la semana.

192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4

Cómo iterar en un objeto key:value en jinja2

¿Sencillo verdad? Pero qué pasa si quieres utilizar una lista en la que usar un nombre para cada línea y también el valor de dicha línea para hacer una lista, por ejemplo:

- cards:
    - nombre: eth0 
      address: 192.168.0.10
      netmask: 255.255.255.0
      gateway: 192.168.0.1
      broadcast: 192.168.0.255
    - nombre: eth1
      address: 10.0.0.10
      netmask: 255.255.255.0
      gateway: 10.0.0.1
      broadcast: 10.0.0.255

Esto se llaman diccionarios, y en este otro caso, tienes un host, y quieres utilizar cada uno de los datos que hay dentro de este para crear un archivo de configuración, por ejemplo para interfaces si quieres tener varias conexiones de red en varias tarjetas:

{% for card in cards %}
{% for key, value in card.iteritems() %}
{% if key is sameas nombre %}
auto {{nombre}}
iface {{nombre}} inet static
{% else %}
{{key}} {{value}}
{% endif %}
{% endfor %}

{% endfor %}

Aquí lo primero va a ser hacer loop en cards para sacar cada una por separado. Luego accedes al diccionario for para asignar la clave y el valor a las variables key, value, y avisar de que es un objeto poniendo tras la variable .iteritems(). Esto lo que hará es que trate el array como un objeto, y devuelva la clave en la variable key, y el valor en la de valor.

Una vez dentro del for, ya puedes simplemente seguir con el script que necesites, con las condiciones que se tercien.

Por ejemplo, en este le hemos dicho, que si la clave es “nombre”, va a pintar la configuración de la tarjeta de red, pero la parte del tipo de tarjeta y cómo ponerla en marcha. Y en el resto de casos (en el else), lo que haremos será simplemente pintar la clave y el valor separados por tabuladores y con un tabulador al principio.

Léete también  Cómo bloquear el fondo de pantalla en Windows 10

Te has fijado en el intro antes del endfor ¿verdad? esto es porque jinja2 es muy estricto, y en este caso, para que quede separado cada bloque queremos un intro extra, de esta forma quedaría así:

auto eth0
iface eth0 inet static
	address 192.168.0.10
	netmask 255.255.255.0
	gateway 192.168.0.1
	broadcast 192.168.0.255

auto eth1
iface eth1 inet static
	address 10.0.0.10
	netmask 255.255.255.0
	gateway 10.0.0.1
	broadcast 10.0.0.255

¿Sencillo verdad? Con este método para acceder a “objetos” o diccionarios en jinja2, puedes crear unas plantillas de configuración para Ansible mucho más lógicas y ordenadas, además de poder reducir repeticiones y demás según lo complejo que necesites tu script.

Si te has liado o tienes problemas puedes dejarme un mensaje abajo y te echo un cable. Y si tienes algún consejo no te lo pienses y ponlo también.

En mi caso lo uso para configuraciones de redes locales con Haproxy, ¿y en el tuyo? Comenta y comparte


AYUDANOS a poder seguir dando respuestas. Te podemos echar una mano y tú también a nosotros, símplemente dale a me gusta.