include_tasks 和 import_tasks 之间有什么区别?

include_tasks 和 import_tasks 之间有什么区别?

在 Ansible 2.4 中,该include模块已被弃用。取而代之的是,它附带两个替代模块import_tasksinclude_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不会执行,因为它继承whenimport_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

我们得到truetrue,参见前一种情况(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到子任务。

相关内容