Marc
Marc

Reputation: 89

Multiple conditions in JMESPath query does not give any results

I am trying to query the following Infoblox data with Ansible and JMESPath json_query:

{
    "ip_records.json": {
        "result": [
            {
                "_ref": "fixedaddress/blabla",
                "ipv4addr": "10.10.10.10",
                "network_view": "Bla"
            },
            {
                "_ref": "record:host/blabla",
                "ipv4addrs": [
                    {
                        "_ref": "record:host_ipv4addr/blabla",
                        "host": "bla.bla.com",
                        "ipv4addr": "10.10.10.10"
                    }
                ],
                "name": "bla.bla.com",
                "view": " "
            },
            {
                "_ref": "record:a/blabla",
                "ipv4addr": "10.10.10.10",
                "name": "bla.bla.com",
                "view": "bla"
            }
        ]
    }
}

I want to get only the _ref value for the item with fixedaddress in the _ref value.

Forgot to add that there might also be multiple records with fixedaddress but different IP's. So I also want to filter on a specific IP as the same time.

I have created queries to filter

The first two work as expected. But, I want to combine both conditions and would expect to get the single item as output, but I get nothing. I tried using && and | to combine both, as showed below.

- name: "Search IP Record: Task 2.2: Filter Results."
  vars:
    jmesquery: "[] | [?ipv4addr==`{{ infoblox_ip }}`]._ref"
  set_fact:
    ip_records_refs: "{{ ip_records.json.result | json_query(jmesquery) }}"

- name: "Search IP Record: Task 2.4: Filter Results."
  vars:
    jmesquery: "[] | [?_ref.contains(@,`fixedaddress`)]._ref"
  set_fact:
    ip_records_refs: "{{ ip_records.json.result | to_json | from_json | json_query(jmesquery) }}"

- name: "Search IP Record: Task 2.6: Filter Results."
  vars:
    # jmesquery: "[] | ([?ipv4addr==`{{ infoblox_ip }}` && _ref.contains(@,`fixedaddress`)])._ref"
    jmesquery: "[] | [?ipv4addr==`{{ infoblox_ip }}`].ref | [?_ref.contains(@,`fixedaddress`)]._ref"
  set_fact:
    ip_records_refs: "{{ ip_records.json.result | to_json | from_json | json_query(jmesquery) }}"

Output:

TASK [Search IP Record: Task 2.3 Dump variable Content] ***********
ok: [localhost] => {
    "ip_records_refs": [
        "fixedaddress/blabla",
        "record:a/blabla"
    ]
}

TASK [Search IP Record: Task 2.5 Dump variable Content] ***********
ok: [localhost] => {
    "ip_records_refs": [
        "fixedaddress/blabla"
    ]
}

TASK [Search IP Record: Task 2.7 Dump variable Content] ***********
ok: [localhost] => {
    "ip_records_refs": []
}

Upvotes: 1

Views: 1321

Answers (2)

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

Reputation: 39079

You are misusing the pipe expression.

From your trial, it is hard to tell exactly what you think it does, but here is a simple explanation: you might not see it, but a JMESPath filter on an array does not return you a JSON array, rather it returns you a projection.
You cannot chain a filter on top of projection, you need to reset it first, in order to get the resulting JSON array, and this is what the pipe expression is meant for.

In your case, you do not want to have a filter on top of a projection, you want a filter with multiple conditions, so, your last set_fact query should read:

jmesquery: >-
  [?
    _ref.contains(@,`fixedaddress`) 
    && ipv4addr == `{{ infoblox_ip }}`
  ]._ref

And your two first queries should be simplified to:

jmesquery: "[?_ref.contains(@,`fixedaddress`)]._ref"

and

jmesquery: "[?ipv4addr == `{{ infoblox_ip }}`]._ref"

Upvotes: 1

Vladimir Botka
Vladimir Botka

Reputation: 67984

Q: "Get _ref value for the item with 'fixedaddress' in the _ref key."

A: The query below

  jmesquery: "[?_ref.contains(@,`fixedaddress`)]._ref"
  ip_records_refs: "{{ ip_records.json.result|json_query(jmesquery) }}"

gives the expected result

  ip_records_refs:
  - fixedaddress/blabla

Example of a complete playbook for testing

- hosts: localhost

  vars:

    ip_records:
      json:
        result:
        - _ref: fixedaddress/blabla
          ipv4addr: 10.10.10.10
          network_view: Bla
        - _ref: record:host/blabla
          ipv4addrs:
          - _ref: record:host_ipv4addr/blabla
            host: bla.bla.com
            ipv4addr: 10.10.10.10
          name: bla.bla.com
          view: ' '
        - _ref: record:a/blabla
          ipv4addr: 10.10.10.10
          name: bla.bla.com
          view: bla

    # Get _ref value for the item with 'fixedaddress' in the _ref key
    jmesquery: "[?_ref.contains(@,`fixedaddress`)]._ref"
    ip_records_refs: "{{ ip_records.json.result|json_query(jmesquery) }}"
    
  tasks:

    - debug:
        var: ip_records
    - debug:
        var: ip_records_refs

Upvotes: 0

Related Questions