在查询中使用 Ansible JMESPath

Usage of Ansible JMESPath in queries

我正在使用以下 JSON 文件:

sample.json:

{
    "lldp_output['gathered']": [
        {
            "mode": "trunk",
            "name": "GigabitEthernet0/0",
            "trunk": {
                "encapsulation": "dot1q"
            }
        },
        {
            "access": {
                "vlan": 12
            },
            "mode": "access",
            "name": "GigabitEthernet0/1"
        },
        {
            "name": "GigabitEthernet0/2"
        }
    ]
}

剧本:

---
- hosts: localhost
  gather_facts: no
  vars:
    tmpdata: "{{ lookup('file','sample.json') | from_json }}"

  tasks:
    - name: Take 4
      debug:
        msg: "{{ tmpdata | community.general.json_query(lldp_output['gathered']) }}"

我收到以下错误:

TASK [Take 4] ********************************************************************************************
task path: /root/scripts/atest.yml:18
fatal: [localhost]: FAILED! => {
    "msg": "Error in jmespath.search in json_query filter plugin:\n'lldp_output' is undefined"
}

如何查询显示的 JSON 以便获得具有 mode: trunk

的所有端口的列表

当我 运行 在剧本中时:

---
- name: Find trunk ports
  hosts: ios

  tasks:
    - name: Collect interface output
      cisco.ios.ios_l2_interfaces:
        config:
        state: gathered
      register:
         "intf_output"

    - debug:
        var=intf_output

    - name: Take 4
      debug:
        msg: "{{ intf_output | json_query(query) }}"
      vars:
        query: >-
          "lldp_output['gathered']"[?mode=='trunk']

返回的结构如下:

{
    "intf_output": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python3"
        },
        "changed": false,
        "failed": false,
        "gathered": [
            {
                "name": "GigabitEthernet0/0"
            },
            {
                "mode": "trunk",
                "name": "GigabitEthernet0/1",
                "trunk": {
                    "allowed_vlans": [
                        "10",
                        "20",
                        "30",
                        "100"
                    ],
                    "encapsulation": "dot1q"
                }
            },
            {
                "mode": "trunk",
                "name": "GigabitEthernet0/2",
                "trunk": {
                    "allowed_vlans": [
                        "10",
                        "20",
                        "30",
                        "100"
                    ],
                    "encapsulation": "dot1q"
                }
            },
            {
                "mode": "trunk",
                "name": "GigabitEthernet0/3",
                "trunk": {
                    "allowed_vlans": [
                        "10",
                        "20",
                        "30",
                        "100"
                    ],
                    "encapsulation": "dot1q"
                }
            },
            {
                "mode": "trunk",
                "name": "GigabitEthernet1/0",
                "trunk": {
                    "allowed_vlans": [
                        "10",
                        "20",
                        "30",
                        "100"
                    ],
                    "encapsulation": "dot1q"
                }
            },
            {
                "mode": "trunk",
                "name": "GigabitEthernet1/1",
                "trunk": {
                    "allowed_vlans": [
                        "10",
                        "20",
                        "30",
                        "100"
                    ],
                    "encapsulation": "dot1q"
                }
            },
            {
                "name": "GigabitEthernet1/2"
            },
            {
                "name": "GigabitEthernet1/3"
            },
            {
                "name": "GigabitEthernet2/0"
            },
            {
                "name": "GigabitEthernet2/1"
            },
            {
                "name": "GigabitEthernet2/2"
            },
            {
                "name": "GigabitEthernet2/3"
            },
            {
                "name": "GigabitEthernet3/0"
            },
            {
                "name": "GigabitEthernet3/1"
            },
            {
                "name": "GigabitEthernet3/2"
            },
            {
                "name": "GigabitEthernet3/3"
            }
        ]
    }
}

对于每个主机,我 运行 反对剧本。

json_query 的参数必须是字符串。因为你没有引用你的论点,Ansible 正在寻找一个名为 lldp_output 的变量。但是你有额外的问题,因为你试图访问一个名为 lldp_output['gathered'] 的键,但是 [ 在 JSON (和 JMESPath 查询)中是一个语法上重要的字符,所以需要也要逃脱。

为了避免各种引用转义扭曲,我们可以将查询本身放入一个变量中,这样我们就有:

- hosts: localhost
  vars:
    tmpdata: "{{ lookup('file','sample.json') | from_json }}"

  tasks:
    - name: Take 4
      debug:
        msg: "{{ tmpdata | json_query(query) }}"
      vars:
        query: >-
          "lldp_output['gathered']"

请注意,我们使用的是 >- 块引号运算符,这意味着 query 的值是文字字符串 "lldp_output['gathered']",包括外部引号。

剧本输出:

TASK [Take 4] *********************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "mode": "trunk",
            "name": "GigabitEthernet0/0",
            "trunk": {
                "encapsulation": "dot1q"
            }
        },
        {
            "access": {
                "vlan": 12
            },
            "mode": "access",
            "name": "GigabitEthernet0/1"
        },
        {
            "name": "GigabitEthernet0/2"
        }
    ]
}

要获得 mode 等于 trunk 的那些系统,只需添加 您的查询条件:

- hosts: localhost
  vars:
    tmpdata: "{{ lookup('file','sample.json') | from_json }}"

  tasks:
    - name: Take 4
      debug:
        msg: "{{ tmpdata | json_query(query) }}"
      vars:
        query: >-
          "lldp_output['gathered']"[?mode=='trunk']

这将输出:

TASK [Take 4] *********************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "mode": "trunk",
            "name": "GigabitEthernet0/0",
            "trunk": {
                "encapsulation": "dot1q"
            }
        }
    ]
}

更新

鉴于您在更新后的问题中显示的数据,事情很多 更简单,因为你没有你在 原来的问题。使用如图所示定义的 intf_output,您可以 写:

  tasks:
    - name: Take 4
      debug:
        msg: "{{ intf_output | json_query(query) }}"
      vars:
        query: >-
          gathered[?mode=='trunk']