Ansible: Característica: permitir bucles hasta en bloques o incluye

Creado en 27 sept. 2018  ·  29Comentarios  ·  Fuente: ansible/ansible

RESUMEN

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.

TIPO DE PROBLEMA
  • Idea característica
NOMBRE DEL COMPONENTE

Centro

affects_2.8 feature has_pr core

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.

Todos 29 comentarios

@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?

+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.

¿Fue útil esta página
0 / 5 - 0 calificaciones