Sería bastante útil si puede recorrer más de una sola tarea.
Por ejemplo, si tiene que sondear un sistema remoto para ver algún progreso y, al mismo tiempo, desea enviar este progreso a otro backend, podría estar haciendo lo siguiente:
- hosts: localhost
tasks:
- name: Start a long-running task
uri:
url: https://some-service/v1/put/new_job
body: { foo: bar }
register: new_job
- until: job_status.json.message in ['Finished', 'Failed']
block:
- name: Get job status
uri:
url: https://some-service/v1/get/new_job
register: job_status
- name: Report job status to web service
uri:
url: https://backend-system/v1/post/job_status
body: '{{ job_status.json }}'
Hay muchos usos para esto.
Centro
@mkrizek Hmm, busqué varias combinaciones de palabras clave, y esa no sobresalió :-(
Dicho esto, intenté usar until:
con block:
, include:
y include_tasks
, pero el primero falla y los otros 2 solo ejecutan el archivo incluido una vez .
- hosts: localhost
tasks:
- include: taskboot.yml
until: 5|random == 5
Pero aparentemente, el bucle solo funciona cuando se usa loop:
?
- hosts: localhost
tasks:
- include: taskboot.yml
loop: [ 1, 2, 3, 4, 5 ]
Intente lo que intente, usar until:
no funciona con include:
y include_tasks:
.
- hosts: localhost
tasks:
- include: taskbook.yml
until: false
retries: 5
delay: 1
Sí, until
no es un argumento válido para include, consulte https://github.com/ansible/ansible/pull/46177.
@mkrizek En otras palabras, lo que necesitamos no es posible, ni en bloques ni en inclusiones.
Así que mantendré este abierto, pero cambié el título.
Tenemos una propuesta abierta para incluir "tareas", lo que permitiría que cosas como hasta funcionen en ellas.
https://github.com/ansible/proposals/issues/136
Sin embargo, no creo que los bloques deban extenderse para admitir esta función.
@sivel ¿Y cuál sería la razón para no extender la funcionalidad a los bloques? Como sería algo natural si funcionara. (es decir, poder hacer un bucle de cada construcción dentro de una obra)
los bloques son actualmente agrupaciones 'estáticas', habilitar bucles en ellos (no solo hacer que las tareas los hereden) requeriría hacerlos dinámicos... como vimos con include:
esto tiene muchas consecuencias que no son evidentes de inmediato.
Para ampliar lo que menciona @bcoca , hacerlo nos obligaría a desaprobar block
y reemplazarlo con algo como block_dynamic
y block_static
.
Además, _todos_ los usuarios de ansible utilizan bloques, ya sean explícitos o nuestro uso interno implícito de ellos. Son un componente fundamental de cómo se representan y ejecutan las tareas. Cambiar una característica tan integral seguramente conducirá a problemas imprevistos.
En cualquier caso, la documentación no da ningún detalle, o incluso no discute lo que se supone que funciona y lo que no. No hay una distinción real entre "bucles" y bucles hasta, no estoy seguro de cómo podemos hacer esto más claro en general. La expectativa es que lo que funciona para "bucles" también funcione para bucles hasta.
Yo haría ambas cosas, permitir que los bucles hasta/reintentar funcionen con inclusiones y luego documentar claramente cómo funcionan... así tenemos algo que señalar cuando no cumple con las expectativas de algunas personas.
Solo para proporcionar una pequeña cantidad de detalles sobre cómo funcionan las inclusiones, es que las inclusiones dinámicas son más un disparador interno, a diferencia de algo que envuelve la ejecución.
Como tal, task_executor hace cortocircuito al principio de una inclusión, lo que indica a la estrategia que debe leer un archivo e insertar bloques de tareas en el TQM, que luego serán procesados por task_executor.
Debido a esto, no hay un seguimiento del estado como un resumen de la inclusión principal. Por lo tanto, un ciclo hasta, que se basaría en alguna versión de un escenario fallido de cuándo/éxito, solo se referiría a si se le indicó o no a la estrategia que hiciera lo detallado anteriormente. En cuyo caso, siempre debería tener éxito.
En cualquier caso, el modo de funcionamiento es que cortocircuitamos mucho antes y hasta que se inspeccionan las condiciones. Si simplemente "lo hiciéramos funcionar" en este momento, definitivamente no haría lo que una persona espera. Para hacer lo que la gente espera, sería necesario implementar ansible/proposals#136.
el hasta en este caso tendría que depender de vars establecidos o registrados de las tareas incluidas, ya que el registro de la inclusión en sí sería inútil ... todavía 'funcionaría' pero no como lo hacen la mayoría de los otros casos.
@dagwieers El otro hilo está bloqueado ahora. Pero esta sugerencia reciente (comentario de @sivel arriba) es completamente nueva:
https://github.com/ansible/ansible/issues/46203#issuecomment-425111123
Y usted está diciendo que tal vez queramos dejar abierta la posibilidad de que alguien más venga más tarde, para hacer una PR para recorrer bloques de sus propias espaldas. Entonces, al menos, podríamos dejarles muy claro, como para hacerlo como un block_dynamic:
separado y nuevo, y no tocar el block:
estático tradicional intacto. ¿No tendría eso más sentido para todos? ¿Podemos todos estar de acuerdo en eso antes de tiempo? Porque estoy de acuerdo con esta idea. Por las mismas razones, ayudará a evitar romper otras cosas existentes en las que confiamos. Mientras aún permite la posibilidad de que alguien venga, intente hacer un PR para implementarlo. ¿Deberíamos realmente querer que hagan el mejor trabajo posible y tal? Entonces deberíamos al menos especificar claramente esto. Si eso ya lo sabemos de antemano. ¿Cuál parece ser el caso ahora?
Vinculando esto aquí https://github.com/ansible/ansible/issues/16621
+1 por implementar esta característica
Es natural que un bloque sea repetible. De lo contrario, es muy contrario a la intuición. Confunde.
Y parece que no hay forma de escribir un libro de jugadas con bucle con más de una declaración. Ningún lenguaje de programación es tan limitado.
Parece que en Ansible, si uno necesita hacer algo complejo, debe escribir un complemento de acción. Esto es lo que vamos a hacer.
Aquí uno tiene muchos ejemplos:
https://github.com/ansible/ansible/tree/devel/lib/ansible/plugins/action
Atentamente
Esto es absolutamente una deficiencia. Ansible ha sido perfecto para la mayoría de mis necesidades hasta ahora, pero parece que expandir las capacidades de los bloques haría que Ansible fuera una solución mucho mejor.
Traté de usar until
en un include_tasks
y no funcionó.
Lo que hice como solución fue crear un archivo yml que incluyera la tarea ( loop.yml
) y se llamara a sí mismo recursivamente ( recursive.yml
) mientras la condición aún no se cumple.
_recursivo.yml:_
---
- name: 'checking {{ watch_job }} status (recursive)'
include_tasks: 'loop.yml'
- name: 'count ({{ watch_count | int + 1 }})'
set_fact:
watch_count: '{{ watch_count | int + 1 }}'
- name: 'retries ({{ (watch_timeout | int / watch_poll | int) | int }})'
set_fact:
watch_retries: '{{ (watch_timeout | int / watch_poll | int) | int }}'
- name: 'timeout ({{ watch_timeout }} seconds)'
fail:
msg: "Timeout of {{ watch_timeout }} seconds exceeded ({{ watch_retries }} retries)"
when: (not watch_status.finished) and (watch_count | int > watch_retries | int)
- name: 'wait for {{ watch_poll }} seconds'
wait_for:
timeout: '{{ watch_poll | int }}'
when: not watch_status.finished
- name: 'call itself recursively'
include_tasks: 'recursive.yml'
when: not watch_status.finished
En el archivo anterior, incluí un tiempo de espera en caso de demorarse demasiado (esto es en un rol que muestra el resultado de lo que se está ejecutando en los hosts ).
No es la solución ideal, pero funcionó para mí y fue relativamente fácil de cambiar usando until
para hacer lo anterior.
¡+1 por esta característica!
+1
+1 para bucles hasta en bloques
He estado buscando una manera de hacer until
(infinitamente) para tener éxito en todos los módulos del bloque y lo logré con include_tasks
con rescue
No pude usar until
regulares porque la IP cambia con el tiempo y tuve que modificarla sobre la marcha
esperar_hasta_el_éxito.yml
- name: 'Wait until success'
block:
- name: Get server updated ip
uri:
url: https://localhost/ip
return_content: yes
status_code: 200
register: ip
- name: ssh to the server
wait_for:
host: "{{ ip }}"
port: 22
timeout: 30
state: started
rescue:
- debug:
msg: "Failed to connect - Retrying..."
- include_tasks: wait_until_success.yml
Igual que @matanbaru con una forma de fallar después de múltiples reintentos
- name: 'Wait until success'
block:
- name: Set the retry count
set_fact:
retry_count: "{{ 0 if retry_count is undefined else retry_count|int + 1 }}"
- name: Get server updated ip
uri:
url: https://localhost/ip
return_content: yes
status_code: 200
register: ip
- name: ssh to the server
wait_for:
host: "{{ ip }}"
port: 22
timeout: 30
state: started
rescue:
- fail:
msg: Ended after 5 retries
when: retry_count|int == 5
- debug:
msg: "Failed to connect - Retrying..."
- include_tasks: wait_until_success.yml
+1, ¿podría agregar reintentar hasta que esté en bucle?
¡Característica absolutamente "imprescindible"!
+1
+1
He bloqueado esto para los contribuyentes por ahora. Agregar +1
comentarios es demasiado ruidoso. Para referencia futura, agregue una reacción al cuerpo del problema y no haga comentarios.
Comentario más útil
Es natural que un bloque sea repetible. De lo contrario, es muy contrario a la intuición. Confunde.
Y parece que no hay forma de escribir un libro de jugadas con bucle con más de una declaración. Ningún lenguaje de programación es tan limitado.