Skip to content

Commit f009a2f

Browse files
felixfonteinacozine
authored andcommitted
Read and generate role documentation.
Co-authored-by: Alicia Cozine <[email protected]>
1 parent d44438a commit f009a2f

File tree

14 files changed

+667
-23
lines changed

14 files changed

+667
-23
lines changed

antsibull/augment_docs.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,10 @@ def augment_docs(plugin_info: t.MutableMapping[str, t.MutableMapping[str, t.Any]
5656
"""
5757
for plugin_type, plugin_map in plugin_info.items():
5858
for plugin_name, plugin_record in plugin_map.items():
59-
add_full_key(plugin_record['return'], 'contains')
60-
add_full_key(plugin_record['doc']['options'], 'suboptions')
59+
if 'return' in plugin_record:
60+
add_full_key(plugin_record['return'], 'contains')
61+
if 'doc' in plugin_record:
62+
add_full_key(plugin_record['doc']['options'], 'suboptions')
63+
if 'entry_points' in plugin_record:
64+
for entry_point in plugin_record['entry_points'].values():
65+
add_full_key(entry_point['options'], 'options')

antsibull/cli/doc_commands/stable.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,14 @@ def normalize_plugin_info(plugin_type: str,
117117
in :mod:`antsibull.schemas.docs`. The nonfatal errors are strings representing the problems
118118
encountered.
119119
"""
120-
new_info = {}
121120
errors = []
121+
if plugin_type == 'role':
122+
try:
123+
return DOCS_SCHEMAS[plugin_type].parse_obj(plugin_info).dict(by_alias=True), errors
124+
except ValidationError as e:
125+
raise ValueError(str(e))
126+
127+
new_info = {}
122128
# Note: loop through "doc" before any other keys.
123129
for field in ('doc', 'examples', 'return'):
124130
try:
@@ -224,8 +230,13 @@ def get_plugin_contents(plugin_info: t.Mapping[str, t.Mapping[str, t.Any]],
224230
for plugin_type, plugin_list in plugin_info.items():
225231
for plugin_name, plugin_desc in plugin_list.items():
226232
namespace, collection, short_name = get_fqcn_parts(plugin_name)
227-
plugin_contents[plugin_type]['.'.join((namespace, collection))][short_name] = (
228-
plugin_desc['doc']['short_description'])
233+
if plugin_type == 'role':
234+
desc = ''
235+
if 'main' in plugin_desc['entry_points']:
236+
desc = plugin_desc['entry_points']['main']['short_description']
237+
else:
238+
desc = plugin_desc['doc']['short_description']
239+
plugin_contents[plugin_type]['.'.join((namespace, collection))][short_name] = desc
229240

230241
return plugin_contents
231242

antsibull/constants.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@
44
# Copyright: Ansible Project, 2020
55
"""Constant values for use throughout the antsibull codebase."""
66

7-
from typing import FrozenSet
7+
from typing import Dict, FrozenSet
88

99

1010
#: All the types of ansible plugins
1111
PLUGIN_TYPES: FrozenSet[str] = frozenset(('become', 'cache', 'callback', 'cliconf', 'connection',
1212
'httpapi', 'inventory', 'lookup', 'shell', 'strategy',
13-
'vars', 'module', 'module_utils',))
13+
'vars', 'module', 'module_utils', 'role',))
1414

1515
#: The subset of PLUGINS which we build documentation for
1616
DOCUMENTABLE_PLUGINS: FrozenSet[str] = frozenset(('become', 'cache', 'callback', 'cliconf',
1717
'connection', 'httpapi', 'inventory', 'lookup',
1818
'netconf', 'shell', 'vars', 'module',
19-
'strategy',))
19+
'strategy', 'role',))
20+
21+
22+
DOCUMENTABLE_PLUGINS_MIN_VERSION: Dict[str, str] = {
23+
'role': '2.11.0',
24+
}

antsibull/data/collection-enum.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,40 @@ def load_all_plugins(plugin_type, basedir, coll_filter):
128128
return result
129129

130130

131+
def load_role(role_mixin, role_name, collection_name, collection_path):
132+
result = {
133+
'directory': collection_path,
134+
'collection_name': collection_name,
135+
}
136+
137+
argspec = role_mixin._load_argspec(role_name, collection_path=collection_path)
138+
fqcn, ansible_doc = role_mixin._build_doc(
139+
role_name, collection_path, collection_name, argspec, None)
140+
141+
try:
142+
# If this fails, the documentation cannot be serialized as JSON
143+
json.dumps(ansible_doc, cls=AnsibleJSONEncoder)
144+
# Store result. This is guaranteed to be serializable
145+
result['ansible-doc'] = ansible_doc
146+
except Exception as e:
147+
result['error'] = (
148+
'Cannot serialize documentation as JSON: %s' % to_native(e)
149+
)
150+
151+
return result
152+
153+
154+
def load_all_roles(RoleMixin, basedir, coll_filter):
155+
role_mixin = RoleMixin()
156+
roles = role_mixin._find_all_collection_roles()
157+
result = {}
158+
for role_name, collection_name, collection_path in roles:
159+
fqcn = '{1}.{0}'.format(role_name, collection_name)
160+
if match_filter(fqcn, coll_filter):
161+
result[fqcn] = load_role(role_mixin, role_name, collection_name, collection_path)
162+
return result
163+
164+
131165
def load_collection_meta_manifest(b_manifest_path):
132166
with open(b_manifest_path, 'rb') as f:
133167
meta = json.load(f)
@@ -195,6 +229,13 @@ def main(args):
195229
for plugin_type in C.DOCUMENTABLE_PLUGINS:
196230
result['plugins'][plugin_type] = load_all_plugins(plugin_type, basedir, coll_filter)
197231

232+
# Export role docs
233+
RoleMixin = getattr(doc, 'RoleMixin', None)
234+
if RoleMixin is not None:
235+
result['plugins']['role'] = load_all_roles(RoleMixin, basedir, coll_filter)
236+
else:
237+
result['plugins']['role'] = {}
238+
198239
# Export collection data
199240
b_colldirs = list_collection_dirs(coll_filter=ansible_doc_coll_filter(coll_filter))
200241
for b_path in b_colldirs:

antsibull/data/docsite/list_of_plugins.rst.j2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
{% if plugin_type == 'module' %}
66
Index of all Modules
77
====================
8+
{% elif plugin_type == 'role' %}
9+
Index of all Roles
10+
==================
811
{% else %}
912
Index of all @{ plugin_type | capitalize }@ Plugins
1013
=============@{ '=' * (plugin_type | length) }@========

antsibull/data/docsite/plugins_by_collection.rst.j2

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,20 @@ Collection version @{ collection_version }@
3232
Plugin Index
3333
------------
3434

35-
{% if plugin_maps %}
35+
{% if plugin_maps | reject('eq', 'role') | list %}
3636
These are the plugins in the @{collection_name}@ collection
3737
{% else %}
3838
There are no plugins in the @{collection_name}@ collection with automatically generated documentation.
3939
{% endif %}
4040

41-
{% for category, plugins in plugin_maps.items() | sort %}
41+
{% for category, plugins in plugin_maps.items() | sort | rejectattr('0', 'eq', 'role') %}
4242

4343
{% if category == 'module' %}
4444
Modules
4545
~~~~~~~
46+
{% elif category == 'role' %}
47+
Roles
48+
~~~~~
4649
{% else %}
4750
@{ category | capitalize }@ Plugins
4851
@{ '~' * ((category | length) + 8) }@
@@ -53,6 +56,18 @@ Modules
5356
{% endfor %}
5457
{% endfor %}
5558

59+
{% if 'role' in plugin_maps %}
60+
Role Index
61+
----------
62+
63+
These are the roles in the @{collection_name}@ collection
64+
65+
{% for name, desc in plugin_maps['role'].items() | sort %}
66+
* :ref:`@{ name }@ <ansible_collections.@{ collection_name }@.@{ name }@_role>` -- @{ desc | rst_ify | indent(width=2) }@
67+
{% endfor %}
68+
69+
{% endif %}
70+
5671

5772
.. seealso::
5873

0 commit comments

Comments
 (0)