Dans Ansible 2.4, le module include
est obsolète. À sa place, il est livré avec deux modules de remplacement, import_tasks
et 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 en cours pour une exécution ultérieure.Quand dois-je utiliser le premier et quand dois-je utiliser le second?
Il y a pas mal de choses sur ce sujet dans la documentation:
La principale différence est:
Tout
import*
les instructions sont prétraitées au moment de l'analyse des playbooks.
Toutinclude*
les instructions sont traitées telles qu'elles se sont produites lors de l'exécution du playbook.
Donc import
est statique, include
est dynamique.
D'après mon expérience, vous devriez utiliser import
lorsque vous traitez avec des "unités" logiques. Par exemple, séparez la longue liste de tâches en fichiers de sous-tâches:
main.yml:
- import_tasks: prepare_filesystem.yml
- import_tasks: install_prerequisites.yml
- import_tasks: install_application.yml
Mais vous utiliseriez include
pour gérer différents workflows et prendre des décisions basées sur des faits collectés dynamiquement:
install_prerequisites:
- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
Les importations sont statiques, les inclus sont dynamiques. Les importations se produisent 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_task
lors de l'exécution. Ainsi, des attributs tels que tags
et when
(et probablement d'autres attributs) sont copiés dans chaque tâche importée.
include
s sont en effet exécutés. tags
et when
d'une tâche incluse ne s'appliquent qu'à la tâche elle-même.
Les tâches balisées d'un fichier importé sont exécutées si la tâche import
n'est pas balisée. Aucune tâche n'est exécutée à partir d'un fichier inclus si la tâche include
n'est pas balisée.
Toutes les tâches d'un fichier importé sont exécutées si la tâche import
est balisée. Seules les tâches balisées d'un fichier inclus sont exécutées si la tâche include
est balisée.
Limitations de import
s:
with_*
ou loop
attributsLimitations de include
s:
--list-tags
n'affiche pas les balises des fichiers inclus--list-tasks
n'affiche pas les tâches des fichiers inclusnotify
pour déclencher un nom de gestionnaire provenant de l'intérieur d'une inclusion dynamique--start-at-task
pour commencer l'exécution d'une tâche à l'intérieur d'une inclusion dynamiquePour moi, cela revient essentiellement au fait que import
s ne peut pas être utilisé avec des attributs de boucle.
import
échouerait certainement dans des cas comme this :
# playbook.yml
- import_tasks: set-x.yml
when: x is not defined
# set-x.yml
- set_fact
x: foo
- debug:
var: x
debug
n'est pas exécuté, car il hérite when
de import_tasks
tâche. Ainsi, aucun fichier de tâches d'importation qui modifie les variables utilisées dans l'attribut import
de when
.
J'avais une politique pour commencer par import
s, mais une fois que j'ai besoin d'un include
assurez-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élange de include
s et import
s qu'ils ne recommandent pas.
Je ne peux pas utiliser uniquement import
s, car j'ai parfois besoin de boucler include
tâches. Je pourrais probablement passer à seulement include
s. Mais j'ai décidé de passer aux importations partout, sauf dans les cas où la tâche est censée être exécutée plusieurs fois. J'ai décidé de faire l'expérience de tous ces cas Edge difficiles. Peut-être qu'il n'y en aura pas dans mes livres de jeu. Ou j'espère que je trouverai un moyen de le faire fonctionner.
[~ # ~] upd [~ # ~] Une astuce peut-être utile pour créer un fichier de tâches qui peut être importé plusieurs fois, mais exécuté 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 pas vraiment attendu du mixage inclut et importe est que les vars remplacent 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 parce que include_tasks
effectue d'abord toutes les importations statiques supplémentaires, puis modifie les variables transmises via sa directive vars
.
En fait, cela ne se produit pas seulement 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 mixage 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 true
et true
, voir le cas précédent (les vars inclus ont priorité sur les vars d'importation). Nous passons donc aux inclusions dans 3.yml
. Mais le premier inclut dans 3.yml
est ignoré. Puisqu'il hérite when: https
de la tâche parent, et cette dernière prend soi-disant https
du vars
de la tâche. La solution consiste à passer aux inclusions dans 2.yml
ainsi que. Cela empêche la propagation de when: https
aux tâches enfants.