Ansible提取环境变量生成字典时合并顶层值移除外层键的方案
Ansible 多层字典合并方案
场景说明
需要从Ansible主机变量中匹配特定命名规则的环境变量,合并变量对应的内层字典,移除顶层变量名层级。
原表达式
env_loadbalancer_vservers2: "{{ hostvars[inventory_hostname] | dict2items | selectattr('key', 'match', 'env_.*_loadbalancer_vservers(?![_.])') | list | items2dict }} "
原逻辑
- 获取指定主机在Ansible中的所有变量
- 将字典转换为键值对列表
- 通过正则匹配筛选出符合命名规则的变量
- 转换为列表
- 重新转换为字典
原输出结构
{ "env_decision_manager_loadbalancer_vservers": { "decision_central": { "ip_or_dns": "ip", "port": "port", "protocol": "SSL", "ssl": true, "timeout": 600, } }, "env_ftp_loadbalancer_vservers": { "ftp_1": { "ip_or_dns": "ip", "port": "port", "protocol": "FTP", "ssl": false, "timeout": 9010, } }, "env_jboss_loadbalancer_vservers": { "jboss": { "ip_or_dns": "ip", "port": "port", "protocol": "SSL", "ssl": true, "timeout": 600, }, "jboss_adm": { "ip_or_dns": "som_other_ip", "port": "rando_number", "protocol": "SSL", "ssl": true, "timeout": 86410, } } }
期望输出结构
{ "decision_central": { "ip_or_dns": "ip", "port": "port", "protocol": "SSL", "ssl": true, "timeout": 600, }, "ftp_1": { "ip_or_dns": "ip", "port": "port", "protocol": "FTP", "ssl": false, "timeout": 9010, }, "jboss": { "ip_or_dns": "ip", "port": "port", "protocol": "SSL", "ssl": true, "timeout": 600, }, "jboss_adm": { "ip_or_dns": "som_other_ip", "port": "rando_number", "protocol": "SSL", "ssl": true, "timeout": 86410, } }
优化后解决方案
无需额外任务或自定义模块,直接调整原管道逻辑即可:
env_loadbalancer_vservers2: "{{ hostvars[inventory_hostname] | dict2items | selectattr('key', 'match', 'env_.*_loadbalancer_vservers(?![_.])') | map(attribute='value') | combine }}"
调整说明
- 移除原管道中冗余的
list | items2dict步骤 - 新增
map(attribute='value'):提取所有匹配到的变量对应的内层字典值 - 新增
combine:将所有提取到的内层字典合并为一个顶层字典
如果存在重复键需要自定义合并策略,可以调整combine参数,例如递归合并使用combine(recursive=True),列表合并可添加list_merge参数配置策略。
内容的提问来源于stack exchange,提问作者Martin Tomko
相关产品推荐
相关产品推荐

