在Ansible中合并字典
我现在正在用ansible创建一个安装PHP的角色,但在合并字典时遇到了一些困难。我尝试了几种方法,但就是无法达到我想要的效果:
# A vars file:
my_default_values:
key = value
my_values:
my_key = my_value
# In a playbook, I create a task to attempt merging the
# two dictionaries (which doesn't work):
- debug: msg="{{ item.key }} = {{ item.value }}"
with_dict: my_default_values + my_values
# I have also tried:
- debug: msg="{{ item.key }} = {{ item.value }}"
with_dict: my_default_values|union(my_values)
# I have /some/ success with using j2's update,
# but you can't use j2 syntax in "with_dict", it appears.
# This works:
- debug: msg="{{ my_default_values.update(my_values) }}"
# But this doesn't:
- debug: msg="{{ item.key }} = {{ item.value }}"
with_dict: my_default_values.update(my_values)
有没有办法合并两个字典,这样我就可以用“with_dict”来使用它?
6 个回答
2
试试这个来自Ansible Galaxy的角色。
我之前也因为同样的原因用过这个。它可以把多个变量文件里的字典深度合并,并且可以设置合并的优先级。
这个角色可以在Ansible 2.0及以上版本中使用。
6
如果你需要多次使用合并后的字典,可以把它存储到一个新的“变量”里:
- set_fact: _my_values="{{ my_default_values|combine(my_values) }}"
- debug: msg="{{ item.key }} = {{ item.value }}"
with_dict: _my_values
14
如果你想要合并哈希(也就是把多个变量合成一个),你需要在 Ansible 中开启这个功能。具体来说,在你的 Ansible 配置文件里,把哈希合并功能打开。
当你设置 hash_behaviour=merge 后,你可以有两个变量文件,它们里面有相同的变量名:
第一个文件是 defaults.yml:
values:
key: value
第二个文件是 overrides.yml:
values:
my_key: my_value
为了让这两个变量合并,你需要同时包含这两个变量文件:
ansible-playbook some-play.yml ... -e@defaults.yml -e@overrides.yml
这样你最终会得到:
TASK: [debug var=values] ********************************************************
ok: [localhost] => {
"values": {
"key": value,
"my_key": my_value
}
}
在 Jinja 中更新变量是可以做到的,但通常这样做会比较麻烦。我建议你不要在模板之外进行这样的操作,即使在模板中也尽量避免。
22
现在可以使用YAML的锚点和扩展功能了:
---
- hosts: localhost
vars:
my_default_values: &def
key: value
my_values:
<<: *def
my_key: my_value
tasks:
- debug: var=my_default_values
- debug: var=my_values
结果:
TASK [debug]
ok: [localhost] => {
"my_default_values": {
"key": "value"
}
}
TASK [debug]
ok: [localhost] => {
"my_values": {
"key": "value",
"my_key": "my_value"
}
}
我不知道为什么之前没有提到这个。
105
在 Ansible 2.0 中,有一个叫做 combine
的 Jinja 过滤器,可以用来做这个事情:
- debug: msg="{{ item.key }} = {{ item.value }}"
with_dict: "{{ my_default_values | combine(my_values) }}"