Custom Modules
Ansible's custom modules allow you to extend its capabilities by implementing logic for tasks that aren't covered by built-in modules. This guide walks you through creating, testing, and using custom modules for unique workflows, such as interacting with proprietary APIs or managing custom resources.
Module Structure and Requirements¶
A custom Ansible module is a Python script that adheres to Ansible's module API. The core components include:
- main.py: The module's entry point, containing the main() function.
- module_utils/: Optional directory for utility functions shared across modules.
- plugins/: Directory for plugins (e.g., connection plugins), though modules typically live in a separate directory.
Modules must define an argspec (argument specification) and implement logic in the main() function.
Writing a Custom Module¶
1. Define the Module's Purpose¶
For example, create a module to interact with a hypothetical "custom_api" service.
# my_custom_module/main.py
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec={
"api_url": {"type": "str", "required": True},
"resource_id": {"type": "str", "required": True},
"state": {"type": "str", "choices": ["present", "absent"], "default": "present"},
},
supports_check_mode=True,
)
api_url = module.params["api_url"]
resource_id = module.params["resource_id"]
state = module.params["state"]
# Example logic: Check if resource exists
if state == "present":
# Simulate API call
result = {"changed": False, "msg": "Resource exists", "resource_id": resource_id}
else:
# Simulate deletion
result = {"changed": True, "msg": "Resource deleted", "resource_id": resource_id}
module.exit_json(**result)
if __name__ == "__main__":
main()
2. Handle Edge Cases and Errors¶
Use module.fail_json() for errors and ensure all required parameters are validated.
Testing Custom Modules¶
Use ansible-test to validate your module:
-
Install the module:
(Create a
requirements.ymlfile with:
-
Write a Test Playbook (
test_playbook.yml):
-
Run Tests:
Best Practices¶
- Follow Ansible's coding standards: Use
AnsibleModulefor input handling and consistent return values. - Leverage
module_utils: Share utility functions across modules to avoid duplication. - Document parameters: Use
descriptionandrequiredfields inargument_spec. - Support check mode: Implement logic to handle
--checkflags gracefully.
Key takeaways¶
- Custom modules extend Ansible by implementing task-specific logic in Python.
- Use
AnsibleModuleto handle parameters, errors, and return values. - Test modules with
ansible-testand validate edge cases. - Follow best practices for maintainability and compatibility with Ansible's ecosystem.
- Package modules for reuse via
ansible-galaxyor version control.