Search code examples
ansiblejmespath

JMESPath filtering on response


I try to filter to get lldp-remote-system-name when lldp-remote-system-name contains slc1.

But I get the error:

Error in jmespath.search in json_query filter plugin:\n'in ' requires string as left operand, not NoneType

Tasks:

- name: get system information
  juniper_junos_rpc:
    rpc: get-lldp-neighbors-information
  register: response

- name: Get remote system name
  set_fact:
    lldp_interface: "{{ response.parsed_output | to_json | from_json | json_query(interface) }}"
  vars:
    interface: '"lldp-neighbors-information"."lldp-neighbor-information"[?contains("lldp-remote-system-name","slc1")]."lldp-remote-system-name"'

- name: Print response
  debug:
    msg: 
        - "{{ lldp_interface }}"

Response

{
    "lldp-neighbors-information": {
        "lldp-neighbor-information": [
            {
                "lldp-local-parent-interface-name": "ae1",
                "lldp-local-port-id": "et-0/0/50",
                "lldp-remote-chassis-id": "22:22:22:22:22:22",
                "lldp-remote-chassis-id-subtype": "Mac address",
                "lldp-remote-port-description": "las1-router-1:et-0/0/50",
                "lldp-remote-system-name": "las1-router-1"
            },
            {
                "lldp-local-parent-interface-name": "ae0",
                "lldp-local-port-id": "xe-0/0/1",
                "lldp-remote-chassis-id": "11:11:11:11:11:11",
                "lldp-remote-chassis-id-subtype": "Mac address",
                "lldp-remote-port-description": "slc1-router-1-xe-0/0/1",
                "lldp-remote-system-name": "slc1-router-1"
            }
        ]
    }
}

Solution

  • In JMESPath, double quotes are not string delimiters, they serve a specific purpose: they delimit an identifier that have special characters:

    An identifier can also be quoted. This is necessary when an identifier has characters not specified in the unquoted-string grammar rule. In this situation, an identifier is specified with a double quote, followed by any number of unescaped-char or escaped-char characters, followed by a double quote.

    Source: https://jmespath.org/specification.html#identifiers

    If you want to have a raw string littoral, use back ticks instead: `.

    So, your JMESPath query should be — split on multiple lines to make it more readable:

    interface: >-
      "lldp-neighbors-information"
      ."lldp-neighbor-information"[?
        contains("lldp-remote-system-name",`slc1`)
      ]
      ."lldp-remote-system-name"
    

    Given the task:

    - debug:
        msg: "{{ json | json_query(interface) }}"
      vars:
        interface: >-
          "lldp-neighbors-information"
          ."lldp-neighbor-information"[?
            contains("lldp-remote-system-name",`slc1`)
          ]
          ."lldp-remote-system-name"
        json:
          lldp-neighbors-information:
            lldp-neighbor-information:
              - lldp-local-parent-interface-name: ae1
                lldp-local-port-id: et-0/0/50
                lldp-remote-chassis-id: 22:22:22:22:22:22
                lldp-remote-chassis-id-subtype: Mac address
                lldp-remote-port-description: las1-router-1:et-0/0/50
                lldp-remote-system-name: las1-router-1
              - lldp-local-parent-interface-name: ae0
                lldp-local-port-id: xe-0/0/1
                lldp-remote-chassis-id: 11:11:11:11:11:11
                lldp-remote-chassis-id-subtype: Mac address
                lldp-remote-port-description: slc1-router-1-xe-0/0/1
                lldp-remote-system-name: slc1-router-1
    

    This yields:

    ok: [localhost] => 
      msg:
      - slc1-router-1