ansible json-query trying to select "id" 通过内容文件通配符

ansible json-query trying to select "id" by content file wildcard

对 JSON 很陌生。
我正在尝试从此 json 文件中提取 2 个变量。 它有很多文件和 ID,但我只想要包含 es7.x86_64

的文件和 ID

完成后我想要的变量将是:

id=13140

file=NessusAgent-8.3.0-es7.x86_64.rpm

{
    "banners": [],
    "containsRequiredAuth": true,
    "created_at": "2017-10-13T00:53:32.137Z",
    "description": "Download Nessus Agents for use with Tenable.io and Nessus Manager",
    "documentation_link": null,
    "downloads": [
        {
            "created_at": "2021-06-29T19:06:41.776Z",
            "description": "Red Hat ES 7 (64-bit) / CentOS 7 / Oracle Linux 7 (including Unbreakable Enterprise Kernel)",
            "file": "NessusAgent-8.3.0-es7.x86_64.rpm",
            "id": 13140,
            "meta_data": {
                "md5": "f67a2bdd2a7180f66b75f319439d56d5",
                "product": "Nessus Agents - 8.3.0",
                "product_notes": null,
                "product_release_date": "06/29/2021",
                "product_type": "default",
                "release_date": "06/03/2021",
                "sha256": "8a6452086ce0a7193e0f24b1f2adbff3aa6bd0f4ac519384e8453bb68bae0460",
                "version": "8.3.0"
            },
            "name": "NessusAgent-8.3.0-es7.x86_64.rpm",
            "page_id": 61,
            "publish": true,
            "required_auth": false,
            "size": 16375828,
            "sort_order": null,
            "type": "download",
            "updated_at": "2021-06-29T19:08:47.628Z"
        },

我尝试分配具有 es7 的文件和 id 变量完全失败。x86_64。

  - name: Convert agent_tempfile to json and register result
    shell: python -m json.tool "{{ agent_tempfile }}"
    register: result

  - name: Extract file & id for es7.x86_64 rpm's
    set_fact:
      agent_id: "{{ result | json_query('downloads[*es7.x86_64*].id') | first }}"
      agent_file: "{{ result | json_query('downloads[*es7.x86_64*].file') | first }}"

我有一种感觉,我很快就会进行更多此类查询。有人还可以指导我找到一份详细说明从 JSON 输出中解析特定值的指南吗?到目前为止我发现的东西只是列出了数组,但我真的很想知道如何提取特定数据。

首先,有一些很棒的工具可以玩转 JMESPath 语法(json_query 过滤器使用的语法)。 JMESPath tutorial 中的示例都是“实时”的:您可以将自己的数据粘贴到文本字段中,然后试验过滤器并检查结果。

jpterm 命令是用于试验 JMESPath 查询的终端工具。这是我个人的最爱。


要查找包含特定子字符串(如 es7.x86_64)的项目,您可以使用 contains 运算符,如下所示:

json_query("downloads[?contains(name, 'es7.x86_64')]")

为了使您的代码能够正常工作,我们首先需要处理以下事实 你的第一个任务的结果将是一个字符串,而不是 比字典。我们需要通过 from_json 过滤器。

我们也可以避免出现两个几乎相同的json_query表达式 通过将大部分表达式移动到任务局部变量中。

这给了我们类似的东西:

- hosts: localhost
  gather_facts: false
  tasks:
    - command: cat data.json
      register: result

    - set_fact:
        agent_id: "{{ selected[0].id }}"
        agent_file: "{{ selected[0].file }}"
      vars:
        selected: >-
          {{
            result.stdout |
            from_json |
            json_query("downloads[?contains(name, 'es7.x86_64')]")
          }}

    - debug:
        msg:
          - "ID: {{ agent_id }}"
          - "FILE: {{ agent_file }}"

当该任务运行时,selected 的值将类似于:

[
  {
    "file": "NessusAgent-8.3.0-es7.x86_64.rpm",
    "id": 13140,
    "name": "NessusAgent-8.3.0-es7.x86_64.rpm",
    "page_id": 61,
    "publish": true,
    "required_auth": false,
    "size": 16375828,
    "sort_order": null,
    "type": "download",
    "updated_at": "2021-06-29T19:08:47.628Z"
  }
]

这假设您只期待一个结果,所以我们可以问 for selected[0] 得到那本字典,然后就很简单了 获取 .id.file 属性的问题。

运行 上面的剧本产生:

TASK [debug] *********************************************************************************
ok: [localhost] => {
    "msg": [
        "ID: 13140",
        "FILE: NessusAgent-8.3.0-es7.x86_64.rpm"
    ]
}