Skip to content

Enter Python Debugger From Running An Ansible Playbook

Enter the Python debugger from a running Ansible playbook#

I wanted access to pdb or ipdb while running a playbook that used custom modules. The Ansible developer guide has a section on debugging, but custom modules do not behave like normal Python files.

Ansible wraps modules with helper code and puts them into a zip file before execution. That makes normal interactive debugging awkward.

The Ansible documentation mentions simple debugging using epdb.

Simple debugging with epdb#

Install epdb into your virtual environment:

pip install epdb

Then add this line anywhere in the module where you have an issue.

import epdb; epdb.serve()

The line where you have the issue can usually be found by running your playbook in verbose mode:

ansible-playbook playbook.yml -vvvv

From the epdb docs:

To debug code that is either running on a remote system, or in a process that isn’t attached to your tty you can use epdb in server mode

Run your playbook and it should pause at that point. Connect with:

import epdb
epdb.connect()

This partly worked for me, but I could not control stepping. c, s, n and even h did not work, so I do not think it ever fully entered epdb.

One fallback is to raise an exception with the value you need. print() statements do not work reliably in modules.

raise Exception(some_value)

Debug strategy#

It depends on your play strategy.

Set

- hosts: all
  connection: local
  strategy: debug

It will then break on a failing task:

[localhost] TASK: create org (debug)>

You can then get the output of the json args sent to a module or task. Get the task arguments as JSON with:

{
    'org_name': 'TEST0002',
    'full_name': 'Test VCD ORG',
    'is_enabled': 'true',
    'state': 'present',
    '_ansible_check_mode': False,
    '_ansible_no_log': False,
    '_ansible_debug': False,
    '_ansible_diff': False,
    '_ansible_verbosity': 0,
    '_ansible_version': '2.9.7',
    '_ansible_module_name': 'vcd_org',
    '_ansible_syslog_facility': 'LOG_USER',
    '_ansible_selinux_special_fs': ['fuse', 'nfs', 'vboxsf', 'ramfs', '9p', 'vfat'],
    '_ansible_string_conversion_action': 'warn',
    '_ansible_socket': None,
    '_ansible_shell_executable': '/bin/sh',
    '_ansible_keep_remote_files': False,
    '_ansible_tmpdir': '/Users/stephen/.ansible/tmp/ansible-tmp-1588670617.1317708-64312-102300914438839/',
    '_ansible_remote_tmp': '~/.ansible/tmp'
}

More options are available in the Ansible debugger docs.

Module utils#

Module utils can be accessed via ansible.module_utils.<your_name_here>.

When running the module directly, custom module utils might not be in the Python path and you can get an error:

python modules/vcd_org.py ./test_args.json
Traceback (most recent call last):
    File "modules/vcd_org.py", line 102, in <module>
        from ansible.module_utils.vcd import VcdAnsibleModule
ModuleNotFoundError: No module named 'ansible.module_utils.vcd'

To get the Ansible module utils search path:

ansible-config dump | grep MODULE_UTILS_PATH

It looks like a limitation of Ansible when bringing custom module_utils into direct module execution, as discussed in this Google Groups thread.

Workaround#

Copy the files from module_utils into your module library and update references from from ansible.module_utils.<package> to from <package>.

Sources#