netv
netv

Reputation: 185

JMESPathError in json_query filter: Unknown function: regex_search()

Here is my playbook:

- hosts: localhost
  vars:
      {
          "result": [
              {
                  "_ref": "vlan/ZG5zLnZsYW4kLmNvbS5pbmZvYmxveC5kbnMudmxhbl92aWV3JElORlJBTEFCLjEuNDA5NC4xMQ:LAB1/test1/11",
                  "id": 11,
                  "name": "test1",
                  "parent": {
                      "_ref": "vlanview/ZG5zLnZsYW5fdmlldyRJTkZSQUxBQi4xLjQwOTQ:LAB1/1/4094"
                  }
              },
              {
                  "_ref": "vlan/ZG5zLnZsYW4kLmNvbS5pbmZvYmxveC5kbnMudmxhbl92aWV3JFNDTEFCLU9PQi4xLjQwOTQuMTE:LAB2/test1/11",
                  "id": 11,
                  "name": "test1,
                  "parent": {
                      "_ref": "vlanview/ZG5zLnZsYW5fdmlldyRTQ0xBQi1PT0IuMS40MDk0:LAB2/1/4094"
                  }
              }
          ]
      }

  tasks:
     - set_fact: 
            var1: "{{result|json_query(jquery)}}"
       vars:
            jquery: "[].{vlan_view: _ref|regex_search('(?<=:)[^/]*'), vlan_id: id, vlan_name: name}"
     - debug: msg={{var1}}

Which errors with:

fatal: [localhost]: FAILED! => {"msg": "JMESPathError in json_query filter plugin:\nUnknown function: regex_search()"}

My desired output

[
    {
        "vlan_view": LAB1,
        "vlan_id": 11,
        "vlan_name": "test1"
    },
    {
        "vlan_id": 11,
        "vlan_name": "test1",
        "vlan_view": "LAB2"
    }
]

Upvotes: 2

Views: 1154

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68034

Get the attributes vlan_view

vlan_view: "{{ result|map(attribute='_ref')|
                      map('split', ':')|map('last')|
                      map('split', '/')|map('first')|
                      map('community.general.dict_kv', 'vlan_view')|
                      list }}"

gives

vlan_view:
  - vlan_view: LAB1
  - vlan_view: LAB2

Then use json_query to get the other attributes and combine the dictionaries

var1: "{{ result|json_query('[].{vlan_id: id, vlan_name: name}')|
                 zip(vlan_view)|map('combine')|list }}"

gives the expected result

var1:
  - vlan_id: 11
    vlan_name: test1
    vlan_view: LAB1
  - vlan_id: 11
    vlan_name: test1
    vlan_view: LAB2

Example of a complete playbook (simplified for testing)

- hosts: localhost
  
  vars:

    result:
      - _ref: vlan/ZG5z...4xMQ:LAB1/test1/11
        id: 11
        name: test1
        parent:
          _ref: vlanview/ZG5zL...wOTQ:LAB1/1/4094
      - _ref: vlan/ZG5zL...uMTE:LAB2/test1/11
        id: 11
        name: test1
        parent:
          _ref: vlanview/ZG5zL...MDk0:LAB2/1/4094

    vlan_view: "{{ result|map(attribute='_ref')|
                          map('split', ':')|map('last')|
                          map('split', '/')|map('first')|
                          map('community.general.dict_kv', 'vlan_view')|
                          list }}"

    var1: "{{ result|json_query('[].{vlan_id: id, vlan_name: name}')|
                     zip(vlan_view)|map('combine')|list }}"

  tasks:
    - debug:
        var: vlan_view
    - debug:
        var: var1

Upvotes: 1

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39129

You cannot do regex operation in JMESPath, as per this issue on their tracker.

And you surely cannot use a Jinja filter as a JMESPath function, as the error is pointing out.

So, you will have to achieve this with Jinja filters and Ansible alone.
And with a loop, it is definitely possible to create a list corresponding to your desired output:

- set_fact:
    var1: "{{ var1 | default([]) + [_vlan] }}"
  loop: "{{ result }}"
  loop_control:
    label: "{{ item.id }}"
  vars:
    _vlan:
      vlan_id: "{{ item.name }}"
      vlan_name: "{{ item.id }}"
      vlan_view: >-
        {{ 
          item.parent._ref 
          | regex_search(':(.*?)\/', '\1') 
          | first 
        }}

Given the two tasks:

- set_fact:
    var1: "{{ var1 | default([]) + [_vlan] }}"
  loop: "{{ result }}"
  loop_control:
    label: "{{ item.id }}"
  vars:
    _vlan:
      vlan_id: "{{ item.name }}"
      vlan_name: "{{ item.id }}"
      vlan_view: >-
        {{ 
          item.parent._ref 
          | regex_search(':(.*?)\/', '\1') 
          | first 
        }}

- debug:
    var: var1

This will yield:

TASK [set_fact] ***************************************************************
ok: [localhost] => (item=11)
ok: [localhost] => (item=11)

TASK [debug] ******************************************************************
ok: [localhost] => 
  var1:
  - vlan_id: test1
    vlan_name: '11'
    vlan_view: LAB1
  - vlan_id: test1
    vlan_name: '11'
    vlan_view: LAB2

Upvotes: 1

Related Questions