¿Cuál es la diferencia entre include_tasks e import_tasks?

63

En Ansible 2.4, el includemódulo está en desuso. En su lugar, se envía con dos módulos de reemplazo, import_tasksy include_tasks. Pero tienen descripciones muy similares:

  • include_tasks: Incluye un archivo con una lista de tareas que se ejecutarán en el libro de jugadas actual.
  • import_tasks: Importa una lista de tareas que se agregarán al libro de jugadas actual para su posterior ejecución.

¿Cuándo debo usar el primero y cuándo debo usar el último?

Ben S
fuente
(También: la advertencia de desaprobación se refiere a tareas "dinámicas" y "estáticas". Leí los documentos pero no los entendí.)
Ben S

Respuestas:

70

Hay bastante sobre este tema en la documentación:

La principal diferencia es:

Todas las import*declaraciones se procesan previamente en el momento en que se analizan los libros de jugadas.
Todas las include*declaraciones se procesan tal como se encontraron durante la ejecución del libro de jugadas.

Entonces importes estático, includees dinámico.

Desde mi experiencia, deberías usar importcuando tratas con "unidades" lógicas. Por ejemplo, separe una larga lista de tareas en archivos de subtareas:

main.yml:

- import_tasks: prepare_filesystem.yml
- import_tasks: install_prerequisites.yml
- import_tasks: install_application.yml

Pero lo usaría includepara lidiar con diferentes flujos de trabajo y tomar decisiones basadas en algunos datos recopilados dinámicamente:

prerrequisitos de instalación:

- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
Konstantin Suvorov
fuente
8
Encontré este enlace muy útil: docs.ansible.com/ansible/latest/… Llama a un caso en el que la importación y la inclusión se comportan de manera diferente: un 'cuando' condicional donde las tareas en el archivo pueden cambiar los criterios utilizados para determinar la importación . Con import_tasks, cada tarea verifica los criterios, por lo que el comportamiento cambia cuando los criterios cambian. Con include_tasks, las tareas están presentes o no en función de si la condición se evaluó como verdadera cuando se ejecutó la instrucción include_tasks. Si entiendo bien ...
Ethel Evans
¿Cuál fue el comportamiento de include? Si estuviéramos usando includesería import_tasksel equivalente?
Andy Shinn el
includetenido static: yes(se comportó como import_tasks) y static: no(como include_tasks).
Konstantin Suvorov
¿Para qué es el valor predeterminado static?
Andy Shinn
statices Nonepor defecto: desde Ansible 2.0, las tareas incluidas son dinámicas y se comportan más como tareas reales. Esto significa que se pueden enlazar, omitir y usar variables de cualquier fuente. Ansible intenta detectarlo automáticamente, pero puede usar la directiva estática (que se agregó en Ansible 2.1) para evitar la detección automática.
Konstantin Suvorov
17

Las importaciones son estáticas, las inclusiones son dinámicas. Las importaciones se realizan en el momento del análisis, incluso en tiempo de ejecución.

Las importaciones básicamente reemplazan la tarea con las tareas del archivo. No hay import_tasken tiempo de ejecución. Por lo tanto, los atributos como tagsy when(y muy probablemente otros atributos) se copian en cada tarea importada.

includes de hecho son ejecutados. tagsy whende una tarea incluida se aplica solo a la tarea misma.

Las tareas etiquetadas de un archivo importado se ejecutan si la importtarea no está etiquetada. No se ejecuta ninguna tarea desde un archivo incluido si la includetarea no está etiquetada.

Todas las tareas de un archivo importado se ejecutan si la importtarea está etiquetada. Solo las tareas etiquetadas de un archivo incluido se ejecutan si la includetarea está etiquetada.

Limitaciones de imports:

  • no se puede usar con with_*o loopatributos
  • no se puede importar un archivo, cuyo nombre depende de una variable

Limitaciones de includes:

  • --list-tags no muestra etiquetas de archivos incluidos
  • --list-tasks no muestra tareas de archivos incluidos
  • no puede usar notifypara activar un nombre de controlador que proviene de una inclusión dinámica
  • no puede usar --start-at-taskpara comenzar la ejecución de una tarea dentro de una inclusión dinámica

Más sobre esto aquí y aquí .

Para mí, eso básicamente se reduce al hecho de que imports no se puede usar con atributos de bucle.

importciertamente fallaría en casos como este :

# playbook.yml
- import_tasks: set-x.yml
  when: x is not defined

# set-x.yml
- set_fact
  x: foo
- debug:
  var: x

debugno se ejecuta, ya que hereda whende la import_taskstarea. Por lo tanto, no importa archivos de tareas que cambien las variables utilizadas en importel whenatributo de.

Tenía una política para comenzar con imports, pero una vez que lo necesito, includeasegúrese de que el archivo incluido o los archivos que incluye no importen nada. Pero eso es muy difícil de mantener. Y todavía no está claro si me protegerá de los problemas. Es decir, mezclar includesys importque no recomiendan.

No puedo usar solo imports, ya que ocasionalmente necesito realizar includetareas en bucle . Probablemente podría cambiar a solo includes. Pero decidí cambiar a importaciones en todas partes, excepto en los casos en que se supone que la tarea se ejecuta varias veces. Decidí experimentar todos esos casos difíciles de primera mano. Quizás no haya ninguno en mis libros de jugadas. O con suerte encontraré una manera de hacerlo funcionar.

UPD Un truco posiblemente útil para crear un archivo de tarea que puede importarse muchas veces, pero ejecutarse una vez :

- name: ...
  ...
  when: not _file_executed | default(False)

- name: ...
  ...
  when: not _file_executed | default(False)

...

- name: Set _file_executed
  set_fact:
    _file_executed: True

UPD Uno de los efectos no esperados de mezclar incluye e importar es que incluir vars anula los de importación:

playbook.yml:

- hosts: all
  tasks:
    - import_tasks: 2.yml
      vars:
        v1: 1
    - include_tasks: 2.yml
      vars:
        v1: 1

2.yml:

- import_tasks: 3.yml
  vars:
    v1: 2

3.yml:

- debug:
    var: v1    # 2 then 1

Probablemente, porque include_tasksprimero realiza todas las importaciones estáticas adicionales, y luego cambia las variables pasadas a través de su varsdirectiva.

En realidad, sucede no solo con las importaciones:

playbook.yml:

- hosts: all
  tasks:
    - import_tasks: 2.yml
      vars:
        v1: 1
    - include_tasks: 2.yml
      vars:
        v1: 1

2.yml:

- debug:
    var: v1    # 2 then 1
  vars:
    v1: 2

UPD Otro caso de mezcla incluye e importaciones.

playbook.yml:

- hosts: all
  tasks:
    # here you're bound to use include, some sort of loop
    - include_tasks: 2.yml
      vars:
        https: yes

2.yml:

- import_tasks: 3.yml
  when: https

3.yml:

- import_tasks: 4.yml
  vars:
    https: no  # here we're trying to temporarily override https var
- import_tasks: 4.yml

4.yml:

- debug:
    var: https

Obtenemos truey true, vemos el caso anterior (incluir los vars tienen prioridad sobre los vars de importación). Entonces cambiamos a incluye en 3.yml. Pero luego 3.ymlse omite la primera inclusión en . Dado que hereda when: httpsde la tarea principal, y esta última supuestamente toma httpsde la tarea de la tarea vars. La solución es cambiar a incluye 2.ymltambién. Eso evita la propagación de when: httpslas tareas secundarias.

x-yuri
fuente
44
¡Gran respuesta!. Estaba frustrado con todos en Internet simplemente repitiendo lo que dice la documentación. Gracias.
Sergio Acosta