将变量传递给包含的剧本
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}}"}
。
对此有什么优雅的解决方案吗?
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 作为参考,它指的是 name 而 name 现在指的是 new_val.所以目前唯一的价值是 new_value 和 name1 和 name 只是参考参考new_value。
对 old_value 的引用已丢失。
现在考虑以下脚本:
main_recursive.yml
---
- hosts: all
vars:
- name: shasha
- name1: "{{name}}"
- name: "{{name1}}"
tasks:
- debug: msg="{{name}}"
现在让我们尝试解决 name 的值。 name 指向 name1 而 name1 指向 name.没关系,但我们如何才能达到实际价值???没办法,这是一个递归循环!!!
我正在从我的剧本中加入另一本剧本。我需要向它传递一个名为 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}}"}
。
对此有什么优雅的解决方案吗?
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 作为参考,它指的是 name 而 name 现在指的是 new_val.所以目前唯一的价值是 new_value 和 name1 和 name 只是参考参考new_value。 对 old_value 的引用已丢失。
现在考虑以下脚本:
main_recursive.yml
---
- hosts: all
vars:
- name: shasha
- name1: "{{name}}"
- name: "{{name1}}"
tasks:
- debug: msg="{{name}}"
现在让我们尝试解决 name 的值。 name 指向 name1 而 name1 指向 name.没关系,但我们如何才能达到实际价值???没办法,这是一个递归循环!!!