我在剧本中加入了另一本剧本。我需要传递一个名为required_node_version
的变量。我在我的剧本中使用相同的变量,所以期待包含的剧本将继承它。但它不会导致“未定义”错误。所以我尝试使用这个不是很优雅的解决方案:
- 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}}"}
。
对此有什么优雅的解决方案吗?
答案 0 :(得分:3)
Ansible分别保持每个游戏的状态。一个游戏的可变范围也与其他游戏分开。您可以将播放中定义的变量范围视为有向非循环图,其中每个节点名称都是唯一的,并且值将在第二次写入时被覆盖。
当你在剧本中包含一些其他剧本(包括顶级剧本)时,所包含的剧本将拥有自己的变量范围,因为它是一个完全不同的剧本。因此,您将无法访问主游戏中定义的变量。实际错误不是递归循环检测错误,实际错误是变量未定义错误,因为您正在尝试访问在某些其他游戏中定义的变量。
试试这个:
<强> main.yml 强>
---
- hosts: all
vars:
name: shasha
- include: included_playbook.yml
vars:
name1: "{{name}}""
现在您将收到以下实际错误:名称未定义,因为您尝试从名称分配名称时访问不同范围(不同游戏)的变量的 NAME1 强>
现在用以下内容更改 main.yml :
<强> main.yml 强>
---
- hosts: all
vars:
name: shasha
- include: included_playbook.yml
vars:
name: shashank
虽然名称被定义了两次,但它们彼此不同,因为两者的范围不同(主要游戏的范围和所包含游戏的范围)。所以这没有任何问题。
<强> 1。在调用playbook时传递变量:
由于您所包含的剧本也可以作为主剧本运行,在这种情况下您将如何使用该变量?您可以在该剧本中定义变量,也可以从命令行传递它。
当您在调用playbook时传递变量时,它会自动在两个剧本的范围内创建该变量(主要剧本以及包含的剧本):
ansible-playbook -i hosts main.yml -e "required_node_version=v6.3.1"
或许您可以创建一个JSON文件,其中包含所有常用变量,这些变量在您包含的所有剧本中都很常见,然后在调用主要的ansible剧本时传递该JSON文件。
<强> 2。重新设计你的Ansible剧本:
如果您所包含的ansible剧本作为助手而不是以独立方式使用,那么您应该在任务级别包含此剧本。您仍将保持可重用性,并且只有一个范围,因此您不必担心明确传递变量。
当您将变量赋值给变量时,Ansible实际上不使用rvalue的概念,而是执行两者之间的绑定。例如,您认为以下代码中变量 name1 的价值是什么:
<强> main.yml 强>
---
- hosts: all
vars:
- name: old_val
- name1: "{{name}}"
- name: new_val
tasks:
- debug: msg="{{name1}}"
如果你的答案是 new_val ,你就明白了逻辑。考虑 name1 作为参考,指的是名称,而名称现在指的是new_val。因此,唯一的值是 new_value 和 name1 ,名称只是引用 new_value 的引用。 old_value 的引用将丢失。
现在考虑以下脚本:
<强> main_recursive.yml 强>
---
- hosts: all
vars:
- name: shasha
- name1: "{{name}}"
- name: "{{name1}}"
tasks:
- debug: msg="{{name}}"
现在让我们尝试重新名称的值。 名称指向 name1 , name1 指向名称。那没关系,但我们怎样才能达到实际值?没办法,它是一个递归循环!!!
答案 1 :(得分:1)
Ansible有3个主要范围:
全局:这是由配置,环境变量和命令行设置的 播放:每个播放和包含的结构,变量条目,include_vars,角色默认值和变量。
主机:与主机直接关联的变量,例如广告资源,事实或已注册的任务输出
因此,您为每个游戏定义的变量彼此不了解。
您有两种选择:
全局设置required_node_version
(通过-e
开关),因此它将在任何地方定义
为每个主机设置required_node_version
(即通过./group_vars/all.yml
文件),因此它将作为主机绑定事实在每个任务中可用。