I am a big fan of Ansible automation: its simplicity, the ease of developing and testing playbooks, the fact that you can run playbooks on any machine - there is no dedicated server installation required.
But there is one thing I really dont like about Ansible: the readability of its output, or better, its lack thereof.
Ansible can be quite verbose, which is perfect while developing and debugging playbooks.
But during regular playbook runs that verbosity is cluttering the screen and making the output a bit cumbersome to read for human eyes. Especially when you use any loop construct, Ansible will print out the entire data structure while happily looping through data. This, again, is handy for small data, but will make your eyes water when working with larger data sets.
Fortunately there are a few things we can do about that:
override the default message that gets printed out for each loop-iteration
reduce the data required for the loop
Definitions
For the sake of demonstrating these techniques, we need to define Ansible variables and a simple playbook showing the effects of our improvements.
Variables and playbook
Here we define our variables. We define a list of dictionaries, where each list item describes an minion object which owns a bunch of properties, ie. name/value-pairs.
- name:Minion demo playbookhosts:localhostgather_facts:novars:minions:- name:Daveloves:banananumberOfEyes:1outfit:"blue trousers"hair:spiky- name:Stuartloves:even more bananasnumberOfEyes:2outfit:"golfer"hair:center-parted- name:Kevinloves:GrunumberOfEyes:2outfit:"french maid"hair:a tiny clumptasks:- name:01- standard loop over list of minionsdebug:msg:|Meet minion {{ item.name }} !loop:"{{ minions }}"- name:02- override loop item labeldebug:msg:|Meet minion {{ item.name }} !loop:"{{ minions }}"loop_control:label:"processing minion: {{ item.name }}"- name:03- loop over minion names (extracted/mapped)debug:msg:|Meet minion {{ item }} !loop:"{{ minions | map(attribute='name') | list }}"
Improving loop readability
When run, output of task 01 will look like shown below. The entire, large Json data structure is printed for each loop iteration. The message line is almost lost in the middle.
1
2
3
4
5
6
7
8
9
10
11
12
13
PLAY [Minion demo playbook] ***************************************************TASK [01 - standard loop over list of minions] ********************************Tuesday 16 April 2019 23:22:18 +0200 (0:00:00.091) 0:00:00.091 *********ok:[localhost] => (item={u'hair': u'spiky', u'loves': u'banana', u'name': u'Dave', u'numberOfEyes': 1, u'outfit': u'blue trousers'}) =>msg:|-Meet minion Dave !ok:[localhost] => (item={u'hair': u'center-parted', u'loves': u'even more bananas', u'name': u'Stuart', u'numberOfEyes': 2, u'outfit': u'golfer'}) =>msg:|-Meet minion Stuart !ok:[localhost] => (item={u'hair': u'a tiny clump', u'loves': u'Gru', u'name': u'Kevin', u'numberOfEyes': 2, u'outfit': u'french maid'}) =>msg:|-Meet minion Kevin !
Overriding the loop label
The next best thing to do is override the loop label. This is shown in task-02, which then changes the output as shown below. Much better!
TASK [02 - override loop item label] *****************************************Tuesday 16 April 2019 23:22:18 +0200 (0:00:00.063) 0:00:00.155 ********ok: [localhost] => (item=processing minion:Dave) =>msg:|-Meet minion Dave !ok: [localhost] => (item=processing minion:Stuart) =>msg:|-Meet minion Stuart !ok: [localhost] => (item=processing minion:Kevin) =>msg:|-Meet minion Kevin !
Extracting the required key(s) from dictionary
Another option is to extract (map) the attribute we actually require in the loop.
This is shown in task-03 using the Jinja filter map(attribute='xxx').
Using the map filter makes the expression a bit unwieldy (and twice so when you require more than one attribute!), but it works like a charm nevertheless: the <item> in the loop label now consist of only the values of “name” property.
loop: "{{ minions | map(attribute='name') | list }}"
1
2
3
4
5
6
7
8
9
10
11
TASK [03 - loop over minion names (extracted/mapped)] *************************Tuesday 16 April 2019 23:33:06 +0200 (0:00:00.056) 0:00:00.208 *********ok:[localhost] => (item=Dave) =>msg:|-Meet minion Dave !ok:[localhost] => (item=Stuart) =>msg:|-Meet minion Stuart !ok:[localhost] => (item=Kevin) =>msg:|-Meet minion Kevin !