High-quality modules with minimal dependencies can be included in Ansible, but modules (just due to the programming preferences of the developers) will need to be implemented in Python and use the AnsibleModule common code, and should generally use consistent arguments with the rest of the program. Stop by the mailing list to inquire about requirements if you like, and submit a github pull request to the ansible project. Included modules will ship with ansible, and also have a chance to be promoted to ‘core’ status, which gives them slightly higher development priority (though they’ll work in exactly the same way).
The following checklist items are important guidelines for people who want to contribute to the development of modules to Ansible on GitHub. Please read the guidelines before you submit your PR/proposal.
#!/usr/bin/python
. This allows ansible_python_interpreter
to workDOCUMENTATION
. In Ansible-2.3 the minimum requirement for modules was Python-2.4.ANSIBLE_METADATA = {'status': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'}
The complete module metadata specification is here: Ansible metadata block
started/stopped
, present/absent
–don’t overload options too much. It is preferable to add a new, simple option than to add choices/states that don’t fit with existing ones.Modules should make use of the “extends_documentation_fragment” to ensure documentation available. For example, the AWS module should include:
extends_documentation_fragment:
- aws
- ec2
The module must not use sys.exit() –> use fail_json() from the module object.
Import custom packages in try/except and handled with fail_json() in main() e.g.
try:
import foo
HAS_LIB=True
except:
HAS_LIB=False
ansible.module_utils
code in the same place as you import other libraries. In older code, this was done at the bottom of the file but that’s no longer needed.from ansible.module_utils.basic import *
). This used to be required for code imported from ansible.module_utils
but, from Ansible-2.1 onwards, it’s just an outdated and bad practice.main()
from a conditional so that it would be possible to
import them into unittests in the future exampleif __name__ == '__main__':
main()
API_<MODULENAME>_USERNAME
). Using generic environment variables
like API_USERNAME
would conflict between modules.For a checklist and details on how to write Windows modules please see Windows Ansible Module Development Walkthrough
Starting in 1.8, you can deprecate modules by renaming them with a preceding _
, i.e. old_cloud.py
to
_old_cloud.py
. This keeps the module available, but hides it from the primary docs and listing.
When deprecating a module:
Set the ANSIBLE_METADATA
status to deprecated.
In the DOCUMENTATION
section, add a deprecated field along the lines of:
deprecated: Deprecated in 2.3. Use M(whatmoduletouseinstead) instead.
Add the deprecation to CHANGELOG.md under the ###Deprecations:
section.
You can also rename modules and keep an alias to the old name by using a symlink that starts with _. This example allows the stat module to be called with fileinfo, making the following examples equivalent:
EXAMPLES = '''
ln -s stat.py _fileinfo.py
ansible -m stat -a "path=/tmp" localhost
ansible -m fileinfo -a "path=/tmp" localhost
'''