How to loop in Ansible over registerd result and selecting specific node? - ansible

i am registering a result from a specific SQL query:
- name: Output Result
debug:
var: result.query_result[0]
I get a long list that looks like this:
{
"result": {
"changed": true,
"failed": false,
"query_result": [
[
{
"C": "",
"CHID": "",
"DESCRIPTION": "",
"EXPECTED_VALUE": "",
"HOST": "",
"SAP_NOTE": "",
"VALUE": ""
},
{
"C": "",
"CHID": "M0005",
"DESCRIPTION": "Generated with",
"EXPECTED_VALUE": "",
"HOST": "",
"SAP_NOTE": "1969700",
"VALUE": "SQL: \\HANA_Configuration_MiniChecks\\\"\""
}
]
],
"rc": 0,
"stderr": "",
"stderr_lines": []
}
}
How can I output only this part if he exists:
{
"C": "",
"CHID": "M0005",
"DESCRIPTION": "Generated with",
"EXPECTED_VALUE": "",
"HOST": "",
"SAP_NOTE": "1969700",
"VALUE": "SQL: \\HANA_Configuration_MiniChecks\\\"\""
}
The location of the above node can change, so i can't specifically target it.

you can use json_query to filter the item that has key/value: "CHID": "M0005"
full playbook example to demonstrate:
---
- hosts: localhost
gather_facts: false
vars:
query_result:
- C: ''
CHID: ''
DESCRIPTION: ''
EXPECTED_VALUE: ''
HOST: ''
SAP_NOTE: ''
VALUE: ''
- C: ''
CHID: M0005
DESCRIPTION: Generated with
EXPECTED_VALUE: ''
HOST: ''
SAP_NOTE: '1969700'
VALUE: 'SQL: \HANA_Configuration_MiniChecks\""'
- C: ''
CHID: 22M00051231
DESCRIPTION: Generated with2121
EXPECTED_VALUE: ''
HOST: ''
SAP_NOTE: '1969700444'
VALUE: '444SQL: \HANA_Configuration_MiniChecks\""'
tasks:
- set_fact:
filtered_item: "{{ query_result | json_query('[?CHID == `M0005`]') }}"
- debug:
var: filtered_item
in your case, the json_query should look like:
- set_fact:
filtered_item: "{{ result.query_result | json_query('[?CHID == `M0005`]') }}"
Please note that if the list may have multiple items matching the condition, they will all be added to the filtered_item. To make sure you get only the first, you can pass the result to first:
- set_fact:
filtered_item: "{{ query_result | json_query('[?CHID == `M0005`]') | first }}"

Related

ansible json_query with character "-"

I have this json file and I need extract some data but problem is with this character -
{
"changed": true,
"failed": false,
"meta": {
"request_url": "pm/config/adom/AMIS/obj/dynamic/interface",
"response_code": 0,
"response_data": [
{
"color": 0,
"defmap-zonemember": [],
"description": "BYOD VLAN sub-interface.\nUsed in policy for firewalls maintaining BYOD traffic on LIBOs",
"dynamic_mapping": null,
"name": "BYOD",
"single-intf": "enable"
},
{
"color": 0,
"defmap-zonemember": [],
"dynamic_mapping": [
{
"_scope": [
{
"name": "ftg02",
"vdom": "dev"
}
],
"intrazone-deny": "enable",
"local-intf": [
"port8"
]
}
],
"name": "DMZ",
"single-intf": "disable"
},
{
"color": 0,
"defmap-zonemember": [],
"description": "Guest VLAN sub-interface. Used in policy for firewalls maintaining Guestnet traffic on LIBOs",
"dynamic_mapping": null,
"name": "Guest",
"single-intf": "enable"
}
]
}
}
I would like to get result of this "name": "DMZ" - DMZ with some condition
if local-intf == port8
I have got this error
FAILED! => {"msg": "template error while templating string: expected token ',', got 'local'. String: {{ item | json_query('dynamic_mapping[0]['local-intf'][0]') }}"}
here is my playbook which does not work \
- name: interface
debug:
msg: "{{ item.name }}"
loop: "{{ interface_info.meta.response_data }}"
when:
- item.dynamic_mapping != 'null'
- item | json_query('dynamic_mapping[0]._scope[0].name') == 'ftg02'
- item | json_query('dynamic_mapping[0]._scope[0].vdom') == 'dev'
- item | json_query('dynamic_mapping[0]['local-intf'][0]) == 'port8' #this line does not work
is some way to dont use loop ? Loop is to slow .
thank you for help
Try this
- debug:
msg: "{{ interface_info.meta.response_data|
selectattr('dynamic_mapping')|
selectattr('dynamic_mapping.0.local-intf.0', '==', 'port8')|
selectattr('dynamic_mapping.0._scope.0.name', '==', 'ftg02')|
selectattr('dynamic_mapping.0._scope.0.vdom', '==', 'dev')|
map(attribute='name')|first }}"
should give the first item
msg: DMZ

Ansible get unique value in loop for register

Hi friend below is my sample output from a regsiter name dataInfo
ok: [123.23.44.123] => {
"msg": [
{
"changed": true,
"item": [
{
"artifactName": "helloWorld.jar",
"status": "false"
},
"myGroup1"
],
"rc": 0,
"stderr_lines": [],
"stdout": "ok",
"stdout_lines": [
"ok"
]
},
{
"changed": true,
"item": [
{
"artifactName": "helloWorld.jar",
"status": "false"
},
"myGroup2"
],
"rc": 0,
"stderr_lines": [],
"stdout": "ok",
"stdout_lines": [
"ok"
]
}
Below is my code
- name: My ArtifactName Name
debug:
msg: "artifactName = {{ item.item[0].artifactName }}"
loop: "{{ dataInfo.results }}"
when: item.changed | bool == true and item.stdout == "ok"
How can i only display as below
artifactName = helloWorld.jar
rather than
artifactName = helloWorld.jar
artifactName = helloWorld.jar
I have shared my code as shown above. Please advice
As you are looping with dataInfo.results, the debug message will repeat for each "item". If you only want unique artifactName, then you can save it to a variable using json_query and choose to display only unique ones.
Something like this:
# Save list of artifactName found in dataInfo.results even with duplicates
- name: save artifact names
set_fact:
artifact_names: "{{ artifact_names | default([]) + [ item | json_query('item[].artifactName') ] }}"
loop: "{{ dataInfo.results }}"
# Show each item of artifact_names using unique filter to eliminate duplicates
- name: show unique artifact names
debug:
var: item
loop: "{{ artifact_names | flatten | unique }}"
Update:
Below set_fact:
artifact_names: "{{ artifact_names | default([]) + [ item.item[0].artifactName ] }}"
... will work if you get only 1 hash in item like this:
"item": [
{
"artifactName": "helloWorld.jar",
"status": "false"
},
],
But if it may have multiple hashes like below, it won't work:
"item": [
{
"artifactName": "helloWorld.jar",
"status": "false"
},
{
"artifactName": "someother.jar",
"status": "false"
},
...
],
If this is a possibility, then json_query should be used. It can be used exactly like the jq command.

filter a key value from the ansible output

I'm trying to filter a key value from a ansible output. Unable to parse it . Request your assistance on how to pass it. Please find the code below.
Playbook:
- uri:
url: "https://*********/nics/nic1"
method: GET
force_basic_auth: true
headers:
cookie: "{{ login.cookies_string }}"
validate_certs: false
register: test
Output :
ok: [192.168.84.203] => {
"allow": "GET, PUT",
"invocation": {
"module_args": {
"status_code": [
200
],
}
},
"json": {
"body": {
"interfaces": {
"#order": [
"ff7574025754b3df1647001"
],
"ff7574025754b3df1647001": {
"addresses": {
"1": "192.168.1.4/22",
"#order": [
"1"
]
},
"mtu": 1500,
"name": "default",
"source_based_routes": [],
"vlantag": 0
}
},
}
}
}
}
From the above output, I need "ff7574025754b3df1647001" to be printed which will have addresses. Just mentioning below in Bold and Italic on what need to be printed to avoid conflicts.
"#order": [
"ff7574025754b3df1647001"
],
"***ff7574025754b3df1647001***": {
"addresses": {
Please assist ..!
I have tried the below approach..
needle_in_haystack: "192.168.1.4/22"
tasks:
- name: find key for given needle
vars:
key_list: >-
{{
test.json.body.interfaces
| dict2items
| selectattr('value.addresses', 'defined')
| map(attribute='value.addresses')
| map('dict2items')
| flatten
| selectattr('value', 'eq', needle_in_haystack)
| map(attribute='key')
| list
}}
debug:
msg: "This is the list of found keys: {{ key_list }}"

Complex JSON and Ansible JSON_QUERY syntax

i have complex result in JSON format and struggling to extract values out of it.
I tested the JSONpath online evaluator https://jsonpath.com/ where i can just simply type
$.[*].toPort
and get the list of requested variables.
I've tried to use the same syntax in Ansible but getting empty list.
- name: JSON test
hosts: localhost
gather_facts: no
vars:
jsoncontent:
{
"infraAccPortP": {
"attributes": {
"annotation": "",
"childAction": "",
"descr": "",
"nameAlias": "",
"ownerKey": "",
"ownerTag": "",
"status": "",
"uid": "15374"
},
"children": [
{
"infraHPortS": {
"attributes": {
"annotation": "",
"uid": "8927"
},
"children": [
{
"infraPortBlk": {
"attributes": {
"fromPort": "41",
"toPort": "41",
"uid": "8927"
}
}
}
]
}
},
{
"infraHPortS": {
"attributes": {
"annotation": "",
"uid": "8927"
},
"children": [
{
"infraPortBlk": {
"attributes": {
"fromPort": "42",
"toPort": "42",
"uid": "8927"
}
}
}
]
}
}
]
}
}
tasks:
- name: show jsoncontent
debug:
var: jsoncontent
- name: Show just toPort values
debug:
msg: "{{ jsoncontent | json_query(jmesquery) }}"
vars:
jmesquery: "[*].toPort"
Any help how to adjust the query to get the expected result? Its bit frustrating as there is not much documentation on how json_query is implemented in Ansible
The task below does the job
- name: Show just toPort values
debug:
msg: "{{ jsoncontent.infraAccPortP.children | json_query(jmesquery) }}"
vars:
jmesquery: "[].infraHPortS.children[].infraPortBlk.attributes.toPort"
gives
msg:
- '41'
- '42'
Q: "Ansible implementation doesn't allow wildcard searches?"
A: There doesn't seem to be anything special in the implementation. (This filter moved to ansible-collections/community.general since 2.10.)
Q: "Just confused why I got the same result with much shorter syntax in that online checker."
A: The question is how the checker is implemented, I think. jq doesn't work this way either. For example
shell> cat data.json | jq .jsoncontent.infraAccPortP.children[].infraHPortS.children[].infraPortBlk.attributes.toPort
"41"
"42"
The "checker" query crashes
shell> cat data.json | jq .[*].toPort
jq: error: syntax error, unexpected '*' (Unix shell quoting issues?) at <top-level>, line 1:
.[*].toPort
jq: 1 compile error
, or gives an empty result
shell> cat data.json | jq .[].toPort
null

Need to map json to list

I have register variable with below json as value and need to extract name and dn from this JSON to list. tried different options using set_fact without any luck.
{
"nodes": {
"status": -1,
"imdata": [
{
"fabricNode": {
"attributes": {
"status": "",
"dn": "topology/pod-1/node-1",
"name": "NOQCJALAB1"
}
}
},
{
"fabricNode": {
"attributes": {
"status": "",
"dn": "topology/pod-1/node-1",
"name": "NOQCJALAB2"
}
}
}
],
"totalCount": 2,
"changed": false,
"failed": false
},
"changed": false,
"_ansible_verbose_always": true,
"_ansible_no_log": false
}
You need to remove the extraneous calls to map('from_json') because the object is already a dict
- set_fact:
node_names: >-
{{ (nodes.stdout | from_json).data
| map(attribute='fabnode')
| map(attribute='attributes')
| map(attribute='dn')
| list
}}
You would only want those map('from_json') call if your data structure contained embedded JSON, like so:
- set_fact:
inner_value: >-
{{ (example_text | from_json).a_key
| map("from_json")
| map(attribute="inner_key")
| list
}}
vars:
example_text: |
{"a_key": ["{\"inner_key\": \"inner value\"}"]}
It's possible to use json_query. For example the tasks below
- set_fact:
my_list: "{{ nodes.imdata|
json_query('[].{dn: fabricNode.attributes.dn,
name: fabricNode.attributes.name}')
}}"
- debug:
var: my_list
give
"my_list": [
{
"dn": "topology/pod-1/node-1",
"name": "NOQCJALAB1"
},
{
"dn": "topology/pod-1/node-1",
"name": "NOQCJALAB2"
}
]

Resources