Blog

Ansible filters

No es ningún secreto que en nuestro día a día trabajamos con Ansible e intentamos automatizar el 100% de todos los sistemas. Dentro de nuestra metodología, en muchas ocasiones, utilizamos listas para invocar reiteradamente una tarea, un role, etc.

Esto nos permite normalizar bastante las automatizaciones e iterar en listas en casos como:

  • Configuración de múltiples virtualhosts, donde la tarea/rol requiere ser instanciado una vez por cada virtualhost.
  • Configuración de definiciones en kubernetes como deployments, ingress, etc., invocando 'N' veces para desplegar la definición de ficheros YAML.
  • Configuración de distintas versiones de php, donde se invoca una tarea para instalar cada versión de php y configurar los php.ini pertinentes.

Es una gran ventaja a muchos niveles:

  • Legibilidad.
  • Mantenimiento de código.
  • Reutilización de código.

Ahora bien, en otras ocasiones, si estas listas tienen muchos elementos, las ejecuciones de tareas/roles pueden ser largas (dependiendo de lo que hagan) prolongando mucho la ejecución de Ansible, o bien, puede darse el caso de no querer desplegar todas las configuraciones por algún motivo.

Para ello, hacemos uso del método "search" de Ansible y los condicionales "when".

Método "search" de Ansible y los condicionales "when"

El método search(), devuelve un boolean si encuentra la expresión regular el string facilitado. Y when... ya sabemos para qué lo utilizamos.

La forma de usar "search()" es => var_1 is search("exp"). Será true si el valor de la variable var_1 hace match con la expresión regular "exp".

Si sacamos el valor "exp" a una variable filter_example, quedaría de la siguiente forma:

---
filter_example: "exp"
---
var_1 is search(filter_example)

 

Como hemos dicho, search() busca expresiones regulares, por lo que usando ".*" como valor de filter_example, lo ejecutaríamos siempre.

Finalmente, si esto lo metemos en un condicional "when", tendríamos una ejecución de una tarea, siempre que la función search() encuentre la expresión regular:

---
- name: "Iterate over list"
  debug: msg="Domain= {{ obj.domain }} --  Port= {{ obj.port }}"
  loop: "{{ vhost_list | default([]) }}"
  loop_control:
    loop_var: obj
  when:
    - obj.domain is search(filter_test_domain)
    - obj.port is search(filter_test_port)
---

 

En la tarea arriba reflejada, apreciamos:

  • Invocación de la tarea con "lopp", la cual itera sobre los elementos de una variable "vhost_list".
  • Uso de loop_control y loop_var para iterar sobre "vhost_list", y se define "obj" como nombre para la variable de cada elemento de la lista.
  • Utilización de when para condicional de ejecución de la tarea. En este caso, 2 condicionales que actúan como "and".
  • Cada condición del "when" evalúa una propiedad del elemento de la lista ("domain" y "port") en busca de las expresiones regulares correspondientes, definidas en las variables "filter_test_domain" y "filter_test_port".

Para continuar, mostraremos la definición de las variables a usar en el ejemplo:

---
filter_test_domain: ".*"
filter_test_port: ".*"

vhost_list:
  - domain: "foo1.strsistemas.com"
    port: "80"
  - domain: "foo2.strsistemas.com"
    port: "443"
  - domain: "foo3.strsistemas.com"
    port: "8080"
---

 

Veamos a continuación lo que hemos ganado con esto.

Si los valores de "filter_test_domain" y "filter_test_port" no se modifican, los filtros search() siempre se cumplirán y se ejecutarán en todos la tarea, iterando sobre todos los elementos de la lista.

Si modificamos el valor (ejemplo):


filter_test_port: "443"

 

Al ejecutar la tarea, el segundo condicional when (obj.port is search(filter_test_port)), se cumplirá unicamente para el elemento con domain="foo2.strsistemas.com" y port=443, por lo que se obviarán los elementos domain "foo1.strsistemas.com" y "foo3.strsistemas.com".

Ahora bien, la guinda la ponemos cuando cambiamos en el momento de la ejecución el valor de dichas variables con el flag "-e" de Ansible:

  • ansible-playbook -i hosts_inventario stack_STR.yml -e filter_test_port="443".
  • ansible-playbook -i hosts_inventario stack_STR.yml -e filter_test_port="^80" -e filter_test_domain=”(.*)strsistemas(.*)

 

Newsletter de STR Sistemas

Suscríbete a nuestra newsletter para recibir contenido interesante del mundo DevOps y artículos escritos por nuestros técnicos

¡Usamos cookies propias y de terceros para mejorar tu experiencia en esta web! Si sigues navegando, consientes y aceptas estas cookies en tu ordenador, móvil o tablet.

Más información sobre las cookies y cómo cambiar su configuración en tu navegador aquí.

x