Reputation: 89
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
fixedaddress
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
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
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