温馨提示:本文翻译自stackoverflow.com,查看原文请点击:python - How to loop over a JSON list in Ansible, filtered by values from a separate list?
ansible jinja2 jmespath python

python - 如何在Ansible中循环遍历JSON列表,并按单独列表中的值过滤?

发布于 2020-07-01 13:12:22

我有一个每个包含用户名,gecos等的用户词典列表,以及一个每个包含组成员列表的组词典列表。我需要一个Ansible任务,以仅遍历与列表中特定组的成员列表匹配的用户列表条目。

我怀疑我的问题与正确使用引号和Jinja分隔符有关,以便在Ansible-> Jinja-> JMESPath层次结构中的适当级别上对所有内容进行评估,但是我无法确切确定我在做什么错误地。我在下面尝试了数十种变体,包括将子查询分解为自己的变量,但是没有有意义的反馈,我没有太多信息可以改进。

users.json:

{
  "aws_users": [
    {
      "name": "userA",
      "gecos": "User A"
    },
    {
      "name": "userB",
      "gecos": "User B"
    },
    {
      "name": "userC",
      "gecos": "User C"
    }
  ]
}

groups.json:

{
  "aws_groups": [
    {
      "name": "groupA",
      "members": [
        "userA",
        "userC"
      ]
    }
  ]
}

ansible.yml:

---
- hosts: 127.0.0.1
  become: true
  connection: local
  gather_facts: no
  vars_files:
    - ../../config/groups.json
    - ../../config/users.json

  vars:
     groupARoster: "{{ aws_groups | json_query('[?name==`groupA`].members | [0]') }}"
     query: "aws_users[?contains(`{{ groupARoster }}`, name)]"
     groupAUsers: "{{ aws_users | json_query(query) }}"

  tasks:
    - debug:
        var: groupARoster

    - debug:
        var: query

    - debug:
        var: groupAUsers

#    - name: Some looping thing
#      command: ...
#      loop: "{{ groupAusers }}"

输出:

PLAY [127.0.0.1] ***********************************************************************************************************************************************************************************************

TASK [debug] ***************************************************************************************************************************************************************************************************
ok: [127.0.0.1] => {
    "groupARoster": [
        "userA", 
        "userC"
    ]
}

TASK [debug] ***************************************************************************************************************************************************************************************************
ok: [127.0.0.1] => {
    "query": "aws_users[?contains(`[u'userA', u'userC']`, name)]"
}

TASK [debug] ***************************************************************************************************************************************************************************************************
ok: [127.0.0.1] => {
    "groupAUsers": ""
}

PLAY RECAP *****************************************************************************************************************************************************************************************************
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

所需的输出(用于传递到Ansible循环参数):

"groupAUsers": [
    {
      "name": "userA",
      "gecos": "User A"
    },
    {
      "name": "userC",
      "gecos": "User C"
    }
  ]

查看更多

提问者
Brian Bauman
被浏览
2
Zeitounator 2020-04-08 08:17

除非您真的想为此使用jmespath,否则IMO有一种更简单的方法selectattr

groupARoster: "{{ (aws_groups | selectattr('name', 'equalto', 'groupA') | list)[0].members }}"
groupAUsers: "{{ aws_users | selectattr('name', 'in', groupARoster) | list }}"

同时,使用仍然可以实现json_query你真的很亲近 问题是您的中间查询。您正在将变量传递aws_userjson_query因此,"aws_user"您传递的值中没有第一级密钥。您必须从查询中删除它:

groupARoster: "{{ aws_groups | json_query('[?name==`groupA`].members | [0]') }}"
query: "[?contains(`{{ groupARoster }}`, name)]"
groupAUsers: "{{ aws_users | json_query(query) }}"