include
模块。它随附两个替换模块import_tasks
和include_tasks
。但是它们具有非常相似的描述:include_tasks
:包括一个文件,其中包含要在当前剧本中执行的任务列表。import_tasks
:导入要添加到当前剧本中以供后续执行的任务列表。我什么时候应该使用前者,什么时候应该使用后者?
#1 楼
文档中有很多关于此主题的内容:包含与导入
动态与静态
主要区别在于:
在解析剧本时,将对所有
import*
语句进行预处理。在执行剧本时,将对它们进行处理。 >
所以
include*
是静态的,import
是动态的。根据我的经验,在处理逻辑“单位”时应使用
include
。例如,将一长串任务分成子任务文件:main.yml:
- import_tasks: prepare_filesystem.yml
- import_tasks: install_prerequisites.yml
- import_tasks: install_application.yml
但是您可以使用
import
来处理不同的任务工作流并根据一些动态收集的事实做出决策:install_prerequisites:
- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
评论
我发现此链接非常有用:docs.ansible.com/ansible/latest/…它指出了导入和包含行为不同的情况-一种“何时”条件,其中文件中的任务可能会更改用于确定导入的条件。使用import_tasks,每个任务都会检查标准,因此,当标准更改时,行为也会更改。使用include_tasks时,根据执行include_tasks语句时条件是否被评估为true来确定任务是否存在。如果我了解...
– Ethel Evans
17年12月6日在20:28
包含的行为是什么?如果我们使用include,那么import_tasks是否等效?
–安迪·辛(Andy Shinn)
18年1月18日在20:27
include具有static:是(行为与import_tasks相似)和static:否(例如include_tasks)。
–康斯坦丁·苏沃洛夫(Konstantin Suvorov)
18年1月19日在6:28
静态默认值是什么?
–安迪·辛(Andy Shinn)
18年5月30日在0:46
static默认情况下为None:自Ansible 2.0起,任务包含是动态的,其行为更像真实任务。这意味着它们可以循环,跳过并使用任何来源的变量。 Ansible尝试自动检测到此问题,但是您可以使用static指令(在Ansible 2.1中添加了此指令)绕过自动检测。
–康斯坦丁·苏沃洛夫(Konstantin Suvorov)
18年5月30日在7:48
#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
属性中使用的变量。我有一个从导入开始的策略,但是一旦需要包含文件,我就确保包含文件或其子文件不会导入任何内容。但这很难维护。目前尚不清楚是否能保护我免受麻烦。我的意思是,不建议混合包含和导入。
我不能只使用导入,因为我偶尔需要循环。我可能会切换到仅包含。但是我决定在所有地方都需要改用导入,除了需要循环的情况。我决定亲自体验所有这些棘手的情况。也许我的剧本中没有任何内容。或者希望我能找到一种使之工作的方法。
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混合包含和导入的效果不是真正预期的,是包含任务的var会覆盖导入的任务:
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
伪指令。实际上,它也可以像这样复制: - hosts: all
tasks:
- import_tasks: 2.yml
vars:
v1: 1
- include_tasks: 2.yml
vars:
v1: 1
playbook.yml
:- debug:
var: v1 # 2 then 1
vars:
v1: 2
UPD另一种混合情况包括进口。
2.yml
:- hosts: all
tasks:
# say, you're bound to use include here (because you need a loop)
- include_tasks: 2.yml
vars:
https: yes
playbook.yml
:- import_tasks: 3.yml
when: https
2.yml
:- import_tasks: 4.yml
vars:
https: no # here we're trying to temporarily override the https var
- import_tasks: 4.yml
3.yml
:- debug:
var: https
我们得到
4.yml
和true
,请参见前面的情况(true
'var优先于include_tasks
')。为了避免这种情况,我们可以切换到import_tasks
中的include。但是随后会跳过3.yml
中的第一个包含项。由于它从父任务继承了3.yml
,因此第一个任务的基本内容为:- import_tasks: 4.yml
vars:
https: no # here we're trying to temporarily override the https var
when: https
解决方案是也切换到
when: https
中的包含项。这样可以防止2.yml
传播到子任务。评论
好答案!互联网上的每个人都只是重复文档中的内容而感到沮丧。谢谢。
–塞尔吉奥·阿科斯塔(Sergio Acosta)
19年1月26日,下午2:22
塞尔吉奥·阿科斯塔(Sergio Acosta)恰好-最终的答案是导入是静态的,包括动态的,就像它应该向您解释它的工作原理一样:-P
–坦率
20年8月7日在8:58
评论
(另外:弃用警告涉及“动态”和“静态”任务。我阅读了文档,但不理解它们。)