在Ansible 2.4中,不建议使用include模块。它随附两个替换模块import_tasksinclude_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 楼

导入是静态的,包含是动态的。导入在解析时发生,包括在运行时。
导入基本上将任务替换为文件中的任务。在运行时没有导入任务。因此,会将tagswhen之类的属性(很可能是其余的属性)复制到每个导入的任务中。
包含确实得以执行。包含的任务的tagswhen仅适用于任务本身。
如果未标记导入任务,则将执行导入文件中标记的任务。如果未标记包含任务,则不会从包含的文件执行任何任务。
如果标记了导入任务,则导入文件中的所有任务都会执行。如果标记了包含任务,则仅执行包含文件中标记的任务。
导入限制:

不能与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.ymltrue,请参见前面的情况(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