include_tasks和import_tasks有什么区别?


62

在Ansible 2.4中,该include模块已弃用。它附带两个替换模块,import_tasksinclude_tasks。但是它们有非常相似的描述:

  • include_tasks:包括一个文件,其中包含要在当前剧本中执行的任务的列表。
  • import_tasks:导入要添加到当前剧本以供后续执行的任务列表。

我什么时候应该使用前者,什么时候应该使用后者?


(另外:弃用警告是指“动态”和“静态”任务。我阅读了文档但不理解它们。)
Ben S

Answers:


68

文档中有很多关于此主题的内容:

主要区别在于:

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

8
我发现此链接非常有用:docs.ansible.com/ansible/latest/…它指出了导入和包含行为不同的情况-一种“何时”条件,其中文件中的任务可能会更改用于确定导入的条件。使用import_tasks,每个任务都会检查标准,因此,当标准更改时,行为也会更改。对于include_tasks,根据执行include_tasks语句时条件是否被评估为true来确定任务是否存在。如果我听得懂...
Ethel Evans

的行为是include什么?如果我们使用includeimport_tasks是等效的?
安迪·辛

include具有static: yes(的行为类似import_tasks)和static: no(如include_tasks)。
康斯坦丁·苏沃洛夫

默认值是static什么?
安迪·辛

staticNone默认:因为Ansible 2.0,任务包括是动态的,更像真正的任务。这意味着可以循环,跳过它们并使用任何来源的变量。Ansible尝试自动检测到此问题,但是您可以使用static指令(在Ansible 2.1中添加了该指令)绕过自动检测。
康斯坦丁·苏沃洛夫'18

15

导入是静态的,包含是动态的。导入在解析时进行,包括在运行时。

导入基本上将任务替换为文件中的任务。import_task在运行时没有。因此,诸如tags和和when(以及最可能的其他属性)之类的属性被复制到每个导入的任务中。

include确实已执行。tags并且when包含的任务仅适用于任务本身。

如果import任务是未标记的,则将执行导入文件中标记的任务。如果include任务未加标签,则不会从包含的文件中执行任何任务。

如果import标记了任务,则将执行导入文件中的所有任务。如果标记了任务,则仅执行包含文件中的标记任务include

imports的局限性:

  • 不能与with_*loop属性一起使用
  • 无法导入文件,名称取决于变量

includes的局限性:

  • --list-tags 不显示包含文件中的标签
  • --list-tasks 不显示包含文件中的任务
  • 您不能notify用来触发来自动态包含内部的处理程序名称
  • 您不能--start-at-task用来开始执行动态包含中的任务

这里这里有更多的信息

对我来说,基本上可以归结为imports不能与循环属性一起使用的事实。

import肯定会失败,在这样的情况下这样

# playbook.yml
- import_tasks: set-x.yml
  when: x is not defined

# set-x.yml
- set_fact
  x: foo
- debug:
  var: x

debug不执行,因为它whenimport_tasks任务继承。因此,没有导入任务文件会更改importwhen属性中使用的变量。

我有一个以imports 开头的策略,但是一旦需要,请include确保该包含的文件或包含的文件未导入任何内容。但这很难维护。目前尚不清楚是否能保护我免受麻烦。含义是,将includes和imports 混合使用,而不推荐使用。

我不能只使用imports,因为我偶尔需要循环include执行任务。我可能只能切换到includes。但是我决定在所有地方都改用导入,除了应该多次执行该任务的情况。我决定亲自体验所有这些棘手的情况。也许我的剧本中没有任何内容。或希望我能找到一种使之起作用的方法。

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

我们得到truetrue,参见前面的情况(include vars优先于import vars)。因此,我们切换到include in 3.yml。但是随后将3.yml跳过第一个包含。由于它是when: https从父任务继承而来的,因此后者应该https从任务的继承vars。解决方案是也切换到包含2.yml。这样可以防止传播when: https到子任务。


4
好答案!互联网上的每个人都只是重复文档中的内容而感到沮丧。谢谢。
塞尔吉奥·阿科斯塔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.