如何在Ansible中用ID与DB组合作为combine的字典键避免重复覆盖?
问题:Ansible中构建含ID+DB组合键的字典以避免重复键覆盖
原始YAML数据结构
crdb: db: - test users: - id: 42712 permissions: - level: ALL db: test
当前实现及存在的问题
目前使用以下代码构建字典:
- set_fact: db_user_permissions: "{{ db_user_permissions | default ({}) | combine({ item.key: item.value }) }}" loop: "{{ crdb.users | json_query('[*].{key: id, value: permissions}') }}" when: item.value
生成的输出示例:
{"db_user_permissions": {"42712": [{"db": "test", "level": "ALL"}], "42699": [{"db": "test", "level": "ALL"}]}}
但当存在重复ID时,字典中只会保留最后一个对应条目,因为字典的键是唯一的用户ID。
尝试过的错误写法
以下几种尝试均无法正确生成ID+DB的组合键:
- 错误拼接键名:
- set_fact: db_user_permissions: "{{ db_user_permissions | default ({}) | combine({ item.key_item.value[0].db : item.value }) }}" loop: "{{ crdb.users | json_query('[*].{key: id, value: permissions}') }}" when: item.value
- 错误嵌套Jinja2表达式:
- set_fact: db_user_permissions: "{{ db_user_permissions | default ({}) | combine({ {{ item.key }}_{{ item.value[0].db }} : item.value }) }}" loop: "{{ crdb.users | json_query('[*].{key: id, value: permissions}') }}" when: item.value
- 错误的字符串拼接语法:
- set_fact: db_user_permissions: "{{ db_user_permissions | default ({}) | combine({ item.key'_'item.value[0].db : item.value }) }}" loop: "{{ crdb.users | json_query('[*].{key: id, value: permissions}') }}" when: item.value
正确实现方式
方法1:在json_query中直接生成组合键
如果每个用户的permissions列表中只有一个数据库权限,可以直接在json_query里拼接ID和DB作为键:
- set_fact: db_user_permissions: "{{ db_user_permissions | default({}) | combine({ item.key: item.value }) }}" loop: "{{ crdb.users | json_query('[*].{key: id + \"_\" + permissions[0].db, value: permissions}') }}" when: item.value
这里通过id + "_" + permissions[0].db在json_query中直接生成ID_DB格式的组合键,避免重复键冲突。
方法2:处理多数据库权限场景
如果用户可能有多个数据库权限,需要将每个权限条目单独作为字典的一项,此时可以用subelements展开permissions列表:
- set_fact: db_user_permissions: "{{ db_user_permissions | default({}) | combine({ item_key: [item_perm] }) }}" loop: "{{ crdb.users | subelements('permissions') }}" vars: item_key: "{{ item.0.id }}_{{ item.1.db }}" item_perm: "{{ item.1 }}"
这种方式会将每个用户的每条权限单独生成一个ID_DB键,确保所有权限都被保留。
关键说明
Jinja2中字符串拼接需要用~运算符或者字符串格式化,不能直接在字典键的位置嵌套{{}},也不能用无运算符的直接拼接。上述方法通过正确的字符串拼接生成唯一键,解决了重复ID覆盖的问题。
内容的提问来源于stack exchange,提问作者CJW
相关产品推荐
相关产品推荐

