Skip to content

Commit

Permalink
Fix loading namespaced doc_fragments from collections (#55249)
Browse files Browse the repository at this point in the history
* Fix loading namespaced doc_fragments

The syntax for specifying a different fragment name was already
using '.' as a separator, so the code needed to be tweaked to
avoid choking on names like `testns.testcoll.fragname` and
`testns.testcoll.fragname.altvar`.

`get_plugin_class()` returns 'docfragment' for the fragment loader;
mangling `subdir` provides consistent alignment with the normal plugin
directory names and avoids needing special handling of plugin types
with 'module' in the name.

* Add changelog entry
  • Loading branch information
flowerysong authored and ansibot committed May 3, 2019
1 parent fcca1a1 commit 2ef8b29
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 10 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/55249-doc_fragments_from_collections.yml
@@ -0,0 +1,2 @@
bugfixes:
- Fixed loading namespaced documentation fragments from collections.
15 changes: 6 additions & 9 deletions lib/ansible/plugins/loader.py
Expand Up @@ -330,15 +330,12 @@ def _find_fq_plugin(self, fq_name, extension):
package = splitname[0]
resource = splitname[1]

append_plugin_type = self.class_name or self.subdir

if append_plugin_type:
# only current non-class special case, module_utils don't use this loader method
if append_plugin_type == 'library':
append_plugin_type = 'modules'
elif append_plugin_type != 'module_utils':
append_plugin_type = get_plugin_class(append_plugin_type)
package += '.plugins.{0}'.format(append_plugin_type)
append_plugin_type = self.subdir.replace('_plugins', '')

if append_plugin_type == 'library':
append_plugin_type = 'modules'

package += '.plugins.{0}'.format(append_plugin_type)

if extension:
resource += extension
Expand Down
8 changes: 7 additions & 1 deletion lib/ansible/utils/plugin_docs.py
Expand Up @@ -50,14 +50,20 @@ def add_fragments(doc, filename, fragment_loader):
# Allow the module to specify a var other than DOCUMENTATION
# to pull the fragment from, using dot notation as a separator
for fragment_slug in fragments:
fallback_name = None
fragment_slug = fragment_slug.lower()
if '.' in fragment_slug:
fragment_name, fragment_var = fragment_slug.split('.', 1)
fallback_name = fragment_slug
fragment_name, fragment_var = fragment_slug.rsplit('.', 1)
fragment_var = fragment_var.upper()
else:
fragment_name, fragment_var = fragment_slug, 'DOCUMENTATION'

fragment_class = fragment_loader.get(fragment_name)
if fragment_class is None and fallback_name:
fragment_class = fragment_loader.get(fallback_name)
fragment_var = 'DOCUMENTATION'

if fragment_class is None:
raise AnsibleAssertionError('fragment_class is None')

Expand Down
@@ -0,0 +1,14 @@
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
normal_doc_frag:
description:
- an option
'''

OTHER_DOCUMENTATION = r'''
options:
other_doc_frag:
description:
- another option
'''
Expand Up @@ -2,6 +2,14 @@

import json

DOCUMENTATION = r'''
module: testmodule
description: for testing
extends_documentation_fragment:
- testns.testcoll.frag
- testns.testcoll.frag.other_documentation
'''


def main():
print(json.dumps(dict(changed=False, source='user')))
Expand Down
3 changes: 3 additions & 0 deletions test/integration/targets/collections/runme.sh
Expand Up @@ -20,6 +20,9 @@ fi
# test callback
ANSIBLE_CALLBACK_WHITELIST=testns.testcoll.usercallback ansible localhost -m ping | grep "usercallback says ok"

# test documentation
ansible-doc testns.testcoll.testmodule -vvv | grep -- "- normal_doc_frag"

# we need multiple plays, and conditional import_playbook is noisy and causes problems, so choose here which one to use...
if [[ ${INVENTORY_PATH} == *.winrm ]]; then
export TEST_PLAYBOOK=windows.yml
Expand Down

0 comments on commit 2ef8b29

Please sign in to comment.