I am trying to do a nice print out of the data from Ansible but have no idea on how to manipulate it.
This is what I have in the debug — I am trying to somehow manipulate the data so that it only gives me a CN= (without the CN=) value, and not the whole subject string:
[
{
"certkey": "Verisign_ca3_cer",
"daystoexpiration": 0,
"status": "Expired",
"subject": " C=US,O=VeriSign, Inc.,OU=VeriSign Trust Network,OU=Terms of use at https://www.verisign.com/rpa (c)06,CN=VeriSign Class 3 Extended Validation SSL SGC CA"
},
{
"certkey": "Verisign_ca5_cer",
"daystoexpiration": 0,
"status": "Expired",
"subject": " C=US,O=VeriSign, Inc.,OU=VeriSign Trust Network,OU=Terms of use at https://www.verisign.com/rpa (c)10,CN=VeriSign Class 3 International Server CA - G3"
}
]
I wanted output similar to this:
[
{
"certkey": "Verisign_ca3_cer",
"daystoexpiration": 0,
"status": "Expired",
"subject": "CN=VeriSign Class 3 Extended Validation SSL SGC CA"
},
{
"certkey": "Verisign_ca5_cer",
"daystoexpiration": 0,
"status": "Expired",
"subject": "CN=VeriSign Class 3 International Server CA - G3"
}
]
Q: "Select 'CN' from 'subject'."
A: Let's assume your data is a list of dictionaries, e.g.
certs:
- {"certkey": "Verisign_ca3_cer",
"daystoexpiration": 0,
"status": "Expired",
"subject": " C=US,O=VeriSign, ...
Create the list of the parsed subjects, e.g.
- set_fact:
subjs: "{{ subjs|d([]) + [_subj] }}"
loop: "{{ certs|map(attribute='subject')|list }}"
vars:
_subj: "{{ dict(item.split(',')|
select('match', '.*=.*')|
map('trim')|
map('split', '=')|
list) }}"
gives
subjs:
- C: US
CN: VeriSign Class 3 Extended Validation SSL SGC CA
O: VeriSign
OU: Terms of use at https://www.verisign.com/rpa (c)06
- C: US
CN: VeriSign Class 3 International Server CA - G3
O: VeriSign
OU: Terms of use at https://www.verisign.com/rpa (c)10
and select the attribute 'CN'
- set_fact:
CN: "{{ subjs|map(attribute='CN')|list }}"
gives
CN:
- VeriSign Class 3 Extended Validation SSL SGC CA
- VeriSign Class 3 International Server CA - G3
Combine the certificates with the updated attribute subject, e.g.
- set_fact:
cert_cn: "{{ cert_cn|d([]) +
[item.0|combine({'subject': 'CN=' ~ item.1.CN})] }}"
loop: "{{ certs|zip(subjs) }}"
gives the output you want
cert_cn:
- certkey: Verisign_ca3_cer
daystoexpiration: 0
status: Expired
subject: CN=VeriSign Class 3 Extended Validation SSL SGC CA
- certkey: Verisign_ca5_cer
daystoexpiration: 0
status: Expired
subject: CN=VeriSign Class 3 International Server CA - G3
I just went the regex_replace way
msg: '{{ result.json.sslcertkey | regex_replace(" C=.*?CN=", "") }}'
Related
this is the raw data I want to search this using json_query in ansible with keyvalue=65060 and print the corresponding Neighbor, can anyone please help.
so far I got this:
- name: data manipulate
debug: msg="{{ msnjson | json_query(msnquery) }}"
vars:
msnquery: "[*].AS"
but this just displays all AS keys but I'm looking for exactly the key with value 65060 and corresponding Neighbor Key.
[
{
"AS": "65060",
"InQ": "0",
"MsgRcvd": "258259",
"MsgSent": "120410",
"Neighbor": "99.99.99.5",
"OutQ": "0",
"Spk": "0",
"StPfxRcd": "1",
"TblVer": "2241",
"UpDown": "2w0d"
},
{
"AS": "64600",
"InQ": "0",
"MsgRcvd": "281828",
"MsgSent": "120498",
"Neighbor": "192.168.100.1",
"OutQ": "0",
"Spk": "0",
"StPfxRcd": "33",
"TblVer": "2241",
"UpDown": "12w5d"
},
{
"AS": "64600",
"InQ": "0",
"MsgRcvd": "281867",
"MsgSent": "120498",
"Neighbor": "192.168.100.2",
"OutQ": "0",
"Spk": "0",
"StPfxRcd": "33",
"TblVer": "2241",
"UpDown": "12w5d"
},
{
"AS": "64600",
"InQ": "0",
"MsgRcvd": "258516",
"MsgSent": "120499",
"Neighbor": "192.168.100.4",
"OutQ": "0",
"Spk": "0",
"StPfxRcd": "19",
"TblVer": "2241",
"UpDown": "5w6d"
}
]
Try
- name: data manipulate
debug: msg="{{ msnjson | json_query(msnquery) }}"
vars:
msnquery: "[?AS=='65060'].Neighbor"
Update
There are multiple items with the same value of AS. It might be practical to create a dictionary if you have to search Neighbor by AS repeatedly. For example,
AS_Neighbors: "{{ [msnjson|json_query(msnquery), []]|
community.general.lists_mergeby('AS', list_merge='append')|
items2dict(key_name='AS', value_name='Neighbor') }}"
msnquery: "[].{AS: AS, Neighbor: [Neighbor]}"
gives
AS_Neighbors:
'64600':
- 192.168.100.1
- 192.168.100.2
- 192.168.100.4
'65060':
- 99.99.99.5
Example of a complete playbook for testing
- hosts: localhost
vars:
AS_Neighbors: "{{ [msnjson|json_query(msnquery), []]|
community.general.lists_mergeby('AS', list_merge='append')|
items2dict(key_name='AS', value_name='Neighbor') }}"
msnquery: "[].{AS: AS, Neighbor: [Neighbor]}"
msnjson:
- AS: '65060'
InQ: '0'
MsgRcvd: '258259'
MsgSent: '120410'
Neighbor: 99.99.99.5
OutQ: '0'
Spk: '0'
StPfxRcd: '1'
TblVer: '2241'
UpDown: 2w0d
- AS: '64600'
InQ: '0'
MsgRcvd: '281828'
MsgSent: '120498'
Neighbor: 192.168.100.1
OutQ: '0'
Spk: '0'
StPfxRcd: '33'
TblVer: '2241'
UpDown: 12w5d
- AS: '64600'
InQ: '0'
MsgRcvd: '281867'
MsgSent: '120498'
Neighbor: 192.168.100.2
OutQ: '0'
Spk: '0'
StPfxRcd: '33'
TblVer: '2241'
UpDown: 12w5d
- AS: '64600'
InQ: '0'
MsgRcvd: '258516'
MsgSent: '120499'
Neighbor: 192.168.100.4
OutQ: '0'
Spk: '0'
StPfxRcd: '19'
TblVer: '2241'
UpDown: 5w6d
tasks:
- debug:
var: AS_Neighbors
I have a dictionary of dictionaries collecting data from openshift using prometheus. Now I intend to add values in all the dictionaries. But some projects don't have quota and hence some pods don't have request/limit set for cpu and memory. I am trying the following and it fails in case the key:value is not there.
If possible I want to use if else such that, if the variable exists then add the variable else use the value as 0.
- name: Total section for Projects
set_fact:
pod_count_total: "{{ (pod_count_total|int) + (item.value.pod_count|int)}}"
total_cpu_request: "{{ (total_cpu_request|float |round(2,'ceil')) + (item.value.cpu_request|float |round(2,'ceil'))}}"
total_cpu_limit: "{{ (total_cpu_limit|float |round(2,'ceil')) + (item.value.cpu_limit|float |round(2,'ceil'))}}"
total_memory_request: "{{ (total_memory_request|float |round(2,'ceil')) + (item.value.memory_request|float |round(2,'ceil'))}}"
total_memory_limit: "{{ (total_memory_limit|float |round(2,'ceil')) + (item.value.memory_limit|float |round(2,'ceil'))}}"
with_dict: "{{all_project}}"
Dictionary of dictionaries is like
ok: [127.0.0.1] => {
"msg": {
"openshift-web-console": {
"cpu_usage": 0.015,
"memory_used": 0.04,
"cpu_request": 0.301,
"memory_request": 0.293,
"pod_count": 3
},
"srv-test": {
"cpu_usage": 0.013,
"memory_used": 0.02,
"pod_count": 5
},
"test": {
"cpu_usage": 0.001,
"memory_used": 0.0,
"pod_count": 1
},
"openshift-monitoring": {
"cpu_limit": 1.026,
"cpu_request": 0.556,
"cpu_usage": 0.786,
"memory_limit": 1.866,
"memory_request": 1.641,
"memory_used": 0.14,
"pod_count": 98
}
}
}
If possible I want to use if else such that, if the variable exists then add the variable else use the value as 0.
The thing you are looking for is the default filter
total_memory_request: "{{ (
total_memory_request | default(0)
| float | round(2,'ceil')
) + (
item.value.memory_request | default(0)
| float | round(2,'ceil')
) }}"
There's a subtlety in that if the variable exists but is the empty string, you'll need to pass in the 2nd parameter to default to have it act in a python "truthiness" way: {{ "" | default(0, true) | float }} -- that might not apply to you, but if it does, you'll be glad to know what that 2nd param does
I want to use ansible to merge below 2 dictionary to become 1.
I have been stucking for few days already. Headache.
I have 2 variables now.
1. variable "my_directories":
{
"directoryA": [
"/bar/foo/file1.txt",
"/bar/foo/file2.txt"
],
"directoryB": [
"/bar/baz/file3.txt",
"/bar/baz/file4.txt",
"/bar/baz/file5.txt"
]
}
2. variable "my_filecontents":
{
"/bar/foo/file1.txt": "file1Content",
"/bar/foo/file2.txt": "file2Content",
"/bar/baz/file3.txt": "file3Content",
"/bar/baz/file4.txt": "file4Content",
"/bar/baz/file5.txt": "file5Content"
}
i want to merge it to become:
Result:
variable my_result
{
"directoryA": {
"/bar/foo/file1.txt": "file1Content",
"/bar/foo/file2.txt": "file2Content"
},
"directoryB": {
"/bar/baz/file3.txt": "file3Content",
"/bar/baz/file4.txt": "file4Content",
"/bar/baz/file5.txt": "file5Content"
}
}
The directories and files could be dynamic.
I tried so many codes but still did not work.
Thank you!
The task below does the job
- set_fact:
my_result: "{{ my_result|default({})|
combine({item.0.key: {item.1: my_filecontents[item.1]}},
recursive=True) }}"
with_subelements:
- "{{ my_directories|dict2items }}"
- value
- debug:
var: my_result
gives
"my_result": {
"directoryA": {
"/bar/foo/file1.txt": "file1Content",
"/bar/foo/file2.txt": "file2Content"
},
"directoryB": {
"/bar/baz/file3.txt": "file3Content",
"/bar/baz/file4.txt": "file4Content",
"/bar/baz/file5.txt": "file5Content"
}
}
Is it possible to select which json object to use based on some dynamic criteria?
I have a yml file:
- name: Get data
uri:
url: "foo/get_data/{{item.name}}"
return_content: yes
with_items: "{{stuff_names}}"
register: app_out
- name: Use data
uri:
url: "foo/use_data/item.json[0].id"
method: POST
with_items: "{{ app_out.results }}"
Where the call to foo/get_data/<name> returns a json array with 1 or 2 items:
Sample from foo/get_data/bar1:
[{"id": 1, "type": "x"},{"id": 2, "type": "y"}]
Sample from foo/get_data/bar2:
[{"id": 1, "type": "x"}]
In the "Use data" task is there a way to specify which json object in the array to use based on if an object exists in item or the size of item etc? Right now its hard coded to the first object item.json[0].
For example,
if item contains an object of type "y" then use that object, otherwise use item of type "x".
or
if size of item is > 1, use item of type "x".
EDIT:
Or perhaps even a separate ansible task to prune the registered app_out?
Q: "if item contains an object of type "y" then use that object, otherwise use item of type "x"
A: The play below implements this logic, I think.
- hosts: localhost
vars:
results:
- {"id": 1, "type": "x"}
- {"id": 2, "type": "y"}
- {"id": 3, "type": "z"}
tasks:
- set_fact:
my_list: "{{ results|
selectattr('type', 'defined')|
selectattr('type', 'equalto','y')|list }}"
- set_fact:
my_list: "{{ results|
selectattr('type', 'defined')|
selectattr('type', 'equalto','x')|list }}"
when: my_list|length == 0
- name: Use type y, otherwise use type x
debug:
var: my_list
gives
"my_list": [
{
"id": 2,
"type": "y"
}
]
I am looking for some directions to fix an issue where i am not able to save or redirect the Ansible debug output to a JSON or md file.
- debug:
msg:
- "{{ item.results['show ip route'].splitlines() }}"
- "{{ item.results['show ip route summary'].splitlines() }}"
- "{{ item.results['show ip route 0.0.0.0'].splitlines() }}"
loop:
- "{{ out2 }}"
The above mentioned debug module runs at the very end of my playbook. The playbook mainly uses "napalm_cli" network module to collect few outputs from a device. The "napalm_cli" module output is not nicely formatted,so, i have to use splitlines.
Now i am trying to save below output as a file
ok: [lab1-r1] => (item={'failed': False, u'changed': False, u'results': {u'show ip route': u'Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP\n D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area \n N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2\n E1 - OSPF external type 1, E2 - OSPF external type 2\n i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2\n ia - IS-IS inter area, * - candidate default, U - per-user static route\n o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP\n a - application route\n + - replicated route, % - next hop override, p - overrides from PfR\n\nGateway of last resort is not set\n\n 172.16.0.0/16 is variably subnetted, 2 subnets, 2 masks\nC 172.16.10.0/24 is directly connected, GigabitEthernet0/1\nL 172.16.10.1/32 is directly connected, GigabitEthernet0/1', u'show ip route summary': u'IP routing table name is default (0x0)\nIP routing table maximum-paths is 32\nRoute Source Networks Subnets Replicates Overhead Memory (bytes)\nconnected 0 2 0 136 360\nstatic 0 0 0 0 0\napplication 0 0 0 0 0\ninternal 1 440\nTotal 1 2 0 136 800', u'show ip route 0.0.0.0': u'% Network not in table'}}) => {
"msg": [
[
"Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP",
" D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area ",
" N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2",
" E1 - OSPF external type 1, E2 - OSPF external type 2",
" i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2",
" ia - IS-IS inter area, * - candidate default, U - per-user static route",
" o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP",
" a - application route",
" + - replicated route, % - next hop override, p - overrides from PfR",
"",
"Gateway of last resort is not set",
"",
" 172.16.0.0/16 is variably subnetted, 2 subnets, 2 masks",
"C 172.16.10.0/24 is directly connected, GigabitEthernet0/1",
"L 172.16.10.1/32 is directly connected, GigabitEthernet0/1"
],
[
"IP routing table name is default (0x0)",
"IP routing table maximum-paths is 32",
"Route Source Networks Subnets Replicates Overhead Memory (bytes)",
"connected 0 2 0 136 360",
"static 0 0 0 0 0",
"application 0 0 0 0 0",
"internal 1 440",
"Total 1 2 0 136 800"
],
[
"% Network not in table"
]
]
}
Also, i would like to get rid of the content between
ok: [lab1-r1] => napalm_cli non formatted output
"msg": [
Any ideas or thoughts.
Thank You
NN
I believe you may want JSON callback (there is also a yaml one, and XMPP, and a whole list of them). The instructions for enabling them are in the fine manual, but the very short version is to just define an environment variable when calling ansible-playbook:
env ANSIBLE_STDOUT_CALLBACK=json ansible-playbook ...
(it works with ansible, too, if you just wanted to run a single task)