我想使用vars
将多个变量传递给任务。目前,我正在执行下面的
vars:
var1_name: "var1_value"
var2_name: "var2_value"
随着变量数量的增加,我宁愿使用vars
将变量字典传递给任务。我构建了一个变量字典,如下面的
- name: set fact
hosts: localhost
tasks:
- set_fact:
variables: "{{ variables|default({}) | combine( {item.variable: item.value} ) }}"
with_items:
- variable: var1_name
value: "var1_value"
- variable: var2_name
value: "var2_name"
字典看起来像这样:
"variables": {
"var1_name": "var1_value",
"var2_name": "var2_value",
}
现在,我想让这个字典中的变量可用于在其他主机上执行的角色。
但是,当我尝试将字典传递给vars
时,如下所示
vars: "{{ variables }}"
Ansible抛出错误:
ERROR! Vars in a Play must be specified as a dictionary, or a list of dictionaries
如何在vars
中传递字典变量?
答案 0 :(得分:3)
在对Ansible源代码进行一些搜索之后,即使是Ansible的开发人员也面临着这个问题。在某些集成测试中,由于同样的错误,有一些特定的测试被注释掉了。
ansible /测试/集成/目标/ include_import /角色/ test_include_role.yml
## FIXME Currently failing with
## ERROR! Vars in a IncludeRole must be specified as a dictionary, or a list of dictionaries
# - name: Pass all variables in a variable to role
# include_role:
# name: role1
# tasks_from: vartest.yml
# vars: "{{ role_vars }}"
我还发现这是被调用以包含变量的基础函数:
def _load_vars(self, attr, ds):
'''
Vars in a play can be specified either as a dictionary directly, or
as a list of dictionaries. If the later, this method will turn the
list into a single dictionary.
'''
def _validate_variable_keys(ds):
for key in ds:
if not isidentifier(key):
raise TypeError("'%s' is not a valid variable name" % key)
try:
if isinstance(ds, dict):
_validate_variable_keys(ds)
return combine_vars(self.vars, ds)
elif isinstance(ds, list):
all_vars = self.vars
for item in ds:
if not isinstance(item, dict):
raise ValueError
_validate_variable_keys(item)
all_vars = combine_vars(all_vars, item)
return all_vars
elif ds is None:
return {}
else:
raise ValueError
except ValueError as e:
raise AnsibleParserError("Vars in a %s must be specified as a dictionary, or a list of dictionaries" % self.__class__.__name__,
obj=ds, orig_exc=e)
except TypeError as e:
raise AnsibleParserError("Invalid variable name in vars specified for %s: %s" % (self.__class__.__name__, e), obj=ds, orig_exc=e)
似乎因为“{{}}”实际上只是一个YAML字符串,Ansible不会将其识别为dict,这意味着vars属性没有通过Jinja2引擎传递,而是被评估为什么它实际上是。
传递YAML对象的唯一方法是使用锚点,但是这需要整个而不是动态地定义对象。
var: &_anchored_var
attr1: "test"
att2: "bar"
vars:
<<: *_anchored_var
答案 1 :(得分:1)
我建议使用结构化的方式管理变量,如:
档案myvars1.yml
myvars:
var1_name: "var1_value"
var2_name: "var2_value"
然后读取像
这样的变量 - name: Read all variables
block:
- name: Get All Variables
stat:
path: "{{item}}"
with_fileglob:
- "/myansiblehome/vars/common/myvars1.yml"
- "/myansiblehome/vars/common/myvars2.yml"
register: _variables_stat
- name: Include Variables when found
include_vars : "{{item.stat.path}}"
when : item.stat.exists
with_items : "{{_variables_stat.results}}"
no_log : true
delegate_to: localhost
become: false
之后,请使用:
- name: My Running Module
mymodule:
myaction1: "{{ myvars.var1_name }}"
myaction2: "{{ myvars.var2_name }}"
希望有所帮助
答案 2 :(得分:0)
您可以使用dict
查找。
以您的示例为例,我会这样做:
- hosts: localhost
vars:
my_vars_dict:
var1_name: "var1_value"
var2_name: "var2_value"
tasks:
- debug:
msg: "Key: {{ item.key }} | Value: {{ item.value }}"
loop: "{{ lookup('dict', my_vars_dict) }}"
输出为:
Key: var2_name | Value: var2_value
Key: var1_name | Value: var1_value
摘自文档:https://docs.ansible.com/ansible/latest/plugins/lookup/dict.html