Quelle est la différence entre include_tasks et import_tasks?

63

Dans Ansible 2.4, le includemodule est obsolète. À sa place, il est livré avec deux modules de remplacement, import_taskset include_tasks. Mais ils ont des descriptions très similaires:

  • include_tasks: Inclut un fichier avec une liste de tâches à exécuter dans le playbook actuel.
  • import_tasks: Importe une liste de tâches à ajouter au Playbook actuel pour une exécution ultérieure.

Quand devrais-je utiliser le premier et quand devrais-je utiliser le dernier?

Ben S
la source
(Aussi: l'avertissement de dépréciation fait référence à des tâches "dynamiques" et "statiques". J'ai lu la documentation mais je ne les ai pas comprises.)
Ben S

Réponses:

70

Il y a beaucoup de choses à ce sujet dans la documentation:

La principale différence est:

Toutes les import*déclarations sont pré-traitées au moment où les playbooks sont analysés.
Toutes les include*instructions sont traitées telles qu’elles se sont présentées lors de l’exécution du livre de jeu.

Ainsi importest statique, includeest dynamique.

D'après mon expérience, vous devriez utiliser importlorsque vous traitez avec des "unités" logiques. Par exemple, séparez une longue liste de tâches dans des fichiers de sous-tâche:

main.yml:

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

Mais vous utiliseriez includepour traiter différents flux de travail et prendre des décisions en fonction de faits rassemblés de manière dynamique:

les conditions d'installation:

- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
Konstantin Suvorov
la source
8
J'ai trouvé ce lien très utile: docs.ansible.com/ansible/latest/… Il appelle un cas où l'importation et l'inclusion se comportent différemment - un "quand" conditionnel dans lequel les tâches du fichier peuvent modifier les critères utilisés pour déterminer l'importation . Avec import_tasks, chaque tâche vérifie les critères, de sorte que le comportement change lorsque les critères changent. Avec include_tasks, les tâches sont présentes ou non, que la condition soit considérée comme vraie ou non lors de l'exécution de l'instruction include_tasks. Si je comprends bien ...
Ethel Evans
Quel était le comportement de include? Si nous utilisions includeserait import_tasksl'équivalent?
Andy Shinn
includeavait static: yes(s'est comporté comme import_tasks) et static: no(comme include_tasks).
Konstantin Suvorov
Quelle est la valeur par défaut pour static?
Andy Shinn
staticest Nonepar défaut: depuis Ansible 2.0, les tâches à inclure sont dynamiques et se comportent plutôt comme des tâches réelles. Cela signifie qu'ils peuvent être mis en boucle, ignorés et utiliser des variables de n'importe quelle source. Ansible essaie de le détecter automatiquement, mais vous pouvez utiliser la directive static (ajoutée dans Ansible 2.1) pour contourner la détection automatique.
Konstantin Suvorov
17

Les importations sont statiques, les inclus sont dynamiques. Les importations ont lieu au moment de l'analyse, y compris au moment de l'exécution.

Les importations remplacent essentiellement la tâche par les tâches du fichier. Il n'y a pas import_taskau moment de l'exécution. Ainsi, des attributs tels que tags, et when(et très probablement d’autres attributs) sont copiés dans chaque tâche importée.

includes sont bien exécutés. tagset whend’une tâche incluse s’appliquent uniquement à la tâche elle-même.

Les tâches importétiquetées à partir d'un fichier importé sont exécutées si la tâche est non étiquetée. Aucune tâche n'est exécutée à partir d'un fichier inclus si la includetâche n'est pas marquée.

Toutes les tâches d'un fichier importé sont exécutées si la importtâche est étiquetée. Seules les tâches balisées d'un fichier inclus sont exécutées si la includetâche est balisée.

Limitations de imports:

  • ne peut pas être utilisé avec with_*ou loopattributs
  • impossible d'importer un fichier dont le nom dépend d'une variable

Limitations de includes:

  • --list-tags ne montre pas les tags des fichiers inclus
  • --list-tasks ne montre pas les tâches des fichiers inclus
  • vous ne pouvez pas utiliser notifypour déclencher un nom de gestionnaire qui provient de l'intérieur d'une inclusion dynamique
  • vous ne pouvez pas utiliser --start-at-taskpour commencer l'exécution d'une tâche dans une inclusion dynamique

Plus sur ici et ici .

Pour moi, cela revient essentiellement au fait que imports ne peut pas être utilisé avec des attributs de boucle.

importéchouerait certainement dans des cas comme celui-ci :

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

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

debugn'est pas exécuté, puisqu'il hérite whende la import_taskstâche. Donc, pas de fichiers de tâches d'importation qui changent les variables utilisées dans importl' whenattribut de.

J'avais une politique pour commencer avec imports, mais une fois que j'ai besoin d'un, includeassurez-vous que rien n'est importé par ce fichier inclus ou les fichiers qu'il contient. Mais c'est sacrément difficile à maintenir. Et on ne sait toujours pas si cela me protégera des ennuis. Signification, mélanger includes et imports qu'ils ne recommandent pas.

Je ne peux pas utiliser que imports, car j'ai parfois besoin de boucler des includetâches. Je pourrais probablement passer à seulement includes. Mais j'ai décidé de passer aux importations partout, sauf dans les cas où la tâche est supposée être exécutée plusieurs fois. J'ai décidé de faire l'expérience de tous ces cas difficiles. Peut-être qu'il n'y en aura pas dans mes playbooks. Ou j'espère trouver un moyen de le faire fonctionner.

UPD Une astuce éventuellement utile pour créer un fichier de tâche pouvant être importé plusieurs fois, mais exécutée une fois :

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

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

...

- name: Set _file_executed
  set_fact:
    _file_executed: True

UPD Un effet peu attendu du mélange des inclusions et des importations est l’inclusion de vars sur ceux importés:

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

Probablement, car effectue d' include_tasksabord toutes les importations statiques supplémentaires, puis modifie les variables transmises via sa varsdirective.

En fait, cela ne se produit pas uniquement avec les importations:

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 Un autre cas de mélange inclut et importe.

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

Nous obtenons trueet true, voir le cas précédent (inclure les variables ont priorité sur les variables d'importation). Nous passons donc aux inclus dans 3.yml. Mais alors la première inclusion dans 3.ymlest ignorée. Puisqu'il hérite when: httpsde la tâche parente, et que celle-ci prend soi-disant httpsde la tâche vars. La solution consiste à basculer également vers les inclusions 2.yml. Cela empêche la propagation des when: httpstâches enfants.

x-yuri
la source
4
Très bonne réponse!. J'étais frustré par le fait que tout le monde sur Internet répète ce que dit la documentation. Je vous remercie.
Sergio Acosta