Skip to content

Commit eeb7898

Browse files
committed
Hide private plugins.
1 parent 5bb7bc5 commit eeb7898

File tree

17 files changed

+1413
-25
lines changed

17 files changed

+1413
-25
lines changed

changelogs/fragments/65-private.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
minor_changes:
2+
- "Supports hiding private plugins (https://github.com/ansible-community/antsibull-docs/pull/65)."

src/antsibull_docs/cli/doc_commands/_build.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def generate_docs_for_all_collections(venv: t.Union[VenvRunner, FakeVenvRunner],
165165
breadcrumbs=breadcrumbs,
166166
for_official_docsite=for_official_docsite))
167167
flog.notice('Finished writing collection namespace index')
168-
asyncio_run(output_plugin_indexes(plugin_contents, dest_dir,
168+
asyncio_run(output_plugin_indexes(plugin_contents, collection_metadata, dest_dir,
169169
collection_url=collection_url,
170170
collection_install=collection_install,
171171
for_official_docsite=for_official_docsite))

src/antsibull_docs/data/docsite/list_of_plugins.rst.j2

+2
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ Index of all @{ plugin_type | capitalize }@ Plugins
3737
* :ref:`@{ collection_name }@.@{ plugin_name }@ <ansible_collections.@{ collection_name }@.@{ plugin_name }@_@{ plugin_type }@>` -- @{ plugin_desc | rst_ify(plugin_fqcn=collection_name ~ '.' ~ plugin_name, plugin_type=plugin_type) }@
3838
{% endfor %}
3939

40+
{% else %}
41+
No public {% if plugin_type == 'module' %}module{% elif plugin_type == 'role' %}role{% else %}@{ plugin_type }@ plugin{% endif %} found.
4042
{% endfor %}

src/antsibull_docs/docs_parsing/__init__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,17 @@ class AnsibleCollectionMetadata:
7474
path: str
7575
version: t.Optional[str]
7676
requires_ansible: t.Optional[str]
77+
private_plugins: t.Mapping[str, t.List[str]] # mapping plugin_type to FQCNs
7778

7879
def __init__(self,
7980
path: str,
8081
version: t.Optional[str] = None,
81-
requires_ansible: t.Optional[str] = None):
82+
requires_ansible: t.Optional[str] = None,
83+
private_plugins: t.Optional[t.Mapping[str, t.List[str]]] = None):
8284
self.path = path
8385
self.version = version
8486
self.requires_ansible = requires_ansible
87+
self.private_plugins = private_plugins or {}
8588

8689
def __repr__(self):
8790
return f'AnsibleCollectionMetadata({repr(self.path)}, {repr(self.version)})'

src/antsibull_docs/docs_parsing/routing.py

+31-18
Original file line numberDiff line numberDiff line change
@@ -212,41 +212,54 @@ def load_meta_runtime(collection_name: str,
212212
return meta_runtime
213213

214214

215+
def _add_symlink_redirects(collection_name: str,
216+
collection_metadata: AnsibleCollectionMetadata,
217+
plugin_routing_out: t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]]
218+
) -> None:
219+
for plugin_type in DOCUMENTABLE_PLUGINS:
220+
directory_name = 'modules' if plugin_type == 'module' else plugin_type
221+
directory_path = os.path.join(collection_metadata.path, 'plugins', directory_name)
222+
plugin_type_routing = plugin_routing_out[plugin_type]
223+
224+
symlink_redirects = find_symlink_redirects(collection_name, plugin_type, directory_path)
225+
for redirect_name, redirect_dst in symlink_redirects.items():
226+
if redirect_name not in plugin_type_routing:
227+
plugin_type_routing[redirect_name] = {}
228+
if 'redirect' not in plugin_type_routing[redirect_name]:
229+
plugin_type_routing[redirect_name]['redirect'] = redirect_dst
230+
if plugin_type_routing[redirect_name]['redirect'] == redirect_dst:
231+
plugin_type_routing[redirect_name]['redirect_is_symlink'] = True
232+
233+
215234
async def load_collection_routing(collection_name: str,
216235
collection_metadata: AnsibleCollectionMetadata
217236
) -> t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]]:
218237
"""
219-
Load plugin routing for a collection.
238+
Load plugin routing for a collection, and populate the private plugins lists
239+
in collection metadata.
220240
"""
221241
meta_runtime = load_meta_runtime(collection_name, collection_metadata)
222242
plugin_routing_out: t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]] = {}
223243
plugin_routing_in = meta_runtime.get('plugin_routing') or {}
244+
private_plugins: t.Dict[str, t.List[str]] = {}
245+
collection_metadata.private_plugins = private_plugins
224246
for plugin_type in DOCUMENTABLE_PLUGINS:
225247
plugin_type_id = 'modules' if plugin_type == 'module' else plugin_type
226248
plugin_type_routing = plugin_routing_in.get(plugin_type_id) or {}
227-
plugin_routing_out[plugin_type] = {
228-
f'{collection_name}.{plugin_name}': process_dates(plugin_record)
229-
for plugin_name, plugin_record in plugin_type_routing.items()
230-
}
249+
plugin_routing_out[plugin_type] = {}
250+
private_plugins[plugin_type] = []
251+
for plugin_name, plugin_record in plugin_type_routing.items():
252+
fqcn = f'{collection_name}.{plugin_name}'
253+
plugin_routing_out[plugin_type][fqcn] = process_dates(plugin_record)
254+
if plugin_record.get('private', False):
255+
private_plugins[plugin_type].append(plugin_name)
231256

232257
if collection_name == 'ansible.builtin':
233258
# ansible-core has a special directory structure we currently do not want
234259
# (or need) to handle
235260
return plugin_routing_out
236261

237-
for plugin_type in DOCUMENTABLE_PLUGINS:
238-
directory_name = 'modules' if plugin_type == 'module' else plugin_type
239-
directory_path = os.path.join(collection_metadata.path, 'plugins', directory_name)
240-
plugin_type_routing = plugin_routing_out[plugin_type]
241-
242-
symlink_redirects = find_symlink_redirects(collection_name, plugin_type, directory_path)
243-
for redirect_name, redirect_dst in symlink_redirects.items():
244-
if redirect_name not in plugin_type_routing:
245-
plugin_type_routing[redirect_name] = {}
246-
if 'redirect' not in plugin_type_routing[redirect_name]:
247-
plugin_type_routing[redirect_name]['redirect'] = redirect_dst
248-
if plugin_type_routing[redirect_name]['redirect'] == redirect_dst:
249-
plugin_type_routing[redirect_name]['redirect_is_symlink'] = True
262+
_add_symlink_redirects(collection_name, collection_metadata, plugin_routing_out)
250263

251264
if collection_name in COLLECTIONS_WITH_FLATMAPPING:
252265
remove_flatmapping_artifacts(plugin_routing_out)

src/antsibull_docs/write_docs/collections.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,22 @@ async def write_plugin_lists(collection_name: str,
9292
'Cannot parse required_ansible specifier set for {collection_name}',
9393
collection_name=collection_name,
9494
)
95+
96+
public_plugin_maps: t.Dict[str, t.Mapping[str, str]] = {}
97+
for plugin_type, plugin_data in plugin_maps.items():
98+
private_plugins = collection_meta.private_plugins.get(plugin_type) or []
99+
public_plugin_data = {}
100+
for plugin_name, plugin_info in plugin_data.items():
101+
if plugin_name not in private_plugins:
102+
public_plugin_data[plugin_name] = plugin_info
103+
if public_plugin_data:
104+
public_plugin_maps[plugin_type] = public_plugin_data
105+
95106
index_contents = _render_template(
96107
template,
97108
dest_dir,
98109
collection_name=collection_name,
99-
plugin_maps=plugin_maps,
110+
plugin_maps=public_plugin_maps,
100111
collection_version=collection_meta.version,
101112
requires_ansible=requires_ansible,
102113
link_data=link_data,

src/antsibull_docs/write_docs/indexes.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from antsibull_core.utils.io import write_file
1717
from jinja2 import Template
1818

19+
from ..docs_parsing import AnsibleCollectionMetadata
1920
from ..env_variables import EnvironmentVariableInfo
2021
from ..jinja2.environment import doc_environment
2122
from ..utils.collection_name_transformer import CollectionNameTransformer
@@ -53,6 +54,7 @@ async def write_callback_type_index(callback_type: str,
5354

5455
async def write_plugin_type_index(plugin_type: str,
5556
per_collection_plugins: t.Mapping[str, t.Mapping[str, str]],
57+
collection_metadata: t.Mapping[str, AnsibleCollectionMetadata],
5658
template: Template,
5759
dest_filename: str,
5860
for_official_docsite: bool = False) -> None:
@@ -62,16 +64,28 @@ async def write_plugin_type_index(plugin_type: str,
6264
:arg plugin_type: The plugin type to write the index for.
6365
:arg per_collection_plugins: Mapping of collection_name to Mapping of plugin_name to
6466
short_description.
67+
:arg collection_metadata: Dictionary mapping collection names to collection metadata objects.
6568
:arg template: A template to render the plugin index.
6669
:arg dest_filename: The destination filename.
6770
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
6871
official docsite on docs.ansible.com.
6972
"""
73+
public_per_collection_plugins = {}
74+
for collection_name, plugins in per_collection_plugins.items():
75+
public_plugins = {}
76+
collection_meta = collection_metadata[collection_name]
77+
private_plugins = collection_meta.private_plugins.get(plugin_type) or []
78+
for plugin_name, plugin_data in plugins.items():
79+
if plugin_name not in private_plugins:
80+
public_plugins[plugin_name] = plugin_data
81+
if public_plugins:
82+
public_per_collection_plugins[collection_name] = public_plugins
83+
7084
index_contents = _render_template(
7185
template,
7286
dest_filename,
7387
plugin_type=plugin_type,
74-
per_collection_plugins=per_collection_plugins,
88+
per_collection_plugins=public_per_collection_plugins,
7589
for_official_docsite=for_official_docsite,
7690
)
7791

@@ -126,6 +140,7 @@ async def output_callback_indexes(plugin_info: PluginCollectionInfoT,
126140

127141

128142
async def output_plugin_indexes(plugin_info: PluginCollectionInfoT,
143+
collection_metadata: t.Mapping[str, AnsibleCollectionMetadata],
129144
dest_dir: str,
130145
collection_url: CollectionNameTransformer,
131146
collection_install: CollectionNameTransformer,
@@ -135,6 +150,7 @@ async def output_plugin_indexes(plugin_info: PluginCollectionInfoT,
135150
136151
:arg plugin_info: Mapping of plugin_type to Mapping of collection_name to Mapping of
137152
plugin_name to short_description.
153+
:arg collection_metadata: Dictionary mapping collection names to collection metadata objects.
138154
:arg dest_dir: The directory to place the documentation in.
139155
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
140156
official docsite on docs.ansible.com.
@@ -163,8 +179,8 @@ async def output_plugin_indexes(plugin_info: PluginCollectionInfoT,
163179
filename = os.path.join(collection_toplevel, f'index_{plugin_type}.rst')
164180
writers.append(await pool.spawn(
165181
write_plugin_type_index(
166-
plugin_type, per_collection_data, plugin_list_tmpl, filename,
167-
for_official_docsite=for_official_docsite)))
182+
plugin_type, per_collection_data, collection_metadata, plugin_list_tmpl,
183+
filename, for_official_docsite=for_official_docsite)))
168184

169185
await asyncio.gather(*writers)
170186

tests/functional/ansible-doc-cache-all.json

+33
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,39 @@
10081008
}
10091009
},
10101010
"lookup": {
1011+
"ns2.col.bar": {
1012+
"doc": {
1013+
"author": "Felix Fontein (@felixfontein)",
1014+
"collection": "ns2.col",
1015+
"description": [
1016+
"This one is private."
1017+
],
1018+
"filename": "ansible_collections/ns2/col/plugins/lookup/bar.py",
1019+
"name": "bar",
1020+
"options": {
1021+
"_terms": {
1022+
"description": "Something",
1023+
"elements": "dict",
1024+
"required": true,
1025+
"type": "list"
1026+
}
1027+
},
1028+
"short_description": "Look up some bar",
1029+
"version_added": "1.0.0",
1030+
"version_added_collection": "ns2.col"
1031+
},
1032+
"examples": "\n- name: Look up!\n ansible.builtin.debug:\n msg: \"{{ lookup('ns2.col.bar', {}) }}\"\n",
1033+
"metadata": null,
1034+
"return": {
1035+
"_raw": {
1036+
"description": [
1037+
"The resulting stuff."
1038+
],
1039+
"elements": "dict",
1040+
"type": "list"
1041+
}
1042+
}
1043+
},
10111044
"ns2.col.foo": {
10121045
"doc": {
10131046
"author": "Felix Fontein (@felixfontein)",

tests/functional/ansible-doc-cache-ns2.col.json

+33
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,39 @@
10081008
}
10091009
},
10101010
"lookup": {
1011+
"ns2.col.bar": {
1012+
"doc": {
1013+
"author": "Felix Fontein (@felixfontein)",
1014+
"collection": "ns2.col",
1015+
"description": [
1016+
"This one is private."
1017+
],
1018+
"filename": "ansible_collections/ns2/col/plugins/lookup/bar.py",
1019+
"name": "bar",
1020+
"options": {
1021+
"_terms": {
1022+
"description": "Something",
1023+
"elements": "dict",
1024+
"required": true,
1025+
"type": "list"
1026+
}
1027+
},
1028+
"short_description": "Look up some bar",
1029+
"version_added": "1.0.0",
1030+
"version_added_collection": "ns2.col"
1031+
},
1032+
"examples": "\n- name: Look up!\n ansible.builtin.debug:\n msg: \"{{ lookup('ns2.col.bar', {}) }}\"\n",
1033+
"metadata": null,
1034+
"return": {
1035+
"_raw": {
1036+
"description": [
1037+
"The resulting stuff."
1038+
],
1039+
"elements": "dict",
1040+
"type": "list"
1041+
}
1042+
}
1043+
},
10111044
"ns2.col.foo": {
10121045
"doc": {
10131046
"author": "Felix Fontein (@felixfontein)",

tests/functional/ansible-version.output

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ansible [core 2.15.0b1.post0] (stable-2.15 8f0ddcba2c) last updated 2023/04/06 20:47:29 (GMT +200)
1+
ansible [core 2.16.0.dev0] (devel 88a380c8f0) last updated 2023/04/06 20:47:05 (GMT +200)
22
config file = None
33
configured module search path = ['<<<<<HOME>>>>>/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
44
ansible python module location = <<<<<ANSIBLE>>>>>

0 commit comments

Comments
 (0)