如何在Ansible中合并拥有共同键的嵌套字典?
在Ansible中合并嵌套字典的相同条目属性
当然可以实现!这种把敏感配置(比如VPN共享密钥)和普通配置分开存储,甚至将敏感部分用Vault加密的需求非常常见,Ansible内置的combine过滤器就能完美解决你的问题。
具体实现步骤
假设你已经将配置分别放在两个文件中:
vpns.yml:存储普通VPN配置(未加密)vpn_credentials.yml:存储Vault加密的共享密钥
1. 编写Playbook实现合并
在你的playbook中,先加载这两个变量文件,然后使用combine过滤器并加上recursive=True参数来递归合并嵌套字典:
- name: 合并VPN配置与加密的共享密钥 hosts: localhost vars_files: - vpns.yml - vpn_credentials.yml tasks: - name: 生成合并后的完整VPN字典 set_fact: merged_vpns: "{{ vpns | combine(vpn_credentials, recursive=True) }}" - name: 验证合并结果(仅用于测试) debug: var: merged_vpns
2. 关键参数说明
combine:Ansible用于合并字典的核心过滤器,默认情况下会用右侧字典的键覆盖左侧同名键recursive=True:开启递归合并模式,针对嵌套字典,当外层键(比如example、example2)相同时,会将内层的键值对(比如vpn_shared_key)合并到一起,而非直接替换整个内层字典——这正是你需要的行为
3. Vault加密文件的使用
因为vpn_credentials.yml是加密状态,你只需要:
- 用
ansible-vault encrypt vpn_credentials.yml加密该文件 - 运行playbook时加上
--ask-vault-pass(交互式输入Vault密码),或者指定密码文件--vault-password-file=your_vault_pass_file,Ansible会自动解密加载变量,完全不影响合并逻辑
合并后的结果
执行上述playbook后,merged_vpns变量就会生成你期望的结构:
merged_vpns: example: vpn_connection_name: "example" vpn_client_public_ip: "xxx.xxx.xxx.xxx" vpn_shared_key: "somekey" example2: vpn_connection_name: "example2" vpn_client_public_ip: "xxx.xxx.xxx.xxx" vpn_shared_key: "someotherkey"
如果遇到内层键冲突的情况(比如两个字典有同名的内层键且值不同),combine会默认用右侧字典(vpn_credentials)的值覆盖左侧,但在你的场景中应该不会出现这种情况,因为两边的配置是互补的。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

