Ansible,如何查询深度嵌套的 json 键 [英] Ansible, how to query deeply nested json keys

查看:36
本文介绍了Ansible,如何查询深度嵌套的 json 键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Ansible 进行 API 调用,该调用返回大量数据集,并且我需要能够获取嵌套值以打印到屏幕上.我尝试使用 json_query 但不确定我做错了什么.

I'm using Ansible to make an API call that returns a huge data set, and I need to be able to get a nested value to print to the screen. I tried using json_query but not sure what I'm doing wrong.

我的任务:

- name: Get certificate by CN name.
      uri:
        method: GET
        url: "https://mayapi/api/1/certificates?filter=cn;{{ inventory_hostname }}"
        headers:
          Authorization: Bearer {{ login.json.token }}
          Content-Type: application/json
        validate_certs: no
      register: certs
      
- name: Print certs for application 
  debug:
    msg: "{{ certs.json | json_query(items) }}"

这是输出的一小段.我希望能够打印 ID 和电子邮件.

This is a small snippet of the output. I want to be able to print ID, and email.

{
    "msg": {
        "changed": false,
        "connection": "close",
        "content_length": "65833",
        "content_type": "application/json",
        "cookies": {},
        "cookies_string": "",
        "date": "Mon, 10 May 2021 21:33:29 GMT",
        "elapsed": 0,
        "failed": false,
        "json": {
            "items": [
                {
                    "active": true,
                    "application": [
                        {
                            "director": {
                                "active": true,
                                "email": "user@domain.com",
                                "fullname": "John Doe",
                                "id": 1611,
                                "manager": "John Doe",
                                "managerEmail": "johndoe@email.com",
                                "username": "jdoe"
                            },
                            ...
                            ...
                            ...
}

我收到以下错误,指示certs.items";不存在:

I get the following error indicating "certs.items" doesn't exist:

FAILED! => {"msg": "Error in jmespath.search in json_query filter plugin:\n'items' is undefined"}

我希望所有项目都打印到屏幕上,然后如果我想要项目下方的某些内容,我会执行 items.active、items.application 等...但这不正确,因为我不断出错.

I was expecting all of the items to get printed to the screen and then if I wanted something below items I would do items.active, items.application, etc... But this is not correct since I keep erroring out.

我也尝试通过 cert.json 和 cert.json.items 循环:

I also tried looping through cert.json and cert.json.items:

- name: Print certs for application 
    debug:
      msg: "{{ item.application.name }}"
    loop: "{{ certs.json}}"

但收到此错误消息:

{"msg": "Invalid data passed to 'loop', it requires a list, got this instead: {u'items': [{u'status': u'Active-Pending Install'...shows all the data of the nested json

然后我尝试了这个:

- name: Print certs for application 
    debug:
      msg: "{{ item.application.name }}"
    loop: "{{ certs.json.items}}"

但收到此错误消息:

{"msg": "Invalid data passed to 'loop', it requires a list, got this instead: <built-in method items of dict object at 0x7f0c9ec43050>. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."}

在这方面取得了一些进展:

Made some progress with this:

- name: Print certs for application 
    debug:
      msg: "KEY:::: {{ item.key }}, VALUE:::: {{ item.value.0 }}"
    loop: "{{ lookup('dict', certs.json) }}"
    when: "'items' in item.key"
    ignore_errors: yes

但这只会打印列表索引 0 中的项目:

But this only prints items in index 0 of the list:

"msg": "KEY:::: items, VALUE:::: {u'status': u'Active-Pending Install', u'serialHex': u'1111', u'validityStart': u'2021-05-10T21:01:36+00:00', u'cn': u'node2.test.corp.net', u'validityEnd': u'2023-05-10T21:11:36+00:00', u'application': [{u'uuid': u'2222', u'name': u'abc'}], u'certType': u'CertType.INTERNAL', u'id': 2582, u'issuer': u'server1'}"

我正在尝试为键items"打印每个列表元素的cn"、id"和serialHex"值.

I'm trying to print the 'cn', 'id', and 'serialHex' values from each list element for the key 'items'.

这是我尝试使用 Ansible 查询的数据集:

This is the data set that I'm trying to query with Ansible:

{
    "total": 2,
    "items": [
        {
            "application": [
                {
                    "uuid": "111",
                    "name": "CDE"
                }
            ],
            "validityEnd": "2023-05-10T21:11:36+00:00",
            "certType": "CertType.INTERNAL",
            "issuer": "server1",
            "id": 2582,
            "validityStart": "2021-05-10T21:01:36+00:00",
            "status": "Active-Pending Install",
            "serialHex": "aaa",
            "cn": "node2.corp.net"
        },
        {
            "application": [
                {
                    "uuid": "222",
                    "name": "CDE"
                }
            ],
            "validityEnd": "2023-05-10T21:05:26+00:00",
            "certType": "CertType.INTERNAL",
            "issuer": "server1",
            "id": 2581,
            "validityStart": "2021-05-10T20:55:26+00:00",
            "status": "Active-Pending Install",
            "serialHex": "bbbb",
            "cn": "node1.corp.net"
        }
    ]
}

推荐答案

您很遗憾地遇到了ansible 中的对象是 python dicts"的怪癖;在那个 .items().keys() 以及许多其他属性(即方法)不能使用 . 符号引用,因为 jinja2 认为您打算调用 那个方法.相反,必须使用 ["items"]__getitem__ 语法,以便清楚地表明您指的是 dict 键,而不是相同的方法姓名

You are regrettably stepping on a quirk of "objects in ansible are python dicts" in that .items() and .keys() and quite a few other attributes-which-are-methods cannot be referenced using the . notation since jinja2 believes you intend to call that method. Rather, one must use the __getitem__ syntax of ["items"] in order to make it abundantly clear that you mean the dict key, and not the method of the same name

  tasks:
    - name: use json_query as you were originally asking
      debug:
        msg: >-
          {{ certs.json | json_query('items[*].{c: cn,i: id,s: serialHex}') }}

    - name: or a jinja2 for loop as you separately attempted
      debug:
        msg: >-
          [
          {%- for i in certs.json["items"] -%}
          {{ "" if loop.first else "," }}
          {{ [i.cn, i.id, i.serialHex ]}}
          {%- endfor -%}
          ]

从各自的步骤产生输出:

produces the output from their respective steps:

TASK [debug] ******************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "c": "node2.corp.net",
            "i": 2582,
            "s": "aaa"
        },
        {
            "c": "node1.corp.net",
            "i": 2581,
            "s": "bbbb"
        }
    ]
}

TASK [debug] ******************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        [
            "node2.corp.net",
            2582,
            "aaa"
        ],
        [
            "node1.corp.net",
            2581,
            "bbbb"
        ]
    ]
}

这篇关于Ansible,如何查询深度嵌套的 json 键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆