Ansible如何查询任务输出JSON中多类型Members字段匹配用户所属组
问题解决方法
问题根源
查询失效的核心原因是Members字段类型不统一,json_query依赖的JMESPath语法对不同类型的处理逻辑不一致:
- 空字典
{}类型的Members:无任何成员,直接排除即可 - 单字符串类型的Members:
contains(@, 'appsupport')是判断子串存在,不是完整用户名匹配,同时实际数据中用户名带主机前缀WIN-U97DIQUENUM\\,直接用contains要么匹配不到要么会出现误判 - 列表类型的Members:
contains才是判断列表是否包含对应元素,符合预期
json_query('[].Members[*]')返回异常也是因为类型不统一:JMESPath的[*]展开符对字符串、字典、列表的展开规则完全不同,无法得到统一的成员列表。
方案1:先统一Members类型再查询(推荐,可读性高)
先通过Jinja2逻辑把所有Members统一转为列表格式,再筛选包含目标用户的组:
- debug: msg: "{{ processed_groups | selectattr('Members', 'contains', target_user) | map(attribute='Group') | list }}" vars: target_user: "WIN-U97DIQUENUM\\appsupport" # 填完整用户名,若仅匹配后缀可改判断逻辑 raw_groups: "{{ getgroup.stdout | from_json }}" processed_groups: >- {% set res = [] %} {% for item in raw_groups %} {% set member_val = item.Members %} {% if member_val is mapping %} {% set members = [] %} {% elif member_val is string %} {% set members = [member_val] %} {% elif member_val is iterable %} {% set members = member_val %} {% else %} {% set members = [] %} {% endif %} {{ res.append({'Group': item.Group, 'Members': members}) }} {% endfor %} {{ res }}
如果只需要匹配用户名后缀(不需要带主机/域前缀),可以把selectattr的判断改成:
selectattr('Members', 'search', '\\\\appsupport$')
方案2:直接写兼容多类型的JMESPath查询
如果不想预处理数据,也可以直接在json_query中通过类型判断覆盖三种场景:
- debug: msg: "{{ getgroup.stdout | from_json | json_query(guser) }}" vars: # 仅匹配后缀appsupport的写法,需要完全匹配则把ends_with改成==,填完整用户名 guser: >- [? (type(Members) == 'string' && ends_with(Members, '\\appsupport')) || (type(Members) == 'array' && Members[?ends_with(@, '\\appsupport')]) ].Group
空字典类型的Members会自动被上述条件排除,不需要额外判断。
内容的提问来源于stack exchange,提问作者Kokrekan
相关产品推荐
相关产品推荐

