I have a list of output from an MQ command that shows the status of a channel, the stdout_lines of my registered variable is;
'stdout_lines': [u'CHANNEL(SVRCONN.CHL) CHLTYPE(SVRCONN) CONNAME(1.2.3.4) STATUS(RUNNING) SUBSTATE(RECEIVE)']}
This out worked OK for what I was intending on doing as I need to display the output of the CHANNEL and STATUS only and could find the values using a combinations of .split(')')[1].split('(')[1] and split(')')[4].split('(')[1] to get values SVRCONN.CHL and RUNNING
I have also been using this task for CLUSTER channel but found it was failing, the reason for this was that there is was an extra field,
'stdout_lines': [u'CHANNEL(CLUSTER_CHL) CHLTYPE(CLUSRCVR) CONNAME(2.3.4.5) RQMNAME(CLUS00) STATUS(RUNNING) SUBSTATE(RECEIVE)']}
now i could do a check to see if RQMNAME is in the output and then use a different split, but is there a way that this can be done using a string to find the location in output of STATUS?
CodePudding user response:
The best way is to convert it to real structured data, and you can then access any value that you need. The following is a somewhat hacky way to achieve that, but works:
- hosts: localhost
tasks:
- debug:
msg: "{{ cooked.CHANNEL }} / {{ cooked.STATUS }}"
vars:
cooked: "{{ dict(item | split | map('regex_replace', '\\((. )\\)$', ' \\1') | map('split')) }}"
loop:
- 'CHANNEL(SVRCONN.CHL) CHLTYPE(SVRCONN) CONNAME(1.2.3.4) STATUS(RUNNING) SUBSTATE(RECEIVE)'
- 'CHANNEL(CLUSTER_CHL) CHLTYPE(CLUSRCVR) CONNAME(2.3.4.5) RQMNAME(CLUS00) STATUS(RUNNING) SUBSTATE(RECEIVE)'
To parse this into a dictionary we split on whitespace, convert each key(value)
into key value
, split on whitespace again to separate keys from values, then pass that into dict()
.
PLAY [localhost] ****************************************************************
TASK [debug] ********************************************************************
ok: [localhost] => (item=CHANNEL(SVRCONN.CHL) CHLTYPE(SVRCONN) CONNAME(1.2.3.4) STATUS(RUNNING) SUBSTATE(RECEIVE)) => {
"msg": "SVRCONN.CHL / RUNNING"
}
ok: [localhost] => (item=CHANNEL(CLUSTER_CHL) CHLTYPE(CLUSRCVR) CONNAME(2.3.4.5) RQMNAME(CLUS00) STATUS(RUNNING) SUBSTATE(RECEIVE)) => {
"msg": "CLUSTER_CHL / RUNNING"
}
CodePudding user response:
Given the list
lines:
- CHANNEL(SVRCONN.CHL) CHLTYPE(SVRCONN) CONNAME(1.2.3.4) STATUS(RUNNING) SUBSTATE(RECEIVE)
- CHANNEL(CLUSTER_CHL) CHLTYPE(CLUSRCVR) CONNAME(2.3.4.5) RQMNAME(CLUS00) STATUS(RUNNING) SUBSTATE(RECEIVE)
You can create the list of dictionaries without iteration. For example,
cooked: "{{ lines|map('split')|
map('map', 'regex_replace', '\\((. )\\)$', ' \\1')|
map('map', 'split')|
map('community.general.dict')|
list }}"
gives
cooked:
- CHANNEL: SVRCONN.CHL
CHLTYPE: SVRCONN
CONNAME: 1.2.3.4
STATUS: RUNNING
SUBSTATE: RECEIVE
- CHANNEL: CLUSTER_CHL
CHLTYPE: CLUSRCVR
CONNAME: 2.3.4.5
RQMNAME: CLUS00
STATUS: RUNNING
SUBSTATE: RECEIVE
Example of a complete playbook for testing
- hosts: localhost
vars:
lines:
- 'CHANNEL(SVRCONN.CHL) CHLTYPE(SVRCONN) CONNAME(1.2.3.4) STATUS(RUNNING) SUBSTATE(RECEIVE)'
- 'CHANNEL(CLUSTER_CHL) CHLTYPE(CLUSRCVR) CONNAME(2.3.4.5) RQMNAME(CLUS00) STATUS(RUNNING) SUBSTATE(RECEIVE)'
cooked: "{{ lines|map('split')|
map('map', 'regex_replace', '\\((. )\\)$', ' \\1')|
map('map', 'split')|
map('community.general.dict')|
list }}"
tasks:
- debug:
var: cooked
- debug:
msg: "{{ item.CHANNEL }} / {{ item.STATUS }}"
loop: "{{ cooked }}"