Answers:
文档中有很多关于此主题的内容:
主要区别在于:
import*
在解析剧本时,所有语句都会进行预处理。
所有include*
语句都按照在执行Playbook时遇到的方式进行处理。
所以import
是静态的,include
是动态的。
根据我的经验,import
在处理逻辑“单位”时应该使用。例如,将一长串任务分成子任务文件:
main.yml:
- import_tasks: prepare_filesystem.yml
- import_tasks: install_prerequisites.yml
- import_tasks: install_application.yml
但是您将习惯于include
处理不同的工作流程并根据一些动态收集的事实做出决策:
install_prerequisites:
- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
include
什么?如果我们使用include
将import_tasks
是等效的?
include
具有static: yes
(的行为类似import_tasks
)和static: no
(如include_tasks
)。
static
什么?
static
是None
默认:因为Ansible 2.0,任务包括是动态的,更像真正的任务。这意味着可以循环,跳过它们并使用任何来源的变量。Ansible尝试自动检测到此问题,但是您可以使用static指令(在Ansible 2.1中添加了该指令)绕过自动检测。
导入是静态的,包含是动态的。导入在解析时进行,包括在运行时。
导入基本上将任务替换为文件中的任务。import_task
在运行时没有。因此,诸如tags
和和when
(以及最可能的其他属性)之类的属性被复制到每个导入的任务中。
include
确实已执行。tags
并且when
包含的任务仅适用于任务本身。
如果import
任务是未标记的,则将执行导入文件中标记的任务。如果include
任务未加标签,则不会从包含的文件中执行任何任务。
如果import
标记了任务,则将执行导入文件中的所有任务。如果标记了任务,则仅执行包含文件中的标记任务include
。
import
s的局限性:
with_*
或loop
属性一起使用include
s的局限性:
--list-tags
不显示包含文件中的标签--list-tasks
不显示包含文件中的任务notify
用来触发来自动态包含内部的处理程序名称--start-at-task
用来开始执行动态包含中的任务对我来说,基本上可以归结为import
s不能与循环属性一起使用的事实。
import
肯定会失败,在这样的情况下这样:
# playbook.yml
- import_tasks: set-x.yml
when: x is not defined
# set-x.yml
- set_fact
x: foo
- debug:
var: x
debug
不执行,因为它when
从import_tasks
任务继承。因此,没有导入任务文件会更改import
的when
属性中使用的变量。
我有一个以import
s 开头的策略,但是一旦需要,请include
确保该包含的文件或包含的文件未导入任何内容。但这很难维护。目前尚不清楚是否能保护我免受麻烦。含义是,将include
s和import
s 混合使用,而不推荐使用。
我不能只使用import
s,因为我偶尔需要循环include
执行任务。我可能只能切换到include
s。但是我决定在所有地方都改用导入,除了应该多次执行该任务的情况。我决定亲自体验所有这些棘手的情况。也许我的剧本中没有任何内容。或希望我能找到一种使之起作用的方法。
UPD创建任务文件可以多次导入但执行一次的可能有用的技巧:
- name: ...
...
when: not _file_executed | default(False)
- name: ...
...
when: not _file_executed | default(False)
...
- name: Set _file_executed
set_fact:
_file_executed: True
UPD混合包含和导入的一个并非真正预期的效果是,包含vars覆盖了导入变量:
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
可能是因为include_tasks
首先执行所有其他静态导入,然后更改通过其vars
指令传递的变量。
实际上,这不仅发生在进口方面:
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另一种混合情况包括进口。
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
我们得到true
和true
,参见前面的情况(include vars优先于import vars)。因此,我们切换到include in 3.yml
。但是随后将3.yml
跳过第一个包含。由于它是when: https
从父任务继承而来的,因此后者应该https
从任务的继承vars
。解决方案是也切换到包含2.yml
。这样可以防止传播when: https
到子任务。