Skip to content

Commit

Permalink
Hide private plugins.
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfontein committed Apr 8, 2023
1 parent fdc47d4 commit 2daefc3
Show file tree
Hide file tree
Showing 17 changed files with 1,413 additions and 25 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/65-private.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- "Supports hiding private plugins (https://github.com/ansible-community/antsibull-docs/pull/65)."
2 changes: 1 addition & 1 deletion src/antsibull_docs/cli/doc_commands/stable.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ def generate_docs_for_all_collections(venv: t.Union[VenvRunner, FakeVenvRunner],
breadcrumbs=breadcrumbs,
for_official_docsite=for_official_docsite))
flog.notice('Finished writing collection namespace index')
asyncio_run(output_plugin_indexes(plugin_contents, dest_dir,
asyncio_run(output_plugin_indexes(plugin_contents, collection_metadata, dest_dir,
collection_url=collection_url,
collection_install=collection_install,
for_official_docsite=for_official_docsite))
Expand Down
2 changes: 2 additions & 0 deletions src/antsibull_docs/data/docsite/list_of_plugins.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ Index of all @{ plugin_type | capitalize }@ Plugins
* :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) }@
{% endfor %}

{% else %}
No public {% if plugin_type == 'module' %}module{% elif plugin_type == 'role' %}role{% else %}@{ plugin_type }@ plugin{% endif %} found.
{% endfor %}
5 changes: 4 additions & 1 deletion src/antsibull_docs/docs_parsing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,17 @@ class AnsibleCollectionMetadata:
path: str
version: t.Optional[str]
requires_ansible: t.Optional[str]
private_plugins: t.Mapping[str, t.List[str]] # mapping plugin_type to FQCNs

def __init__(self,
path: str,
version: t.Optional[str] = None,
requires_ansible: t.Optional[str] = None):
requires_ansible: t.Optional[str] = None,
private_plugins: t.Optional[t.Mapping[str, t.List[str]]] = None):
self.path = path
self.version = version
self.requires_ansible = requires_ansible
self.private_plugins = private_plugins or {}

def __repr__(self):
return f'AnsibleCollectionMetadata({repr(self.path)}, {repr(self.version)})'
Expand Down
49 changes: 31 additions & 18 deletions src/antsibull_docs/docs_parsing/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,41 +212,54 @@ def load_meta_runtime(collection_name: str,
return meta_runtime


def _add_symlink_redirects(collection_name: str,
collection_metadata: AnsibleCollectionMetadata,
plugin_routing_out: t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]]
) -> None:
for plugin_type in DOCUMENTABLE_PLUGINS:
directory_name = 'modules' if plugin_type == 'module' else plugin_type
directory_path = os.path.join(collection_metadata.path, 'plugins', directory_name)
plugin_type_routing = plugin_routing_out[plugin_type]

symlink_redirects = find_symlink_redirects(collection_name, plugin_type, directory_path)
for redirect_name, redirect_dst in symlink_redirects.items():
if redirect_name not in plugin_type_routing:
plugin_type_routing[redirect_name] = {}
if 'redirect' not in plugin_type_routing[redirect_name]:
plugin_type_routing[redirect_name]['redirect'] = redirect_dst
if plugin_type_routing[redirect_name]['redirect'] == redirect_dst:
plugin_type_routing[redirect_name]['redirect_is_symlink'] = True


async def load_collection_routing(collection_name: str,
collection_metadata: AnsibleCollectionMetadata
) -> t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]]:
"""
Load plugin routing for a collection.
Load plugin routing for a collection, and populate the private plugins lists
in collection metadata.
"""
meta_runtime = load_meta_runtime(collection_name, collection_metadata)
plugin_routing_out: t.Dict[str, t.Dict[str, t.Dict[str, t.Any]]] = {}
plugin_routing_in = meta_runtime.get('plugin_routing') or {}
private_plugins: t.Dict[str, t.List[str]] = {}
collection_metadata.private_plugins = private_plugins
for plugin_type in DOCUMENTABLE_PLUGINS:
plugin_type_id = 'modules' if plugin_type == 'module' else plugin_type
plugin_type_routing = plugin_routing_in.get(plugin_type_id) or {}
plugin_routing_out[plugin_type] = {
f'{collection_name}.{plugin_name}': process_dates(plugin_record)
for plugin_name, plugin_record in plugin_type_routing.items()
}
plugin_routing_out[plugin_type] = {}
private_plugins[plugin_type] = []
for plugin_name, plugin_record in plugin_type_routing.items():
fqcn = f'{collection_name}.{plugin_name}'
plugin_routing_out[plugin_type][fqcn] = process_dates(plugin_record)
if plugin_record.get('private', False):
private_plugins[plugin_type].append(plugin_name)

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

for plugin_type in DOCUMENTABLE_PLUGINS:
directory_name = 'modules' if plugin_type == 'module' else plugin_type
directory_path = os.path.join(collection_metadata.path, 'plugins', directory_name)
plugin_type_routing = plugin_routing_out[plugin_type]

symlink_redirects = find_symlink_redirects(collection_name, plugin_type, directory_path)
for redirect_name, redirect_dst in symlink_redirects.items():
if redirect_name not in plugin_type_routing:
plugin_type_routing[redirect_name] = {}
if 'redirect' not in plugin_type_routing[redirect_name]:
plugin_type_routing[redirect_name]['redirect'] = redirect_dst
if plugin_type_routing[redirect_name]['redirect'] == redirect_dst:
plugin_type_routing[redirect_name]['redirect_is_symlink'] = True
_add_symlink_redirects(collection_name, collection_metadata, plugin_routing_out)

if collection_name in COLLECTIONS_WITH_FLATMAPPING:
remove_flatmapping_artifacts(plugin_routing_out)
Expand Down
13 changes: 12 additions & 1 deletion src/antsibull_docs/write_docs/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,22 @@ async def write_plugin_lists(collection_name: str,
'Cannot parse required_ansible specifier set for {collection_name}',
collection_name=collection_name,
)

public_plugin_maps: t.Dict[str, t.Mapping[str, str]] = {}
for plugin_type, plugin_data in plugin_maps.items():
private_plugins = collection_meta.private_plugins.get(plugin_type) or []
public_plugin_data = {}
for plugin_name, plugin_info in plugin_data.items():
if plugin_name not in private_plugins:
public_plugin_data[plugin_name] = plugin_info
if public_plugin_data:
public_plugin_maps[plugin_type] = public_plugin_data

index_contents = _render_template(
template,
dest_dir,
collection_name=collection_name,
plugin_maps=plugin_maps,
plugin_maps=public_plugin_maps,
collection_version=collection_meta.version,
requires_ansible=requires_ansible,
link_data=link_data,
Expand Down
22 changes: 19 additions & 3 deletions src/antsibull_docs/write_docs/indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from antsibull_core.utils.io import write_file
from jinja2 import Template

from ..docs_parsing import AnsibleCollectionMetadata
from ..env_variables import EnvironmentVariableInfo
from ..jinja2.environment import doc_environment
from ..utils.collection_name_transformer import CollectionNameTransformer
Expand Down Expand Up @@ -53,6 +54,7 @@ async def write_callback_type_index(callback_type: str,

async def write_plugin_type_index(plugin_type: str,
per_collection_plugins: t.Mapping[str, t.Mapping[str, str]],
collection_metadata: t.Mapping[str, AnsibleCollectionMetadata],
template: Template,
dest_filename: str,
for_official_docsite: bool = False) -> None:
Expand All @@ -62,16 +64,28 @@ async def write_plugin_type_index(plugin_type: str,
:arg plugin_type: The plugin type to write the index for.
:arg per_collection_plugins: Mapping of collection_name to Mapping of plugin_name to
short_description.
:arg collection_metadata: Dictionary mapping collection names to collection metadata objects.
:arg template: A template to render the plugin index.
:arg dest_filename: The destination filename.
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
"""
public_per_collection_plugins = {}
for collection_name, plugins in per_collection_plugins.items():
public_plugins = {}
collection_meta = collection_metadata[collection_name]
private_plugins = collection_meta.private_plugins.get(plugin_type) or []
for plugin_name, plugin_data in plugins.items():
if plugin_name not in private_plugins:
public_plugins[plugin_name] = plugin_data
if public_plugins:
public_per_collection_plugins[collection_name] = public_plugins

index_contents = _render_template(
template,
dest_filename,
plugin_type=plugin_type,
per_collection_plugins=per_collection_plugins,
per_collection_plugins=public_per_collection_plugins,
for_official_docsite=for_official_docsite,
)

Expand Down Expand Up @@ -126,6 +140,7 @@ async def output_callback_indexes(plugin_info: PluginCollectionInfoT,


async def output_plugin_indexes(plugin_info: PluginCollectionInfoT,
collection_metadata: t.Mapping[str, AnsibleCollectionMetadata],
dest_dir: str,
collection_url: CollectionNameTransformer,
collection_install: CollectionNameTransformer,
Expand All @@ -135,6 +150,7 @@ async def output_plugin_indexes(plugin_info: PluginCollectionInfoT,
:arg plugin_info: Mapping of plugin_type to Mapping of collection_name to Mapping of
plugin_name to short_description.
:arg collection_metadata: Dictionary mapping collection names to collection metadata objects.
:arg dest_dir: The directory to place the documentation in.
:kwarg for_official_docsite: Default False. Set to True to use wording specific for the
official docsite on docs.ansible.com.
Expand Down Expand Up @@ -163,8 +179,8 @@ async def output_plugin_indexes(plugin_info: PluginCollectionInfoT,
filename = os.path.join(collection_toplevel, f'index_{plugin_type}.rst')
writers.append(await pool.spawn(
write_plugin_type_index(
plugin_type, per_collection_data, plugin_list_tmpl, filename,
for_official_docsite=for_official_docsite)))
plugin_type, per_collection_data, collection_metadata, plugin_list_tmpl,
filename, for_official_docsite=for_official_docsite)))

await asyncio.gather(*writers)

Expand Down
33 changes: 33 additions & 0 deletions tests/functional/ansible-doc-cache-all.json
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,39 @@
}
},
"lookup": {
"ns2.col.bar": {
"doc": {
"author": "Felix Fontein (@felixfontein)",
"collection": "ns2.col",
"description": [
"This one is private."
],
"filename": "ansible_collections/ns2/col/plugins/lookup/bar.py",
"name": "bar",
"options": {
"_terms": {
"description": "Something",
"elements": "dict",
"required": true,
"type": "list"
}
},
"short_description": "Look up some bar",
"version_added": "1.0.0",
"version_added_collection": "ns2.col"
},
"examples": "\n- name: Look up!\n ansible.builtin.debug:\n msg: \"{{ lookup('ns2.col.bar', {}) }}\"\n",
"metadata": null,
"return": {
"_raw": {
"description": [
"The resulting stuff."
],
"elements": "dict",
"type": "list"
}
}
},
"ns2.col.foo": {
"doc": {
"author": "Felix Fontein (@felixfontein)",
Expand Down
33 changes: 33 additions & 0 deletions tests/functional/ansible-doc-cache-ns2.col.json
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,39 @@
}
},
"lookup": {
"ns2.col.bar": {
"doc": {
"author": "Felix Fontein (@felixfontein)",
"collection": "ns2.col",
"description": [
"This one is private."
],
"filename": "ansible_collections/ns2/col/plugins/lookup/bar.py",
"name": "bar",
"options": {
"_terms": {
"description": "Something",
"elements": "dict",
"required": true,
"type": "list"
}
},
"short_description": "Look up some bar",
"version_added": "1.0.0",
"version_added_collection": "ns2.col"
},
"examples": "\n- name: Look up!\n ansible.builtin.debug:\n msg: \"{{ lookup('ns2.col.bar', {}) }}\"\n",
"metadata": null,
"return": {
"_raw": {
"description": [
"The resulting stuff."
],
"elements": "dict",
"type": "list"
}
}
},
"ns2.col.foo": {
"doc": {
"author": "Felix Fontein (@felixfontein)",
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/ansible-version.output
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ansible [core 2.15.0b1.post0] (stable-2.15 8f0ddcba2c) last updated 2023/04/06 20:47:29 (GMT +200)
ansible [core 2.16.0.dev0] (devel 88a380c8f0) last updated 2023/04/06 20:47:05 (GMT +200)
config file = None
configured module search path = ['<<<<<HOME>>>>>/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = <<<<<ANSIBLE>>>>>
Expand Down
Loading

0 comments on commit 2daefc3

Please sign in to comment.