将变量传递给包含的剧本

Pass through a variable to an included playbook

我正在从我的剧本中加入另一本剧本。我需要向它传递一个名为 required_node_version 的变量。我在我的剧本中使用了相同的变量,所以期望包含的剧本会继承它。但它不会导致 'undefined' 错误。所以我尝试使用这个不太优雅的解决方案:

- hosts: localhost
  connection: local
  vars:
    required_node_version: v6.3.1

  ...    

- include: ../../base/ci/build.yml
  vars:
    required_node_version: "{{required_node_version}}"

这导致 {"failed": true, "msg": "ERROR! recursive loop detected in template string: {{required_node_version}}"}

对此有什么优雅的解决方案吗?

有点documentation:

Ansible has 3 main scopes:

Global: this is set by config, environment variables and the command line
Play: each play and contained structures, vars entries, include_vars, role defaults and vars.
Host: variables directly associated to a host, like inventory, facts or registered task outputs

因此,您为每个剧本定义的变量彼此不了解。

您有两个选择:

  • 全局设置required_node_version(通过-e开关),所以它会在任何地方定义

  • 为每个单独的主机设置 required_node_version(即通过 ./group_vars/all.yml 文件),因此它将作为主机绑定事实在每个任务中可用。

Ansible 单独维护每个播放的状态。一个剧本的可变范围也与其他剧本分开。您可以将 play 中定义的变量范围视为有向无环图,其中每个节点名称都是唯一的,并且值将在第二次写入时被覆盖。

当你在剧本中包含其他一些剧本时(包括顶层的剧本),被包含的剧本将有自己的变量范围,因为它是一个完全不同的剧本。所以你将无法访问 main play 中定义的变量。实际的错误不是 recursive loop detected error,实际的错误是 variable undefined error 因为你正试图访问某个定义的变量其他玩法。

试试这个:

main.yml

---
- hosts: all
  vars:
    name: shasha

- include: included_playbook.yml
  vars:
    name1: "{{name}}""

现在您将得到实际错误:名称未定义,因为您在分配 [=60= 时试图从不同范围(不同游戏)访问变量]name 到 name1.

现在将您的 main.yml 更改为:

main.yml

---
- hosts: all
  vars:
    name: shasha

- include: included_playbook.yml
  vars:
    name: shashank

name虽然定义了两次,但由于作用域不同(主要作用域和包含作用域),所以它们是不同的。所以这工作正常,没有任何问题。


一些替代解决方案:

1.调用剧本时传递变量:

由于您包含的剧本也可以 运行 作为主要剧本,那么您将如何使用该变量?您要么在该剧本中定义变量,要么从命令行传递它。

当您在调用剧本时传递变量时,它会自动在两个剧本(主要剧本和包含的剧本)的范围内创建该变量:

ansible-playbook -i hosts main.yml -e "required_node_version=v6.3.1"

或者您可以创建一个 JSON 文件,其中包含您所包含的所有剧本中共有的所有公共变量,然后在调用主要的 ansible 剧本时传递该 JSON 文件。

2。重新设计您的 Ansible 剧本:

如果您包含的 ansible playbook 用作帮助程序而不是以独立方式使用,则您应该在任务级别包含此 playbook。您仍将保持可重用性,并且只有一个作用域,因此您无需担心显式传递变量。

更多关于递归循环检测到错误的原因:

Ansible在给一个变量赋值时实际上并没有使用右值的概念,而是执行了两者之间的绑定。例如,您认为以下代码中变量 name1 的值是什么:

main.yml

---
- hosts: all
  vars:
   - name: old_val
   - name1: "{{name}}"
   - name: new_val

  tasks:
    - debug: msg="{{name1}}"

如果你的答案是new_val,你就明白其中的逻辑了。考虑 name1 作为参考,它指的是 namename 现在指的是 new_val.所以目前唯一的价值是 new_valuename1name 只是参考参考new_value。 对 old_value 的引用已丢失。

现在考虑以下脚本:

main_recursive.yml

---
- hosts: all
  vars:
   - name: shasha
   - name1: "{{name}}"
   - name: "{{name1}}"

  tasks:
    - debug: msg="{{name}}"

现在让我们尝试解决 name 的值。 name 指向 name1name1 指向 name.没关系,但我们如何才能达到实际价值???没办法,这是一个递归循环!!!