Search code examples
ansiblejuniperjunos-automation

json_query filter with bug?


I have a situation.

When I try to use json_query filter in ansible-playbook return this error:

{"msg": "Error in jmespath.search in json_query filter plugin:\ninvalid literal for int() with base 10: '-'"}

I solve this with replace ('-','_') filter.

Have I other way to solve this?

complete code here:

---
# tasks file for mpls-lsp

- name: Colete informações do protocolo osfp
  junipernetworks.junos.junos_rpc:
    rpc: get-ospf-neighbor-information
    output: json
  register:
    _data

- name: Aplica as configurações padrão em RT-BRAS.*
  ansible.builtin.debug:
    var: item
  loop: "{{ _data2 | json_query('ospf_neighbor_information[0].ospf_neighbor[*].neighbor_address[0].data') }}"
  vars:
    _data2: "{{ _data.output | replace ('-','_') }}"
  when: "'device_roles_bras' in {{ group_names }}"

Solution

  • TL;DR

    "ospf-neighbor-information"[0]."ospf-neighbor"[*]."neighbor-address"[0].data

    Full Story

    I solve this with replace ('-','_') filter.

    This is actually quite dangerous as this replaces dashes for underscores absolutely everywhere in the input, identifiers and values. But if we now look at your resulting jmespath expression

    json_query('ospf_neighbor_information[0].ospf_neighbor[*].neighbor_address[0].data')

    we can infer that all your identifiers where previously using - as a separator

    In the above expression, you are using unquoted identifiers. If you look at jmespath specification for identifiers, you will see that unquoted ones cannot contain dashes.

    identifier        = unquoted-string / quoted-string
    unquoted-string   = (%x41-5A / %x61-7A / %x5F) *(  ; A-Za-z_
                           %x30-39  /  ; 0-9
                           %x41-5A /  ; A-Z
                           %x5F    /  ; _
                           %x61-7A)   ; a-z
    quoted-string     = quote 1*(unescaped-char / escaped-char) quote
    unescaped-char    = %x20-21 / %x23-5B / %x5D-10FFFF
    escape            = %x5C   ; Back slash: \
    quote             = %x22   ; Double quote: '"'
    escaped-char      = escape (
                           %x22 /          ; "    quotation mark  U+0022
                           %x5C /          ; \    reverse solidus U+005C
                           %x2F /          ; /    solidus         U+002F
                           %x62 /          ; b    backspace       U+0008
                           %x66 /          ; f    form feed       U+000C
                           %x6E /          ; n    line feed       U+000A
                           %x72 /          ; r    carriage return U+000D
                           %x74 /          ; t    tab             U+0009
                           %x75 4HEXDIG )  ; uXXXX                U+XXXX
    

    So if your identifiers contain dashes, you must quote them (and note that quoting identifiers is made with double-quotes)

    You can transform your json_query task as below to make it work on your original data (you might have to adapt as I didn't have your original structure and had to guess a bit...)

    - name: Aplica as configurações padrão em RT-BRAS.*
      ansible.builtin.debug:
        var: item
      loop: "{{ _data.output | json_query(query) }}"
      vars:
        query: >-
          "ospf-neighbor-information"[0]."ospf-neighbor"[*]."neighbor-address"[0].data
      when: "'device_roles_bras' in {{ group_names }}"