如何在Ansible中访问数组内部对象内的键/对值?

时间:2020-05-29 15:38:35

标签: json ansible

因此,我们希望将登录用户列表传播到主机。 我们有一个批处理脚本,可以为我们执行此操作并将其解析为JSON格式。

plt.subplot(5,4,1) 
plt.imshow(xtrain[rand20[0]])

此调试输出以下内容:

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

    - debug:
        var: qusers
        verbosity: 2

因此您可以看到debug以服务器名称作为根元素返回JSON,然后返回具有键/对值的对象数组。 我们需要能够查询这些数组对象中的值,例如每个服务器的“ USERNAME”和“ IDLE TIME”。我已经能够静态地做到这一点(如下所示)来抓住第一个数组对象的用户,但是我不知道如何动态地做到这一点。

{
    "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
}

最后一次播放是我唯一一次能够达到特定键/对元素的机会。我该如何修改它以动态地对数组中的每个用户会话对象执行此操作,而不仅是第一个,并且没有硬编码数字?

1 个答案:

答案 0 :(得分:1)

我无法轻松地在三个主机上重现您的播放循环,因此我用您的示例数据和提示进行了演示,允许您选择要显示的主机。当然,当您在当前的剧本中予以废除时,将直接由您负责。

想法是:

  1. 就像使用dict2items一样将字典转换为列表(与您使用的dict查找相同)。
  2. 仅抓住列表的第一项,因为这是您的数据模型
  3. 将项目的密钥作为当前要显示的服务器的名称
  4. 抓住项目的值并遍历它,因为它是我们的用户列表
  5. 显示我们所需的信息,而无需担心列表是否为空。空列表意味着空循环,因此在这种情况下将不会发生任何事情。

在我的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