在 Ansible 2.4 中,该include
模块已被弃用。取而代之的是,它附带两个替代模块import_tasks
和include_tasks
。但它们的描述非常相似:
include_tasks
:包含一个文件,其中列出了当前剧本中要执行的任务。import_tasks
:导入要添加到当前剧本中以便后续执行的任务列表。
什么时候应该使用前者,什么时候应该使用后者?
答案1
文档中有很多关于这个主题的内容:
主要区别在于:
在解析剧本时,所有
import*
语句都会进行预处理。
所有include*
语句都会在剧本执行期间遇到时进行处理。
所以import
是静态的,include
是动态的。
根据我的经验,你应该import
在处理逻辑“单元”时使用。例如,将长任务列表分成子任务文件:
主要.yml:
- import_tasks: prepare_filesystem.yml
- import_tasks: install_prerequisites.yml
- import_tasks: install_application.yml
但是您可以用来include
处理不同的工作流程,并根据一些动态收集的事实做出决策:
安装先决条件:
- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
答案2
导入是静态的,包含是动态的。导入发生在解析时,包含发生在运行时。
导入基本上是用文件中的任务替换任务。运行时没有导入任务。因此,像tags
、 和when
(以及很可能是其余的)这样的属性会被复制到每个导入的任务中。
包含的任务确实被执行。tags
并且when
只适用于任务本身。
如果导入任务未加标签,则导入文件中加标签的任务会执行。如果包含任务未加标签,则包含文件中不会执行任何任务。
如果导入任务被标记,则导入文件中的所有任务都会执行。如果包含任务被标记,则只有包含文件中的标记任务才会执行。
进口限制:
- 不能与
with_*
或loop
属性一起使用 - 无法导入名称取决于变量的文件
包括的限制:
--list-tags
不显示所包含文件的标签--list-tasks
不显示包含文件中的任务- 您不能使用
notify
它来触发来自动态包含内部的处理程序名称 - 不能用于
--start-at-task
在动态包含的任务中开始执行
对我来说,这基本上归结为导入不能与属性一起使用这一事实loop
。
在以下情况下导入肯定会失败这:
# 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
任务。因此,不会导入更改导入任务when
属性中使用的变量的任务文件。
我有一个从导入开始的政策,但一旦我需要包含,我就会确保包含的文件或其子文件不会导入任何内容。但这很难维持。而且目前还不清楚它是否能让我免受麻烦。我的意思是,不建议混合使用包含和导入。
我不能只使用导入,因为我偶尔需要循环。我可能可以切换到只包含。但我决定在需要循环的情况之外的所有情况下都切换到导入。我决定亲身体验所有这些棘手的边缘情况。也许我的剧本中不会有任何这种情况。或者希望我能找到一种方法让它发挥作用。
更新型多巴胺创建一个可以多次导入的任务文件可能有用的技巧,但是仅执行一次:
- name: ...
...
when: not _file_executed | default(False)
- name: ...
...
when: not _file_executed | default(False)
...
- name: Set _file_executed
set_fact:
_file_executed: True
更新型多巴胺混合包含和导入的一个意想不到的效果是包含任务的变量会覆盖导入任务的变量:
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
更新型多巴胺另一种情况是混合包含和导入。
playbook.yml
:
- hosts: all
tasks:
# say, you're bound to use include here (because you need a 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 the https var
- import_tasks: 4.yml
4.yml
:
- debug:
var: https
我们得到true
和true
,参见前一种情况(include_tasks
'vars 优先于import_tasks
')。为了避免这种情况,我们可以切换到包含在中3.yml
。但是第一个包含在中3.yml
被跳过。由于它继承when: https
自父任务,因此第一个任务基本上是这样的:
- import_tasks: 4.yml
vars:
https: no # here we're trying to temporarily override the https var
when: https
解决方案是切换到包含2.yml
。这可以防止传播when: https
到子任务。