Im trying to pull values from a json file but I do not want values that are null? How can I easily skip null
values?
I am just trying to find the easiest and simplest solution to parsing JSON into YALM and not have formatting errors in YAML. Maybe I am over complicating it.
JSON:
{
"configuration": {
"protocols" : {
"bgp" : {
"group" : [
{
"name" : "IBGP",
"neighbor" : [
{
"name" : "192.168.1.2",
"description" : "router-2"
}
]
},
{
"name" : "EBGP",
"neighbor" : [
{
"name" : "192.168.2.2",
"description" : "router-3",
"local-address" : "192.168.2.1",
"peer-as" : "65555"
}
]
}
]
}
}
}
}
Play:
- name: parse bgp
set_fact:
bgp: "{{ read | to_json | from_json | json_query(bgp_var) }}"
vars:
bgp_var: 'configuration.protocols.bgp.group[].{group_name:name,neighbors:[{peer_ip:neighbor[].name | [0], peer_description:neighbor[].description | [0], peer_as:neighbor[]."peer-as" | [0] }]}'
- copy:
content: >-
routing_protocols:
bgp:
{{ bgp | to_nice_yaml(indent=2, width=1337, sort_keys=False) | indent(4) }}
dest: "{{ inventory_hostname }}_routing_protocols.yaml"
Returns:
routing_protocols:
bgp:
- group_name: IBGP
neighbors:
- peer_as: null # < Is there a way to skip this anytime a value is null?
peer_description: router-2
peer_ip: 192.168.1.2
- group_name: EBGP
neighbors:
- peer_as: '65555'
peer_description: router-3
peer_ip: 192.168.2.2
CodePudding user response:
you could use this playbook with the parameter omit:
tasks:
- name: set var
set_fact:
bgp: >-
{{ bgp | d([])
[ {'group_name': _gpname,
'neighbors': [{'peer_description': _desc, 'peer_ip': _peerip, 'peer_as': _peeras}]
}
] }}
loop: "{{ configuration.protocols.bgp.group }}"
vars:
_gpname: "{{ item.name }}"
_desc: "{{ item.neighbor.0.description }}"
_peeras: "{{ item.neighbor[0]['peer-as'] | d(omit)}}"
_peerip: "{{ item.neighbor.0.name }}"
- name: displ
debug:
msg: "{{ bgp }}"
result:
ok: [localhost] => {
"msg": [
{
"group_name": "IBGP",
"neighbors": [
{
"peer_description": "router-2",
"peer_ip": "192.168.1.2"
}
]
},
{
"group_name": "EBGP",
"neighbors": [
{
"peer_as": "65555",
"peer_description": "router-3",
"peer_ip": "192.168.2.2"
}
]
}
]
}
CodePudding user response:
You can make it in one go in JMESPath, but that would require a double query on the property neighbour
, as JMESPath cannot omit a property as Ansible can (for that, see @Frenchy's answer).
So, you would have to have list of list, into which, the first sub list would consist of the neighbour
that would contain the key peer-as
, and the second sub list, the one that would not contain it. Then you will have to flatten this list of list.
So, here is the copy
task:
- copy:
content: >-
{{
read
| to_json
| from_json
| json_query(query)
| to_nice_yaml(indent=2)
}}
dest: "{{ inventory_hostname }}_routing_protocols.yaml"
vars:
query: >-
{
routing_protocols: {
bgp: configuration.protocols.bgp.group[].{
group_name: name,
neighbors: [
neighbor[?"peer-as"].{
peer_description: description,
peer_ip: name,
peer_as: "peer-as"
},
neighbor[?"peer-as" == null].{
peer_description: description,
peer_ip: name
}
]|[]
}
}
}
After this task, you will end with a YAML file containing your expected:
routing_protocols:
bgp:
- group_name: IBGP
neighbors:
- peer_description: router-2
peer_ip: 192.168.1.2
- group_name: EBGP
neighbors:
- peer_as: '65555'
peer_description: router-3
peer_ip: 192.168.2.2