Как l oop над списком JSON в Ansible, отфильтрованным по значениям из отдельного списка? - PullRequest
1 голос
/ 08 апреля 2020

У меня есть список пользовательских словарей, каждый из которых содержит имя пользователя, gecos и т. Д. c, а также список групповых словарей, каждый из которых содержит список членов группы. Мне нужна задача Ansible для l oop только над записями списка пользователей, которые соответствуют списку участников определенной группы c из списка групп.

Я подозреваю, что моя проблема должна делать при правильном использовании цитат и разделителей Jinja, чтобы все оценивалось на должном уровне в иерархии Ansible -> Jinja -> JMESPath, но я не смог точно определить, что я делаю неправильно. Ниже я пробовал десятки вариантов, включая разбиение подзапросов на их собственные переменные, но без значимой обратной связи у меня не так много информации для улучшения.

пользователей. json:

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

групп. 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 l oop):

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

1 Ответ

2 голосов
/ 08 апреля 2020

Если вы действительно не хотите использовать jmespath для этого, существует более простой способ IMO с использованием selectattr:

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

Между тем это все еще возможно с json_query. Вы были очень близки Проблема в вашем промежуточном запросе. Вы передаете переменную aws_user в json_query. Следовательно, в первом значении, которое вы передаете, нет ключа "aws_user" первого уровня. Вы должны удалить его из запроса:

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