Как получить доступ к значениям ключа / пары внутри объектов внутри массива в Ansible? - PullRequest
1 голос
/ 29 мая 2020

Итак, мы хотим распространить список авторизованных пользователей на наши хосты. У нас есть пакетный скрипт, который делает это за нас и преобразует его в формат JSON.

    - name: Process win_shell output
      set_fact:
        qusers: "{{ qusers_ps.stdout | from_json }}"

    - debug:
        var: qusers
        verbosity: 2

Эта отладка выводит следующее:

{
    "qusers": {
        "Server1": []
    },
    "_ansible_verbose_always": true,
    "_ansible_no_log": false,
    "changed": false
}
{
    "qusers": {
        "Server2": [
            {
                "USERNAME": "user102",
                "SESSIONNAME": "rdp-tcp#0",
                "ID": "6",
                "STATE": "Active",
                "IDLE TIME": "32",
                "LOGON TIME": "5/29/2020 9:13 AM"
            }
        ]
    },
    "_ansible_verbose_always": true,
    "_ansible_no_log": false,
    "changed": false
}
{
    "qusers": {
        "Server3": [
            {
                "USERNAME": "user183",
                "SESSIONNAME": "",
                "ID": "49",
                "STATE": "Disc",
                "IDLE TIME": "14:34",
                "LOGON TIME": "5/28/2020 7:58 AM"
            },
            {
                "USERNAME": "user103",
                "SESSIONNAME": "",
                "ID": "51",
                "STATE": "Disc",
                "IDLE TIME": "18:26",
                "LOGON TIME": "5/28/2020 8:18 AM"
            },
            {
                "USERNAME": "user148",
                "SESSIONNAME": "",
                "ID": "52",
                "STATE": "Disc",
                "IDLE TIME": "17:10",
                "LOGON TIME": "5/28/2020 9:08 AM"
            }
        ]
    },
    "_ansible_verbose_always": true,
    "_ansible_no_log": false,
    "changed": false
}

Итак, вы можете видеть, что отладка возвращает JSON с именем сервера в качестве элемента root, а затем массивом объекты со значениями ключ / пара. Нам необходимо иметь возможность запрашивать значения в этих объектах массива, такие как «USERNAME» и «IDLE TIME» для каждого сервера. Мне удалось сделать это статически (показано ниже), чтобы захватить пользователя первого объекта массива, но я не могу понять, как это сделать динамически.

    - name: Test selecting JSON output and register as array
      debug:
        msg: "{{ item.value }}"
      loop: "{{ q('dict', qusers) }}"
      register: user_op

    - name: Set array variable
      set_fact:
        user_array: "{{ user_op.results }}"

    - name: Print item value # Prints array object as is
      debug:
        msg: "{{ item.item.value }} "
      with_items: "{{ user_array }}"

    - name: Test pulling JSON from array with conditional # This one works, but only grabs the first user
      debug: 
        msg: "{{ item.item.value[0]['USERNAME'] }} is logged into {{item.item.key }}"
      with_items: "{{ user_array }}"
      when: item.item.value != [] 

Последняя игра - это единственный раз, когда мне удавалось достичь определенного c элемента ключа / пары. Как мне изменить это, чтобы динамически выполнять эту операцию для каждого объекта сеанса пользователя в массиве, а не только для первого, и без номеров жесткого кодирования ??

1 Ответ

1 голос
/ 29 мая 2020

Я не могу легко воспроизвести вашу игру l oop на ваших трех хостах, поэтому я сделал демонстрацию с данными вашего примера и подсказкой, позволяющей выбрать, какой хост отображать. Конечно, это возьмет на себя ответственность непосредственно за вас, когда вы воспроизведете это в своей текущей playbook.

Идея состоит в том, чтобы:

  1. преобразовать dict в список, как вы уже сделали используя dict2items (тот же результат, что и при поиске dict, который вы использовали).
  2. захватите только первый элемент списка, поскольку это ваша модель данных
  3. захватите ключ элемента как имя текущего сервера для отображения
  4. захватить значение элемента и l oop поверх него, поскольку это наш список пользователей
  5. отобразить нужную нам информацию, даже не заботясь о список пуст или нет. Пустой список означает пустой l oop, поэтому в этом случае ничего не произойдет.

Ниже моего MCVE и игра для третьего элемента. Вы можете сыграть себя за других. Как видите, это может поместиться в одну задачу после того, как вы загрузили информацию из своего json вывода.

---
- hosts: localhost
  gather_facts: false

  vars_prompt:
    - name: host
      prompt: "display host ? (1-3)"
      private: no
      default: 1

  vars:
    "qusers1": {
      "Server1": []
    }
    "qusers2": {
      "Server2": [
        {
          "USERNAME": "user102",
          "SESSIONNAME": "rdp-tcp#0",
          "ID": "6",
          "STATE": "Active",
          "IDLE TIME": "32",
          "LOGON TIME": "5/29/2020 9:13 AM"
        }
      ]
    }
    "qusers3": {
      "Server3": [
      {
        "USERNAME": "user183",
        "SESSIONNAME": "",
        "ID": "49",
        "STATE": "Disc",
        "IDLE TIME": "14:34",
        "LOGON TIME": "5/28/2020 7:58 AM"
      },
      {
        "USERNAME": "user103",
        "SESSIONNAME": "",
        "ID": "51",
        "STATE": "Disc",
        "IDLE TIME": "18:26",
        "LOGON TIME": "5/28/2020 8:18 AM"
      },
      {
        "USERNAME": "user148",
        "SESSIONNAME": "",
        "ID": "52",
        "STATE": "Disc",
        "IDLE TIME": "17:10",
        "LOGON TIME": "5/28/2020 9:08 AM"
      }
      ]
    }

  tasks:
    - name: Load the relevent host data for demo to be in same condition as in original play
      set_fact:
        qusers: "{{ lookup('vars', 'qusers' +  host) }}"

    - name: Show info about users
      vars:
        host_users_info: "{{ (qusers | dict2items).0 }}"
        servername: "{{ host_users_info.key }}"
        loguedin_users: "{{ host_users_info.value }}"
      debug:
        msg: "{{ item.USERNAME }} is logged into {{ servername }} and is idle for {{ item['IDLE TIME'] }}"
      loop: "{{ loguedin_users }}"

Что дает для элемента 3

$ ansible-playbook test.yml 
display host ? (1-3) [1]: 3

PLAY [localhost] ************************************************************************************************************************************

TASK [Load the relevent host data for demo to be in same condition as in original play] *************************************************************
ok: [localhost]

TASK [Show info about users] ************************************************************************************************************************
ok: [localhost] => (item={'USERNAME': 'user183', 'SESSIONNAME': '', 'ID': '49', 'STATE': 'Disc', 'IDLE TIME': '14:34', 'LOGON TIME': '5/28/2020 7:58 AM'}) => {
    "msg": "user183 is logged into Server3 and is idle for 14:34"
}
ok: [localhost] => (item={'USERNAME': 'user103', 'SESSIONNAME': '', 'ID': '51', 'STATE': 'Disc', 'IDLE TIME': '18:26', 'LOGON TIME': '5/28/2020 8:18 AM'}) => {
    "msg": "user103 is logged into Server3 and is idle for 18:26"
}
ok: [localhost] => (item={'USERNAME': 'user148', 'SESSIONNAME': '', 'ID': '52', 'STATE': 'Disc', 'IDLE TIME': '17:10', 'LOGON TIME': '5/28/2020 9:08 AM'}) => {
    "msg": "user148 is logged into Server3 and is idle for 17:10"
}

PLAY RECAP ******************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...