mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add DOCUMENTATION for module documentation.
This commit is contained in:
parent
dfaef8061a
commit
4b04d7a914
3 changed files with 118 additions and 19 deletions
1
docsite/DOCUMENTATION.yaml
Symbolic link
1
docsite/DOCUMENTATION.yaml
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../examples/DOCUMENTATION.yaml
|
|
@ -1,10 +1,10 @@
|
||||||
Module Development
|
Module Development
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Ansible modules are reusable units of magic that can be used by the Ansible API,
|
Ansible modules are reusable units of magic that can be used by the Ansible API,
|
||||||
or by the `ansible` or `ansible-playbook` programs.
|
or by the `ansible` or `ansible-playbook` programs.
|
||||||
|
|
||||||
Modules can be written in any language and are found in the path specified
|
Modules can be written in any language and are found in the path specified
|
||||||
by `ANSIBLE_LIBRARY_PATH` or the ``--module-path`` command line option.
|
by `ANSIBLE_LIBRARY_PATH` or the ``--module-path`` command line option.
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
@ -12,19 +12,19 @@ by `ANSIBLE_LIBRARY_PATH` or the ``--module-path`` command line option.
|
||||||
:backlinks: top
|
:backlinks: top
|
||||||
|
|
||||||
|
|
||||||
Tutorial
|
Tutorial
|
||||||
````````
|
````````
|
||||||
Let's build a module to get and set the system time. For starters, let's build
|
Let's build a module to get and set the system time. For starters, let's build
|
||||||
a module that just outputs the current time.
|
a module that just outputs the current time.
|
||||||
|
|
||||||
We are going to use Python here but any language is possible. Only File I/O and outputing to standard
|
We are going to use Python here but any language is possible. Only File I/O and outputing to standard
|
||||||
out are required. So, bash, C++, clojure, Python, Ruby, whatever you want
|
out are required. So, bash, C++, clojure, Python, Ruby, whatever you want
|
||||||
is fine.
|
is fine.
|
||||||
|
|
||||||
Now Python Ansible modules contain some extremely powerful shortcuts (that all the core modules use)
|
Now Python Ansible modules contain some extremely powerful shortcuts (that all the core modules use)
|
||||||
but first we are going to build a module the very hard way. The reason we do this is because modules
|
but first we are going to build a module the very hard way. The reason we do this is because modules
|
||||||
written in any language OTHER than Python are going to have to do exactly this. We'll show the easy
|
written in any language OTHER than Python are going to have to do exactly this. We'll show the easy
|
||||||
way later.
|
way later.
|
||||||
|
|
||||||
So, here's an example. You would never really need to build a module to set the system time,
|
So, here's an example. You would never really need to build a module to set the system time,
|
||||||
the 'command' module could already be used to do this. Though we're going to make one.
|
the 'command' module could already be used to do this. Though we're going to make one.
|
||||||
|
@ -107,13 +107,13 @@ a lot shorter than this::
|
||||||
# this is up to each module to decide what it wants, but all
|
# this is up to each module to decide what it wants, but all
|
||||||
# core modules besides 'command' and 'shell' take key=value
|
# core modules besides 'command' and 'shell' take key=value
|
||||||
# so this is highly recommended
|
# so this is highly recommended
|
||||||
|
|
||||||
arguments = shlex.split(args_data)
|
arguments = shlex.split(args_data)
|
||||||
for arg in arguments:
|
for arg in arguments:
|
||||||
|
|
||||||
# ignore any arguments without an equals in it
|
# ignore any arguments without an equals in it
|
||||||
if arg.find("=") != -1:
|
if arg.find("=") != -1:
|
||||||
|
|
||||||
(key, value) = arg.split("=")
|
(key, value) = arg.split("=")
|
||||||
|
|
||||||
# if setting the time, the key 'time'
|
# if setting the time, the key 'time'
|
||||||
|
@ -148,10 +148,10 @@ a lot shorter than this::
|
||||||
|
|
||||||
# when things do not fail, we do not
|
# when things do not fail, we do not
|
||||||
# have any restrictions on what kinds of
|
# have any restrictions on what kinds of
|
||||||
# data are returned, but it's always a
|
# data are returned, but it's always a
|
||||||
# good idea to include whether or not
|
# good idea to include whether or not
|
||||||
# a change was made, as that will allow
|
# a change was made, as that will allow
|
||||||
# notifiers to be used in playbooks.
|
# notifiers to be used in playbooks.
|
||||||
|
|
||||||
date = str(datetime.datetime.now())
|
date = str(datetime.datetime.now())
|
||||||
print json.dumps({
|
print json.dumps({
|
||||||
|
@ -160,7 +160,7 @@ a lot shorter than this::
|
||||||
})
|
})
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# if no parameters are sent, the module may or
|
# if no parameters are sent, the module may or
|
||||||
# may not error out, this one will just
|
# may not error out, this one will just
|
||||||
# return the time
|
# return the time
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ As mentioned, if you are writing a module in Python, there are some very powerfu
|
||||||
Modules are still transferred as one file, but an arguments file is no longer needed, so these are not
|
Modules are still transferred as one file, but an arguments file is no longer needed, so these are not
|
||||||
only shorter in terms of code, they are actually FASTER in terms of execution time.
|
only shorter in terms of code, they are actually FASTER in terms of execution time.
|
||||||
|
|
||||||
Rather than mention these here, the best way to learn is to read some of the `source of the modules <https://github.com/ansible/ansible/tree/devel/library>`_ that come with Ansible.
|
Rather than mention these here, the best way to learn is to read some of the `source of the modules <https://github.com/ansible/ansible/tree/devel/library>`_ that come with Ansible.
|
||||||
|
|
||||||
The 'group' and 'user' modules are reasonably non-trival and showcase what this looks like.
|
The 'group' and 'user' modules are reasonably non-trival and showcase what this looks like.
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ And failures are just as simple (where 'msg' is a required parameter to explain
|
||||||
|
|
||||||
module.fail_json(msg="Something fatal happened")
|
module.fail_json(msg="Something fatal happened")
|
||||||
|
|
||||||
There are also other useful functions in the module class, such as module.md5(path). See
|
There are also other useful functions in the module class, such as module.md5(path). See
|
||||||
lib/ansible/module_common.py in the source checkout for implementation details.
|
lib/ansible/module_common.py in the source checkout for implementation details.
|
||||||
|
|
||||||
Again, modules developed this way are best tested with the hacking/test-module script in the git
|
Again, modules developed this way are best tested with the hacking/test-module script in the git
|
||||||
|
@ -255,7 +255,7 @@ Common Pitfalls
|
||||||
You should also never do this in a module::
|
You should also never do this in a module::
|
||||||
|
|
||||||
print "some status message"
|
print "some status message"
|
||||||
|
|
||||||
Because the output is supposed to be valid JSON. Except that's not quite true,
|
Because the output is supposed to be valid JSON. Except that's not quite true,
|
||||||
but we'll get to that later.
|
but we'll get to that later.
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ and guidelines:
|
||||||
|
|
||||||
* If the module is addressing an object, the parameter for that object should be called 'name' whenever possible, or accept 'name' as an alias.
|
* If the module is addressing an object, the parameter for that object should be called 'name' whenever possible, or accept 'name' as an alias.
|
||||||
|
|
||||||
* If you have a company module that returns facts specific to your installations, a good name for this module is `site_facts`.
|
* If you have a company module that returns facts specific to your installations, a good name for this module is `site_facts`.
|
||||||
|
|
||||||
* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "choices=BOOLEANS" and a module.boolean(value) casting function.
|
* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "choices=BOOLEANS" and a module.boolean(value) casting function.
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ and guidelines:
|
||||||
|
|
||||||
* In the event of failure, a key of 'failed' should be included, along with a string explanation in 'msg'. Modules that raise tracebacks (stacktraces) are generally considered 'poor' modules, though Ansible can deal with these returns and will automatically convert anything unparseable into a failed result. If you are using the AnsibleModule common Python code, the 'failed' element will be included for you automatically when you call 'fail_json'.
|
* In the event of failure, a key of 'failed' should be included, along with a string explanation in 'msg'. Modules that raise tracebacks (stacktraces) are generally considered 'poor' modules, though Ansible can deal with these returns and will automatically convert anything unparseable into a failed result. If you are using the AnsibleModule common Python code, the 'failed' element will be included for you automatically when you call 'fail_json'.
|
||||||
|
|
||||||
* Return codes from modules are not actually not signficant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
|
* Return codes from modules are not actually not signficant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
|
||||||
|
|
||||||
* As results from many hosts will be aggregrated at once, modules should return only relevant output. Returning the entire contents of a log file is generally bad form.
|
* As results from many hosts will be aggregrated at once, modules should return only relevant output. Returning the entire contents of a log file is generally bad form.
|
||||||
|
|
||||||
|
@ -310,6 +310,72 @@ If you're writing a module in Python or Ruby or whatever, though, returning
|
||||||
JSON is probably the simplest way to go.
|
JSON is probably the simplest way to go.
|
||||||
|
|
||||||
|
|
||||||
|
Documenting Your Module
|
||||||
|
```````````````````````
|
||||||
|
|
||||||
|
All modules included in the CORE distribution must have a
|
||||||
|
``DOCUMENTATION`` string. This string MUST be a valid YAML document
|
||||||
|
which conforms to the schema defined below. You may find it easier to
|
||||||
|
start writing your ``DOCUMENTATION`` string in an editor with YAML
|
||||||
|
syntax highlighting before you include it in your Python file.
|
||||||
|
|
||||||
|
Example
|
||||||
|
+++++++
|
||||||
|
|
||||||
|
Here's a correctly formatted YAML document we could use for a
|
||||||
|
``DOCUMENTATION`` string:
|
||||||
|
|
||||||
|
.. literalinclude:: ../DOCUMENTATION.yaml
|
||||||
|
|
||||||
|
This is available in the 'examples/' directory of the of the Ansible
|
||||||
|
github repository. You can copy it into your module and use it as a
|
||||||
|
starting point when writing your own docs.
|
||||||
|
|
||||||
|
Include it in your module file like this::
|
||||||
|
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright header....
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: modulename
|
||||||
|
short_description: This is a sentence describing the module
|
||||||
|
# ... snip ...
|
||||||
|
examples:
|
||||||
|
- code: modulename opt1=arg1 opt2=arg2
|
||||||
|
description: Optional words describing this example
|
||||||
|
'''
|
||||||
|
|
||||||
|
Building & Testing
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
Put your completed module file into the 'library' directory and then
|
||||||
|
run the command: ``make webdocs``. The new 'modules.html' file will be
|
||||||
|
built and appear in the 'docsite/' directory.
|
||||||
|
|
||||||
|
You can also test-build your docs one-by-one using the
|
||||||
|
``module_formatter.py`` script:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ ./hacking/module_formatter.py -t man -M library/ -m git > ansible-git.1
|
||||||
|
$ man ./ansible-git.1
|
||||||
|
|
||||||
|
This will build a manpage for the git module, and look in the
|
||||||
|
'library/' directory for the module source. To see all the other
|
||||||
|
output formats available:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ ./hacking/module_formatter.py -t --help
|
||||||
|
|
||||||
|
|
||||||
|
.. tip::
|
||||||
|
|
||||||
|
If you're having a problem with the syntax of your YAML you can
|
||||||
|
validate it on the `YAML Lint <http://www.yamllint.com/>`_ website.
|
||||||
|
|
||||||
|
|
||||||
Sharing Your Module
|
Sharing Your Module
|
||||||
```````````````````
|
```````````````````
|
||||||
|
|
||||||
|
@ -317,7 +383,7 @@ If you think your module is generally useful to others, a good place to share it
|
||||||
is in `Ansible Resources <https://github.com/ansible/ansible/tree/devel/contrib>`_. This is maintained
|
is in `Ansible Resources <https://github.com/ansible/ansible/tree/devel/contrib>`_. This is maintained
|
||||||
as a simple repo with pointers to other github projects.
|
as a simple repo with pointers to other github projects.
|
||||||
|
|
||||||
Contrib modules here can be implemented in a variety of languages.
|
Contrib modules here can be implemented in a variety of languages.
|
||||||
We would like to build up as many of these as possible in as many languages as possible.
|
We would like to build up as many of these as possible in as many languages as possible.
|
||||||
|
|
||||||
`Ansible Mailing List <http://groups.google.com/group/ansible-project>`_
|
`Ansible Mailing List <http://groups.google.com/group/ansible-project>`_
|
||||||
|
@ -325,7 +391,7 @@ We would like to build up as many of these as possible in as many languages as p
|
||||||
Getting Your Module Into Core
|
Getting Your Module Into Core
|
||||||
`````````````````````````````
|
`````````````````````````````
|
||||||
|
|
||||||
High-quality modules with minimal dependencies
|
High-quality modules with minimal dependencies
|
||||||
can be included in the core, but core modules (just due to the programming
|
can be included in the core, but core modules (just due to the programming
|
||||||
preferences of the developers) will need to be implemented in Python and use
|
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 AnsibleModule common code, and should generally use consistent arguments with the rest of
|
||||||
|
@ -343,4 +409,3 @@ the program. Stop by the mailing list to inquire about requirements.
|
||||||
Questions? Help? Ideas? Stop by the list on Google Groups
|
Questions? Help? Ideas? Stop by the list on Google Groups
|
||||||
`irc.freenode.net <http://irc.freenode.net>`_
|
`irc.freenode.net <http://irc.freenode.net>`_
|
||||||
#ansible IRC chat channel
|
#ansible IRC chat channel
|
||||||
|
|
||||||
|
|
33
examples/DOCUMENTATION.yaml
Normal file
33
examples/DOCUMENTATION.yaml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
# If a key doesn't apply to your module (ex: choices, default, or
|
||||||
|
# aliases) you can use the word 'null', or an empty list, [], where
|
||||||
|
# appropriate.
|
||||||
|
module: modulename
|
||||||
|
short_description: This is a sentence describing the module
|
||||||
|
description:
|
||||||
|
- Longer description of the module
|
||||||
|
- You might include instructions
|
||||||
|
version_added: 0.X
|
||||||
|
author: Your AWESOME name here
|
||||||
|
notes:
|
||||||
|
- Other things consumers of your module should know
|
||||||
|
requirements:
|
||||||
|
- list of required things
|
||||||
|
- like the factor package
|
||||||
|
- or a specic platform
|
||||||
|
options:
|
||||||
|
# One or more of the following
|
||||||
|
option_name:
|
||||||
|
description:
|
||||||
|
- Words go here
|
||||||
|
- that describe
|
||||||
|
- this option
|
||||||
|
required: true or false
|
||||||
|
default: a string or the word null
|
||||||
|
choices: [list, of, choices]
|
||||||
|
aliases: [list, of, aliases]
|
||||||
|
version_added: 0.X
|
||||||
|
examples:
|
||||||
|
# One or more of the following:
|
||||||
|
- code: modulename opt1=arg1 opt2=arg2
|
||||||
|
description: Optional words describing this example
|
Loading…
Reference in a new issue