Add plugin documentation

This change adds documentation for all of the plugins currently
found in the tripleo-ansible repo. This will provide for much
greater visability into what we're providing and will allow
users and developers to better understand how to consume
the available resources.

Change-Id: I2f5813095cbadd999bc68235278a9da1f883e01e
Signed-off-by: Kevin Carter <kecarter@redhat.com>
This commit is contained in:
Kevin Carter 2019-07-09 15:23:01 -05:00
parent 83543cb8aa
commit e25e9c8bc3
No known key found for this signature in database
GPG Key ID: CE94BD890A47B20A
13 changed files with 348 additions and 30 deletions

View File

@ -0,0 +1,175 @@
# Copyright 2019 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import imp
import os
from docutils import core
from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.parsers import rst
from docutils.writers.html4css1 import Writer
from sphinx import addnodes
import yaml
class AnsibleAutoPluginDirective(Directive):
directive_name = "ansibleautoplugin"
has_content = True
option_spec = {
'module': rst.directives.unchanged_required,
'documentation': rst.directives.unchanged,
'examples': rst.directives.unchanged
}
@staticmethod
def _render_html(source):
return core.publish_parts(
source=source,
writer=Writer(),
writer_name='html',
settings_overrides={'no_system_messages': True}
)
def make_node(self, title, contents, content_type=None):
section = nodes.section(
title,
nodes.title(text=title),
ids=[nodes.make_id(__file__)],
)
if not content_type:
# Doc section
for content in contents['docs']:
for paragraph in content.split('\n'):
retnode = nodes.paragraph()
html = self._render_html(source=paragraph)
retnode += nodes.raw('', html['body'], format='html')
section.append(retnode)
# Options Section
options_list = nodes.field_list()
options_section = nodes.section(
'Options',
nodes.title(text='Options'),
ids=[nodes.make_id(__file__)],
)
for key, value in contents['options'].items():
body = nodes.field_body()
if isinstance(value['description'], list):
for desc in value['description']:
html = self._render_html(source=desc)
body.append(
nodes.raw('', html['body'], format='html')
)
else:
html = self._render_html(source=value['description'])
body.append(
nodes.raw('', html['body'], format='html')
)
field = nodes.field()
field.append(nodes.field_name(text=key))
field.append(body)
options_list.append(field)
else:
options_section.append(options_list)
section.append(options_section)
# Authors Section
authors_list = nodes.field_list()
authors_section = nodes.section(
'Authors',
nodes.title(text='Authors'),
ids=[nodes.make_id(__file__)],
)
field = nodes.field()
field.append(nodes.field_name(text=''))
for author in contents['author']:
body = nodes.field_body()
html = self._render_html(source=author)
body.append(
nodes.raw('', html['body'], format='html')
)
field.append(body)
else:
authors_list.append(field)
authors_section.append(authors_list)
section.append(authors_section)
elif content_type == 'yaml':
for content in contents:
retnode = nodes.literal_block(text=content)
retnode['language'] = 'yaml'
section.append(retnode)
return section
def load_module(self, filename):
return imp.load_source('__ansible_module__', filename)
def build_documentation(self, module):
docs = yaml.safe_load(module.DOCUMENTATION)
doc_data = dict()
doc_data['docs'] = docs['description']
doc_data['author'] = docs.get('author', list())
doc_data['options'] = docs.get('options', dict())
return doc_data
def build_examples(self, module):
examples = yaml.safe_load(module.EXAMPLES)
return_examples = list()
for example in examples:
return_examples.append(
yaml.safe_dump([example], default_flow_style=False)
)
return return_examples
def run(self):
module = self.load_module(filename=self.options['module'])
return_data = list()
if self.options.get('documentation'):
docs = self.build_documentation(module=module)
return_data.append(
self.make_node(
title="Module Documentation",
contents=docs
)
)
if self.options.get('examples'):
examples = self.build_examples(module=module)
return_data.append(
self.make_node(
title="Example Tasks",
contents=examples,
content_type='yaml'
)
)
return return_data
def setup(app):
classes = [
AnsibleAutoPluginDirective,
]
for directive_class in classes:
app.add_directive(directive_class.directive_name, directive_class)
return {'version': '0.1'}

View File

@ -26,12 +26,14 @@ sys.path.insert(0, os.path.join(os.path.abspath('.'), '_exts'))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'openstackdocstheme',
'sphinx.ext.autodoc'
'sphinx.ext.autodoc',
'ansible-module-autodoc'
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# autodoc_mock_imports = ["django"]
# The suffix of source filenames.
source_suffix = '.rst'

View File

@ -144,3 +144,34 @@ test being executed and running the environment.
.. code-block:: console
(test-python) $ molecule --debug test
Contributing plugins
~~~~~~~~~~~~~~~~~~~~
All plugins contributed to the TripleO-Ansible can be found in the
`tripleo_ansible/ansible_plugins` directory, from the root of this project.
When contributing a plugin, make sure to also add documentation in the
`doc/source/modules` folder. All documentation added to this folder will be
automatically indexed and rendered via `sphinx`.
If a contributed plugin is following the Ansible practice of placing
documentation within the plugin itself, the following snippet can be used in a
sphinx template to auto-render the in-code documentation.
.. code-block:: rst
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/${DIRECTORY}/${PLUGINFILE}
:documentation: true
:examples: true
The snippet can take two options, `documentation` and `examples`. If a given
plugin does not have either of these in-code documentation objects,
documentation for either type can be disabled by omitting the option.
.. code-block:: rst
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/${DIRECTORY}/${PLUGINFILE}
:documentation: true

View File

@ -15,6 +15,7 @@ Contents:
contributing
usage
roles
modules
Indices and tables
==================

9
doc/source/modules.rst Normal file
View File

@ -0,0 +1,9 @@
Documented modules in TripleO-Ansible
=====================================
Contents:
.. toctree::
:glob:
modules/*

View File

@ -0,0 +1,14 @@
================
Module - package
================
This module provides for the following ansible plugin:
* package
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/action/package.py
:documentation: true
:examples: true

View File

@ -0,0 +1,13 @@
===================
Module - json_error
===================
This module provides for the following ansible plugin:
* json_error
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/callback/json_error.py
:documentation: true

View File

@ -0,0 +1,14 @@
=========================
Module - podman_container
=========================
This module provides for the following ansible plugin:
* podman_container
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/modules/podman_container.py
:documentation: true
:examples: true

View File

@ -0,0 +1,14 @@
=====================
Module - podman_image
=====================
This module provides for the following ansible plugin:
* podman_image
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/modules/podman_image.py
:documentation: true
:examples: false

View File

@ -0,0 +1,14 @@
===========================
Module - podman_image_facts
===========================
This module provides for the following ansible plugin:
* podman_image_facts
.. ansibleautoplugin::
:module: tripleo_ansible/ansible_plugins/modules/podman_image_facts.py
:documentation: true
:examples: true

View File

@ -95,10 +95,12 @@ commands =
[testenv:docs]
basepython = python3
deps = -r{toxinidir}/doc/requirements.txt
deps =
-r{toxinidir}/doc/requirements.txt
-r{toxinidir}/molecule-requirements.txt
commands=
doc8 doc
sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html
sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html -T
[doc8]
# Settings for doc8:

View File

@ -20,6 +20,61 @@ import os
import ansible.plugins.action as action
DOCUMENTATION = """
---
module: package
author:
- Kevin Carter (@cloudnull)
version_added: '2.8'
short_description: Tripleo action plugin to evaluate package installations
notes: []
description:
- This is an action plugin shim that will intercept the use of
the standard package module. The intention of this shim is to ensure the
package module respects the option `tripleo_enable_package_install`
which is used to control the installation of packages through a
deployment.
This plugin will do nothing if `tripleo_enable_package_install`
is unset thereby allowing ansible to function normally. When the global
option is present the plugin will evaluate its truthiness and react
accordingly.
* False - No action taken, task will be marked as skipped.
* True - Package installation happens normally.
If this module encounters an error while processesing the module will
proceed as if the option `tripleo_enable_package_install` is unset which
ensures ansible tasks are handled correctly no matter the context in
which they are executed.
Anytime this module results in a "skip" a message will be made available
which indicates why it was skipped. Messages will only be visualized
when debug mode has been enabled or through registering a variable and
using it a task which can print messages; e.g. `debug` or `fail`.
options:
tripleo_enable_package_install:
description:
- Boolean option to enable or disable package installations. This option
can be passed in as a task var, groupvar, or hostvar. This option is
**NOT** a module argument.
required: True
default: True
"""
EXAMPLES = """
# Run package install
- name: Run Package Installation
package:
name: mypackage
state: present
vars:
tripleo_enable_package_install: true
"""
# NOTE(cloudnull): imp is being used because core action plugins are not
# importable in py27. Once we get to the point where we
# no longer support py27 these lines should be converted
@ -63,32 +118,6 @@ def _bool_set(bool_opt):
class ActionModule(PKG.ActionModule):
"""Tripleo action plugin made to evaluate package installations.
This is an action plugin shim that will intercept the use of
the standard package module. The intention of this shim is to ensure the
package module respects the option `tripleo_enable_package_install`
which is used to control the installation of packages through a deployment.
This plugin will do nothing if the option `tripleo_enable_package_install`
is unset thereby allowing ansible to function normally. When the global
option is present the plugin will evaluate its truthiness and react
accordingly.
* False: No action taken, task will be marked as skipped.
* True: Package installation happens normally.
If this module encounters an error while processesing the module will
proceed as if the option `tripleo_enable_package_install` is unset which
ensures ansible tasks are handled correctly no matter the context in which
they are executed.
Anytime this module results in a "skip" a message will be made available
which indicates why it was skipped. Messages will only be visualized when
debug mode has been enabled or through registering a variable and using it
a task which can print messages; e.g. `debug` or `fail`.
"""
def run(self, tmp=None, task_vars=None):
"""Shim for tripleo package operations.