Ansible ofrece el loop
, with_
, y until
palabras clave para ejecutar una tarea varias veces. Los ejemplos de bucles de uso común incluyen el cambio de propiedad en varios archivos y / o directorios con la módulo de archivo, creando múltiples usuarios con el módulo de usuarioy repetir un paso de sondeo hasta que se alcance un resultado determinado.
Nota
- Agregamos
loop
en Ansible 2.5. Todavía no es un reemplazo completo parawith_
, pero lo recomendamos para la mayoría de los casos de uso. - No hemos desaprobado el uso de
with_
– esa sintaxis seguirá siendo válida en el futuro previsible. - Buscamos mejorar
loop
sintaxis: vea esta página y la registro de cambios para actualizaciones.
- Comparando
loop
ywith_*
-
Bucles estándar
- Iterando sobre una lista simple
- Iterando sobre una lista de hashes
- Iterando sobre un diccionario
- Registrar variables con un bucle
-
Bucles complejos
- Iterando sobre listas anidadas
- Reintentar una tarea hasta que se cumpla una condición
- Bucle sobre el inventario
- Asegurar la entrada de la lista para
loop
: utilizandoquery
en vez delookup
-
Agregar controles a los bucles
- Limitar la salida de bucle con
label
- Pausando dentro de un bucle
- Seguimiento del progreso a través de un bucle con
index_var
- Definición de nombres de variables internas y externas con
loop_var
- Variables de bucle extendido
- Accediendo al nombre de su loop_var
- Limitar la salida de bucle con
-
Migrando de with_X a loop
- with_list
- with_items
- with_indexed_items
- with_flattened
- con nosotros
- with_dict
- with_sequence
- with_subelements
- with_nested / with_cartesian
- with_random_choice
Comparando loop
y with_*
- los
with_
las palabras clave se basan en Complementos de búsqueda – inclusoitems
es una búsqueda. - los
loop
palabra clave es equivalente awith_list
, y es la mejor opción para bucles simples. - los
loop
palabra clave no aceptará una cadena como entrada, consulte Asegurando la entrada de la lista para el bucle: usando una consulta en lugar de una búsqueda. - En general, cualquier uso de
with_*
cubierto de Migrando de with_X a loop se puede actualizar para usarloop
. - Tenga cuidado al cambiar
with_items
paraloop
, comowith_items
realizó un aplanamiento implícito de un solo nivel. Puede que necesite utilizarflatten(1)
conloop
para que coincida con el resultado exacto. Por ejemplo, para obtener el mismo resultado que:
with_items:-1-[2,3]-4
necesitarías:
loop:" flatten(1) "
- Alguna
with_*
declaración que requiere el usolookup
dentro de un bucle no debe convertirse para usar elloop
palabra clave. Por ejemplo, en lugar de hacer:
loop:" lookup('fileglob', '*.txt', wantlist=True) "
es más limpio de mantener:
with_fileglob:'*.txt'
Bucles estándar
Iterando sobre una lista simple
Las tareas repetidas se pueden escribir como bucles estándar sobre una lista simple de cadenas. Puede definir la lista directamente en la tarea:
-name: Add several users ansible.builtin.user:name:" item "state: present groups:"wheel"loop:- testuser1 - testuser2
Puede definir la lista en un archivo de variables, o en la sección ‘vars’ de su juego, luego consulte el nombre de la lista en la tarea:
loop:" somelist "
Cualquiera de estos ejemplos sería equivalente a:
-name: Add user testuser1 ansible.builtin.user:name:"testuser1"state: present groups:"wheel"-name: Add user testuser2 ansible.builtin.user:name:"testuser2"state: present groups:"wheel"
Puede pasar una lista directamente a un parámetro para algunos complementos. La mayoría de los módulos de embalaje, como mmm y apto, tiene esta capacidad. Cuando esté disponible, pasar la lista a un parámetro es mejor que recorrer la tarea. Por ejemplo:
-name: Optimal yum ansible.builtin.yum:name:" list_of_packages "state: present -name: Non-optimal yum, slower and may cause issues with interdependencies ansible.builtin.yum:name:" item "state: present loop:" list_of_packages "
Comprobar el documentación del módulo para ver si puede pasar una lista a los parámetros de algún módulo en particular.
Iterando sobre una lista de hashes
Si tiene una lista de hashes, puede hacer referencia a subclaves en un bucle. Por ejemplo:
-name: Add several users ansible.builtin.user:name:" item.name "state: present groups:" item.groups "loop:-name:'testuser1',groups:'wheel'-name:'testuser2',groups:'root'
Al combinar condicionales con un bucle, el when:
El estado de cuenta se procesa por separado para cada artículo. Ver Condicionales básicos con cuando por ejemplo.
Iterando sobre un diccionario
Para recorrer un dictado, use el dict2items:
-name: Using dict2items ansible.builtin.debug:msg:" item.key - item.value "loop:" dict2items "vars:tag_data:Environment: dev Application: payment
Aquí, estamos iterando sobre tag_data
e imprimiendo la clave y el valor de la misma.
Registrar variables con un bucle
Puede registrar la salida de un bucle como una variable. Por ejemplo:
-name: Register loop output as a variable ansible.builtin.shell:"echo item "loop:-"one"-"two"register: echo
Cuando usas register
con un bucle, la estructura de datos colocada en la variable contendrá un results
atributo que es una lista de todas las respuestas del módulo. Esto difiere de la estructura de datos devuelta al usar register
sin un bucle:
"changed":true,"msg":"All items completed","results":["changed":true,"cmd":"echo "one" ","delta":"0:00:00.003110","end":"2013-12-19 12:00:05.187153","invocation":"module_args":"echo "one"","module_name":"shell","item":"one","rc":0,"start":"2013-12-19 12:00:05.184043","stderr":"","stdout":"one","changed":true,"cmd":"echo "two" ","delta":"0:00:00.002920","end":"2013-12-19 12:00:05.245502","invocation":"module_args":"echo "two"","module_name":"shell","item":"two","rc":0,"start":"2013-12-19 12:00:05.242582","stderr":"","stdout":"two"]
Los ciclos posteriores sobre la variable registrada para inspeccionar los resultados pueden verse así:
-name: Fail if return code is not 0 ansible.builtin.fail:msg:"The command ( item.cmd ) did not have a 0 return code"when: item.rc != 0 loop:" echo.results "
Durante la iteración, el resultado del elemento actual se colocará en la variable:
-name: Place the result of the current item in the variable ansible.builtin.shell: echo " item " loop:- one - two register: echo changed_when: echo.stdout != "one"
Bucles complejos
Iterando sobre listas anidadas
Puede utilizar expresiones Jinja2 para iterar sobre listas complejas. Por ejemplo, un bucle puede combinar listas anidadas:
-name: Give users access to multiple databases community.mysql.mysql_user:name:" item[0] "priv:" item[1] .*:ALL"append_privs: yes password:"foo"loop:"product(['clientdb', 'employeedb', 'providerdb'])"
Reintentar una tarea hasta que se cumpla una condición
Nuevo en la versión 1.4.
Puedes usar el until
palabra clave para reintentar una tarea hasta que se cumpla una determinada condición. He aquí un ejemplo:
-name: Retry a task until a certain condition is met ansible.builtin.shell: /usr/bin/foo register: result until: result.stdout.find("all systems go") !=-1retries:5delay:10
Esta tarea se ejecuta hasta 5 veces con un retraso de 10 segundos entre cada intento. Si el resultado de cualquier intento tiene “todos los sistemas funcionan” en su salida estándar, la tarea se realiza correctamente. El valor predeterminado para “reintentos” es 3 y “retraso” es 5.
Para ver los resultados de los reintentos individuales, ejecute la obra con -vv
.
Cuando ejecuta una tarea con until
y registrar el resultado como una variable, la variable registrada incluirá una clave denominada “intentos”, que registra el número de reintentos de la tarea.
Nota
Debes configurar el until
parámetro si desea reintentar una tarea. Si until
no está definido, el valor de la retries
el parámetro se fuerza a 1.
Bucle sobre el inventario
Para recorrer su inventario, o solo un subconjunto de él, puede usar un loop
con el ansible_play_batch
o groups
variables:
-name: Show all the hosts in the inventory ansible.builtin.debug:msg:" item "loop:" groups['all'] "-name: Show all the hosts in the current play ansible.builtin.debug:msg:" item "loop:" ansible_play_batch "
También hay un complemento de búsqueda específico inventory_hostnames
que se puede usar así:
-name: Show all the hosts in the inventory ansible.builtin.debug:msg:" item "loop:" query('inventory_hostnames', 'all') "-name: Show all the hosts matching the pattern, ie all but the group www ansible.builtin.debug:msg:" item "loop:" query('inventory_hostnames', 'all:!www') "
Puede encontrar más información sobre los patrones en Patrones: dirigidos a hosts y grupos.
Asegurar la entrada de la lista para loop
: utilizando query
en vez de lookup
los loop
la palabra clave requiere una lista como entrada, pero la lookup
palabra clave devuelve una cadena de valores separados por comas de forma predeterminada. Ansible 2.5 introdujo una nueva función Jinja2 llamada consulta que siempre devuelve una lista, ofreciendo una interfaz más simple y una salida más predecible de los complementos de búsqueda cuando se usa el loop
palabra clave.
Puedes forzar lookup
para devolver una lista a loop
mediante el uso wantlist=True
, o puedes usar query
en lugar de.
Estos ejemplos hacen lo mismo:
loop:" query('inventory_hostnames', 'all') "loop:" lookup('inventory_hostnames', 'all', wantlist=True) "
Agregar controles a los bucles
Nuevo en la versión 2.1.
los loop_control
La palabra clave le permite administrar sus bucles de manera útil.
Limitar la salida del lazo con label
Nuevo en la versión 2.2.
Cuando recorre estructuras de datos complejas, la salida de la consola de su tarea puede ser enorme. Para limitar la salida mostrada, use el label
directiva con loop_control
:
-name: Create servers digital_ocean:name:" item.name "state: present loop:-name: server1 disks: 3gb ram: 15Gb network:nic01: 100Gb nic02: 10Gb ...loop_control:label:" item.name "
El resultado de esta tarea mostrará solo el name
campo para cada item
en lugar de todo el contenido de la multilínea item
variable.
Nota
Esto es para hacer que la salida de la consola sea más legible, no para proteger los datos confidenciales. Si hay datos sensibles en loop
, colocar no_log: yes
en la tarea de prevenir la divulgación.
Pausando dentro de un bucle
Nuevo en la versión 2.2.
Para controlar el tiempo (en segundos) entre la ejecución de cada elemento en un ciclo de tareas, utilice el pause
directiva con loop_control
:
# main.yml-name: Create servers, pause 3s before creating next community.digitalocean.digital_ocean:name:" item "state: present loop:- server1 - server2 loop_control:pause:3
Seguimiento del progreso a través de un bucle con index_var
Nuevo en la versión 2.5.
Para realizar un seguimiento de dónde se encuentra en un bucle, utilice el index_var
directiva con loop_control
. Esta directiva especifica un nombre de variable para contener el índice de bucle actual:
-name: Count our fruit ansible.builtin.debug:msg:" item with index my_idx "loop:- apple - banana - pear loop_control:index_var: my_idx
Nota
index_var
está indexado en 0.
Definición de nombres de variables internas y externas con loop_var
Nuevo en la versión 2.1.
Puede anidar dos tareas de bucle utilizando include_tasks
. Sin embargo, por defecto Ansible establece la variable de bucle item
para cada bucle. Esto significa que el bucle anidado interno sobrescribirá el valor de item
desde el bucle exterior. Puede especificar el nombre de la variable para cada bucle usando loop_var
con loop_control
:
# main.yml-include_tasks: inner.yml loop:-1-2-3loop_control:loop_var: outer_item # inner.yml-name: Print outer and inner items ansible.builtin.debug:msg:"outer item= outer_item inner item= item "loop:- a - b - c
Nota
Si Ansible detecta que el ciclo actual está usando una variable que ya ha sido definida, generará un error para fallar la tarea.
Variables de bucle extendido
Nuevo en la versión 2.8.
A partir de Ansible 2.8, puede obtener información de bucle extendido utilizando el extended
opción de control de bucle. Esta opción expondrá la siguiente información.
Variable |
Descripción |
|
La lista de todos los elementos del bucle. |
|
La iteración actual del bucle. (1 indexado) |
|
La iteración actual del bucle. (0 indexados) |
|
El número de iteraciones desde el final del ciclo (1 indexado) |
|
El número de iteraciones desde el final del ciclo (0 indexado) |
|
|
|
|
|
La cantidad de elementos en el bucle |
|
El elemento de la iteración anterior del ciclo. Indefinido durante la primera iteración. |
|
El elemento de la siguiente iteración del bucle. Indefinido durante la última iteración. |
loop_control:extended: yes
Accediendo al nombre de su loop_var
Nuevo en la versión 2.8.
A partir de Ansible 2.8, puede obtener el nombre del valor proporcionado a loop_control.loop_var
utilizando el ansible_loop_var
variable
Para los autores de roles, escribir roles que permitan bucles, en lugar de dictar los loop_var
value, puede recopilar el valor a través de:
" lookup('vars', ansible_loop_var) "
Migrando de with_X a loop
En la mayoría de los casos, los bucles funcionan mejor con loop
palabra clave en lugar de with_X
bucles de estilo. los loop
La sintaxis generalmente se expresa mejor usando filtros en lugar de un uso más complejo de query
o lookup
.
Estos ejemplos muestran cómo convertir muchos with_
bucles de estilo para loop
y filtros.
with_list
with_list
es reemplazado directamente por loop
.
-name: with_list ansible.builtin.debug:msg:" item "with_list:- one - two -name: with_list -> loop ansible.builtin.debug:msg:" item "loop:- one - two
with_items
with_items
es reemplazado por loop
y el flatten
filtrar.
-name: with_items ansible.builtin.debug:msg:" item "with_items:" items "-name: with_items -> loop ansible.builtin.debug:msg:" item "loop:"flatten(levels=1) "
with_indexed_items
with_indexed_items
es reemplazado por loop
, los flatten
filtrar y loop_control.index_var
.
-name: with_indexed_items ansible.builtin.debug:msg:" item.0 - item.1 "with_indexed_items:" items "-name: with_indexed_items -> loop ansible.builtin.debug:msg:" index - item "loop:"flatten(levels=1) "loop_control:index_var: index
with_flattened
with_flattened
es reemplazado por loop
y el flatten
filtrar.
-name: with_flattened ansible.builtin.debug:msg:" item "with_flattened:" items "-name: with_flattened -> loop ansible.builtin.debug:msg:" item "loop:"flatten "
con nosotros
with_together
es reemplazado por loop
y el zip
filtrar.
-name: with_together ansible.builtin.debug:msg:" item.0 - item.1 "with_together:-" list_one "-" list_two "-name: with_together -> loop ansible.builtin.debug:msg:" item.0 - item.1 "loop:" list_one"
Otro ejemplo con datos complejos
- name: with_together -> loop ansible.builtin.debug: msg: " item.0 - item.1 - item.2 " loop: "list " vars: data: - ['a', 'b', 'c'] - ['d', 'e', 'f'] - ['g', 'h', 'i']
with_dict
with_dict
puede ser sustituido por loop
y ya sea el dictsort
o dict2items
filtros.
- name: with_dict ansible.builtin.debug: msg: " item.key - item.value " with_dict: " dictionary " - name: with_dict -> loop (option 1) ansible.builtin.debug: msg: " item.key - item.value " loop: "dict2items " - name: with_dict -> loop (option 2) ansible.builtin.debug: msg: " item.0 - item.1 " loop: " dictionary"
with_sequence
with_sequence
es reemplazado por loop
y el range
función, y potencialmente el format
filtrar.
- name: with_sequence ansible.builtin.debug: msg: " item " with_sequence: start=0 end=4 stride=2 format=testuser%02x - name: with_sequence -> loop ansible.builtin.debug: msg: " 'testuser%02x' " # range is exclusive of the end point loop: "list "
with_subelements
with_subelements
es reemplazado por loop
y el subelements
filtrar.
- name: with_subelements ansible.builtin.debug: msg: " item.0.name - item.1 " with_subelements: - " users " - mysql.hosts - name: with_subelements -> loop ansible.builtin.debug: msg: " item.0.name - item.1 " loop: "subelements('mysql.hosts') "
with_nested / with_cartesian
with_nested
y with_cartesian
son reemplazados por bucle y el product
filtrar.
- name: with_nested ansible.builtin.debug: msg: " item.0 - item.1 " with_nested: - " list_one " - " list_two " - name: with_nested -> loop ansible.builtin.debug: msg: " item.0 - item.1 " loop: " list_one"
with_random_choice
with_random_choice
se reemplaza por el solo uso de la random
filtro, sin necesidad de loop
.
- name: with_random_choice ansible.builtin.debug: msg: " item " with_random_choice: " my_list " - name: with_random_choice -> loop (No loop is needed here) ansible.builtin.debug: msg: "random " tags: random
Ver también
- Introducción a los libros de jugadas
-
Introducción a los libros de jugadas
- Roles
-
Organización del libro de jugadas por roles
- Consejos y trucos
-
Consejos y trucos para libros de jugadas
- Condicionales
-
Declaraciones condicionales en los libros de jugadas
- Usando Variables
-
Todo sobre variables
- Lista de correo de usuarios
-
¿Tengo una pregunta? ¡Pasa por el grupo de google!
- irc.freenode.net
-
#ansible canal de chat de IRC
valoraciones y reseñas
Si estás contento con lo expuesto, tienes la opción de dejar un enunciado acerca de qué le añadirías a esta reseña.