With version 2.1 Ansible introduced two features that make it possible to add proper debug logging to your playbooks, and also check and troubleshoot them on the fly, while they are executed.
The Debug Strategy
Strategies change the way Ansible executes your tasks. The default strategy is linear
. That is the one you are used to, and that executes all tasks one after another, always waiting until each host finished the current task before continuing with the next one. There is also a free
strategy that executes the tasks on each host as fast as it can, without waiting for the other hosts to catch up.
If you set the strategy to debug
, the Ansible playbook debugger will kick in whenever a task has failed, and give you the chance to view and change parameters in-flight and re-run just the failed task. Everyone who ever executed a lengthy playbook with lots of registered variables over and over again, just to debug a small task at the end of it, will immediately see the benefit of the debug
strategy.
To activate a strategy you can add it to your playbook:
1- hosts: localhost 2 strategy: debug 3 tasks: 4 - ...
or, less invasively, change the strategy temporarily with an environment variable:
1$ export ANSIBLE_STRATEGY=debug
and unset it when you are done debugging. This avoids adding a line to your playbook that you need to remove anyway before you commit your fix.
Now, when a task fails Ansible will spawn the debugger and present you with a prompt. Let us assume you want to write a file:
1- name: Write my file 2 copy: 3 dest: /tmp/my 4 content: | 5 Hello World! 6 This is my file.
and that fails for some reason. When using the debug
strategy, Ansible will invoke its debugger that you can use to dissect the current variable environment of the task and change values or task parameters:
1TASK [Write my file] ********************************************** 2fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "can not use content with a dir as dest"} 3Debugger invoked 4(debug) task.args 5{u'dest': u'/tmp/my', u'content': u'Hello World!\nThis is my file.\n'}
The error message tells me that I tried to write to a destination that is a directory and not a file. My bad, the correct dest
parameter value should have been /tmp/my/myfile
. Now lets change that parameter on the fly and re-run the task:
1(debug) task.args['dest']='/tmp/my/myfile' 2(debug) task.args 3{u'dest': '/tmp/my/myfile', u'content': u'Hello World!\nThis is my file.\n'} 4(debug) redo 5changed: [localhost]
The debugger not only lets you change variables and values you can also add and delete them:
1(debug) task.args['owner']='myuser' 2(debug) task.args 3{u'dest': '/tmp/my/myfile', u'content': u'Hello World!\nThis is my file.\n', 'owner': 'myuser'} 4(debug) del(task.args['owner']) 5(debug) task.args 6{u'dest': '/tmp/my/myfile', u'content': u'Hello World!\nThis is my file.\n'}
You can find a full list of the debugger commands here.
The Debug Module
The debug
module is well known. It is the Ansible equivalent to a print
line in Python code that you add now and then to see some variable values when debugging your scripts. But debug
lines are ugly and you want to remove them, or replace them with proper logging, before releasing your code. With version 2.1 Ansible extended the debug
module with a verbosity
parameter, that transforms it from an ugly print
line, that clutters your logs, with debug information on every call, into a more useful logging mechanism with an explicit debug level.
When adding a debug task and setting the the verbosity level to 2
:
1- name: Write file 2 copy: 3 dest: /tmp/my 4 content: | 5 Hello World! 6 This is my file. 7 register: write_file_result 8- name: Debug write_file_result 9 debug: 10 var: write_file_result 11 verbosity: 2
it will only be executed if you specify this verbosity (-vv
) on the command line:
1ansible-playbook debug-demo.yml -vv 2 3[...] 4 5TASK [Debug write_file_result] ********************************************** 6ok: [localhost] => { 7 "write_file_result": { 8 "changed": true, 9 "checksum": "0ded82d0b36ca79392d9bd97debb6fbbb7bb93ef", 10 "dest": "/tmp/my/myfile", 11 "gid": 20, 12 "group": "staff", 13 "md5sum": "f52e35e56cd4087de0948890215f7de0", 14 "mode": "0644", 15 "owner": "myuser", 16 "size": 30, 17 "src": "/Users/myuser/.ansible/tmp/ansible-tmp-1498165508.64-230947914847899/source", 18 "state": "file", 19 "uid": 501 20 } 21}
When using verbosity level 1
(-v
) Ansible will simply skip your debug task:
1ansible-playbook debug-demo.yml -v 2 3[...] 4 5TASK [Debug write_file_result] ******************************************************************** 6skipping: [localhost] => {"changed": false, "skipped": true, "skipped_reason": "Verbosity threshold not met."}
Adding debug
tasks not only on demand, but as a fixed part of your role will give you the ability to more quickly troubleshoot and debug. Some good points to insert debug logging are:
- After any task that registers a variable, or
- at the beginning of any included file that is parameterized or looped over.
Another good use case is to add well placed debug
tasks and the verbosity level of your choice to your Jenkins build jobs, and have debugging information right in your logs.
More articles
fromDaniel Marks
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Daniel Marks
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.