I have been developing custom Ansible modules on my windows system using JetBrains PyCharm IDE. Below I describe some challenges and best practices on the development and how to debug remotely.
For information about developing custom modules using Ansible check here.
Though Ansible supports configuring Windows systems, Ansible itself cannot be run on a windows control machine. If you are developing custom Ansible modules on a Windows Machine you might find it difficult to debug. This can be difficult if you are used to debugging in the IDE. The test-module offers some debug options if you are good with debugging in the Linux console.
In this article I explain how to debug using the IDE debugger on a windows system by running the module remotely on a Ansible controller Linux system.
Below is my development environment:
- Development system - Windows 7
- Development IDE - JetBrains PyCharm IDE Professional Edition *
- Ansible Controller - OpenSuse Linux Machine with Ansible installed. Must have network connectivity with the Development Windows System.
- Must have the Ansible devel package downloaded on the Linux Controller Machine to test custom modules - test-module. For instructions on setting this up, please see Installation.
* Must have a JetBrains PyCharm Professional Edition for remote debugging features. Community edition does not support remote debugging. If you have not purchased already You can get a free trial of Professional Edition for 30 days.
Create a new project in JetBrains PyCharm and create a new file in the project named - 'OSCheckModule.py'
If you have never developed a custom Ansible module, start here. Start from the Common base template and build your module. Here I have a custom module called OSCheckModule that checks the OS flavor against a given input :
#!/usr/bin/python
try:
import json
except ImportError:
import simplejson as json
import os
DOCUMENTATION = '''
---
module: OSCheckModule
short_description: A custom module to check OS of target machine.
description:
- A custom module to check OS of target machine.
options:
os_name:
description:
- Name of OS to check
required: true
'''
EXAMPLES = '''
# Example
module_name:
os_name: Linux
'''
def main():
module = AnsibleModule(
argument_spec=dict(
os_name=dict(required=True),
)
)
# Retreive parameters
os_name = module.params['os_name']
# Check for OS
if os_name in os.uname():
# Successfull Exit
module.exit_json(changed=True, msg="OS Match")
else:
# Fail Exit
module.fail_json(msg="OS Mismatch. OS =" + os.uname()[0])
from ansible.module_utils.basic import AnsibleModule
if __name__ == '__main__':
main()
We are ready with our first custom module. We will now copy this fiel to our Linux Controller Machine for execution. We can use PyCharm's remote Python interpretor feature to push and run the script remotely on the Linux Controller machine without having to manually copy over. Read about it here. Will blog about it another time.
I have copied my new module file to the path /opt/ansible/custom_modules
in my Linux Ansible Controller Machine. I can now use the test-module to test and execute my new custom ansible module.
Syntax:
/opt/ansible/ansible-devel/hacking/test-module -m <module file> -a <module arguments>
Example:
root:/opt/ansible/custom_modules # /opt/ansible/ansible-devel/hacking/test-module -m OSCheckModule.py -a os_name=Linux
* including generated source, if any, saving to: /root/.ansible_module_generated
* this may offset any line numbers in tracebacks/debuggers!
***********************************
RAW OUTPUT
{"msg": "OS Match", "invocation": {"module_args": {"os_name": "Linux"}}, "changed": true}
***********************************
PARSED OUTPUT
{
"changed": true,
"invocation": {
"module_args": {
"os_name": "Linux"
}
},
"msg": "OS Match"
}
Wow!! we have successfully created and tested our first Custom Ansible Module.
We would now like to debug our custom ansible module using PyCharm debugger. For example we would like to set a break point at Line 46 to inspect the result of os.uname() call. We wouldwill use Python pydevd for this purpose.
pip install pydevd
Create a new Project in PyCharm and go to Run -> Edit Configurations..
Click on the plus sign in top left corner and select Python Remote Debug. (You must be using PyCharm Professional Edition to have this feature. Ths is not available in PyCharm Community Edition.)
Provide the following information :
- Name: Give a name to the debugger - OSCheckModule_Debugger
- Local host name: Enter the IP of the Windows development system. Make sure you can ping and establish connectivity to this IP from your Linux System
- Port - Set port to 54654
- Path mappings - Ignore
- Leave the remaining settings to default
Start the PyCharm Debug server by clicking on the debug optionbutton in the top right corner
The Debug server starts and starts listening for connections
Note down the instructions provided to configure source code:
Use the following code to connect to the debugger:
import pydevd
pydevd.settrace('10.123.12.214', port=54654, stdoutToServer=True, stderrToServer=True)
Insert the following lines in the source code of the custom module - OSCheckModule.py
Insert import pydevd line at the top
import pydevd
Insert the below line to set breakpoint at line 46
pydevd.settrace('10.123.12.214', port=54654, stdoutToServer=True, stderrToServer=True)
Copy the source code to the linux system, if you have made the changes on your windows system. Run the module using test-module:
root:/opt/ansible/custom_modules # /opt/ansible/ansible-devel/hacking/test-module -m OSCheckModule.py -a os_name=Linux
If connectivity is established between the Linux and Windows systems, a prompt will appear in PyCharm in windows.
Select the Download Source option to downlaod the source code to windows machine. The source will be downloaded the breakpoint is set. You can line step through the remainder of the code and use Debug console to view variables and their values.
Thank you for reading. Please feel free to comment, propose better solutions.
Mumshad Mannambeth (@mmumshad)
See a problem, have an issue? Raise an issue at the github page