'remove null elements from list ansible
Below is my JSON file:
[
{
"?xml": {
"attributes": {
"encoding": "UTF-8",
"version": "1.0"
}
}
},
{
"domain": [
{
"server": [
{
"name": "myserv1"
},
{
"ssl": {
"name": "myserv1"
}
},
{
"log": [
{
"name": "myserv1"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
]
}
]
},
{
"server": [
{
"name": "myserv2"
},
{
"ssl": {
"name": "myserv2"
}
},
{
"log": [
{
"name": "myserv2"
},
{
"file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
}
]
}
]
}
]
}
]
Here is my Ansible play that uses JMESPath query to read the json data.
- name: Server Names and log details
set_fact:
serverlog: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '[].domain[].server[*].log[*].[name, "file-name"]'
- name: removing empty
set_fact:
serverlog: "{{ serverlog|reject('match', '^$')|list }}"
- name: Print all server names with log details
debug:
msg: "{{ item }}"
with_items:
- "{{ serverlog }}"
Output:
TASK [Print all server names with log details] *********************************
Wednesday 02 March 2022 03:17:45 -0600 (0:00:00.100) 0:00:04.730 *******
ok: [localhost] => (item=[]) => {
"msg": []
}
ok: [localhost] => (item=[[['myserv1', None], [None, '/web/bea_logs/domains/mydom/myserv1/myserv1.log']]]) => {
"msg": [
[
[
"myserv1",
null
],
[
null,
"/web/bea_logs/domains/mydom/myserv1/myserv1.log"
]
]
]
}
I wish to remove null from the output so that the variables are better formatted & easily accessible.
I wish to store the read data as Ansible variables in a file like below:
myserv1_log: "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
myserv2_log: "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
As you can see in the playbook I tried to remove the null in the playbook but it does not help.
Solution 1:[1]
You can achieve most of what you are looking for with this — quite complex — JMESPath query:
[].domain[].server[?log].log[].{
name: join(`_`, [[?name].name | [0], `log`]),
filename: [?"file-name"]."file-name" | [0]
}
The trick here is to query the server list to find elements that do have a property log — with the help of server[?log], then in the log list, do the same for element that have a property name and a property file-name with [?name] and [?"file-name"] respectively.
Because those are lists, you will need to stop the projections with a pipe expression, before getting the first item of both those lists — so, with a construct like | [0].
In order to add the _log suffix, you can use the join function, by creating an array of two element, containing the name and the string log, that would be joined with an underscore: join(`_`, [[?name].name | [0], `log`]).
With all that, you end up with this list:
- filename: /web/bea_logs/domains/mydom/myserv1/myserv1.log
name: myserv1_log
- filename: /web/bea_logs/domains/mydom/myserv2/myserv2.log
name: myserv2_log
And now, we just need to make that a dictionary, with the help of items2dict.
All this together gives this set_fact task:
- set_fact:
server_logs: >-
{{
jsondata | json_query('[].domain[].server[?log].log[].{
name: join(`_`, [[?name].name | [0], `log`]),
filename: [?"file-name"]."file-name" | [0]
}') | items2dict(key_name='name', value_name='filename')
}}
Which would yield, if debug'ed:
TASK [debug] ******************************************************************
ok: [localhost] =>
server_logs:
myserv1_log: /web/bea_logs/domains/mydom/myserv1/myserv1.log
myserv2_log: /web/bea_logs/domains/mydom/myserv2/myserv2.log
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | β.εηοιτ.βε |
