diff options
Diffstat (limited to 'test/integration/targets/ansible-doc')
75 files changed, 2821 insertions, 0 deletions
diff --git a/test/integration/targets/ansible-doc/aliases b/test/integration/targets/ansible-doc/aliases new file mode 100644 index 0000000..1d28bdb --- /dev/null +++ b/test/integration/targets/ansible-doc/aliases @@ -0,0 +1,2 @@ +shippable/posix/group5 +context/controller diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json new file mode 100644 index 0000000..243a5e4 --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/MANIFEST.json @@ -0,0 +1,30 @@ +{ + "collection_info": { + "description": null, + "repository": "", + "tags": [], + "dependencies": {}, + "authors": [ + "Ansible (https://ansible.com)" + ], + "issues": "", + "name": "testcol", + "license": [ + "GPL-3.0-or-later" + ], + "documentation": "", + "namespace": "testns", + "version": "0.1.1231", + "readme": "README.md", + "license_file": "COPYING", + "homepage": "", + }, + "file_manifest_file": { + "format": 1, + "ftype": "file", + "chksum_sha256": "4c15a867ceba8ba1eaf2f4a58844bb5dbb82fec00645fc7eb74a3d31964900f6", + "name": "FILES.json", + "chksum_type": "sha256" + }, + "format": 1 +} diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py new file mode 100644 index 0000000..9fa25b4 --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py @@ -0,0 +1,70 @@ +# (c) 2020 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + cache: notjsonfile + broken: + short_description: JSON formatted files. + description: + - This cache uses JSON formatted, per host, files saved to the filesystem. + author: Ansible Core (@ansible-core) + version_added: 0.7.0 + options: + _uri: + required: True + description: + - Path in which the cache plugin will save the JSON files + env: + - name: ANSIBLE_CACHE_PLUGIN_CONNECTION + version_added: 1.2.0 + ini: + - key: fact_caching_connection + section: defaults + deprecated: + alternative: none + why: Test deprecation + version: '2.0.0' + _prefix: + description: User defined prefix to use when creating the JSON files + env: + - name: ANSIBLE_CACHE_PLUGIN_PREFIX + version_added: 1.1.0 + ini: + - key: fact_caching_prefix + section: defaults + deprecated: + alternative: none + why: Another test deprecation + removed_at_date: '2050-01-01' + _timeout: + default: 86400 + description: Expiration timeout for the cache plugin data + env: + - name: ANSIBLE_CACHE_PLUGIN_TIMEOUT + ini: + - key: fact_caching_timeout + section: defaults + vars: + - name: notsjonfile_fact_caching_timeout + version_added: 1.5.0 + deprecated: + alternative: do not use a variable + why: Test deprecation + version: '3.0.0' + type: integer + extends_documentation_fragment: + - testns.testcol2.plugin +''' + +from ansible.plugins.cache import BaseFileCacheModule + + +class CacheModule(BaseFileCacheModule): + """ + A caching module backed by json files. + """ + pass diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py new file mode 100644 index 0000000..caec2ed --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py @@ -0,0 +1,36 @@ +# Copyright (c) 2018 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + inventory: statichost + broken: + short_description: Add a single host + description: Add a single host + extends_documentation_fragment: + - inventory_cache + options: + plugin: + description: plugin name (must be statichost) + required: true + hostname: + description: Toggle display of stderr even when script was successful + required: True +''' + +from ansible.errors import AnsibleParserError +from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable + + +class InventoryModule(BaseInventoryPlugin, Cacheable): + + NAME = 'testns.content_adj.statichost' + + def verify_file(self, path): + pass + + def parse(self, inventory, loader, path, cache=None): + + pass diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py new file mode 100644 index 0000000..d456986 --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py @@ -0,0 +1,45 @@ +# (c) 2020 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = """ + lookup: noop + broken: + author: Ansible core team + short_description: returns input + description: + - this is a noop + deprecated: + alternative: Use some other lookup + why: Test deprecation + removed_in: '3.0.0' + extends_documentation_fragment: + - testns.testcol2.version_added +""" + +EXAMPLES = """ +- name: do nothing + debug: msg="{{ lookup('testns.testcol.noop', [1,2,3,4] }}" +""" + +RETURN = """ + _list: + description: input given + version_added: 1.0.0 +""" + +from ansible.module_utils.common._collections_compat import Sequence +from ansible.plugins.lookup import LookupBase +from ansible.errors import AnsibleError + + +class LookupModule(LookupBase): + + def run(self, terms, **kwargs): + if not isinstance(terms, Sequence): + raise AnsibleError("testns.testcol.noop expects a list") + return terms diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py new file mode 100644 index 0000000..a1caeb1 --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +DOCUMENTATION = """ + module: fakemodule + broken: + short_desciption: fake module + description: + - this is a fake module + version_added: 1.0.0 + options: + _notreal: + description: really not a real option + author: + - me +""" + +import json + + +def main(): + print(json.dumps(dict(changed=False, source='testns.testcol.fakemodule'))) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/notrealmodule.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/notrealmodule.py new file mode 100644 index 0000000..4479f23 --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/notrealmodule.py @@ -0,0 +1,13 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + + +def main(): + print(json.dumps(dict(changed=False, source='testns.testcol.notrealmodule'))) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py new file mode 100644 index 0000000..fb0e319 --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: randommodule +short_description: A random module +description: + - A random module. +author: + - Ansible Core Team +version_added: 1.0.0 +deprecated: + alternative: Use some other module + why: Test deprecation + removed_in: '3.0.0' +options: + test: + description: Some text. + type: str + version_added: 1.2.0 + sub: + description: Suboptions. + type: dict + suboptions: + subtest: + description: A suboption. + type: int + version_added: 1.1.0 + # The following is the wrong syntax, and should not get processed + # by add_collection_to_versions_and_dates() + options: + subtest2: + description: Another suboption. + type: float + version_added: 1.1.0 + # The following is not supported in modules, and should not get processed + # by add_collection_to_versions_and_dates() + env: + - name: TEST_ENV + version_added: 1.0.0 + deprecated: + alternative: none + why: Test deprecation + removed_in: '2.0.0' + version: '2.0.0' +extends_documentation_fragment: + - testns.testcol2.module +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +z_last: + description: A last result. + broken: + type: str + returned: success + version_added: 1.3.0 + +m_middle: + description: + - This should be in the middle. + - Has some more data + type: dict + returned: success and 1st of month + contains: + suboption: + description: A suboption. + type: str + choices: [ARF, BARN, c_without_capital_first_letter] + version_added: 1.4.0 + +a_first: + description: A first result. + type: str + returned: success +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py new file mode 100644 index 0000000..ae0f75e --- /dev/null +++ b/test/integration/targets/ansible-doc/broken-docs/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py @@ -0,0 +1,30 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + vars: noop_vars_plugin + broken: + short_description: Do NOT load host and group vars + description: don't test loading host and group vars from a collection + options: + stage: + default: all + choices: ['all', 'inventory', 'task'] + type: str + ini: + - key: stage + section: testns.testcol.noop_vars_plugin + env: + - name: ANSIBLE_VARS_PLUGIN_STAGE + extends_documentation_fragment: + - testns.testcol2.deprecation +''' + +from ansible.plugins.vars import BaseVarsPlugin + + +class VarsModule(BaseVarsPlugin): + + def get_vars(self, loader, path, entities, cache=True): + super(VarsModule, self).get_vars(loader, path, entities) + return {'collection': 'yes', 'notreal': 'value'} diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json new file mode 100644 index 0000000..243a5e4 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/MANIFEST.json @@ -0,0 +1,30 @@ +{ + "collection_info": { + "description": null, + "repository": "", + "tags": [], + "dependencies": {}, + "authors": [ + "Ansible (https://ansible.com)" + ], + "issues": "", + "name": "testcol", + "license": [ + "GPL-3.0-or-later" + ], + "documentation": "", + "namespace": "testns", + "version": "0.1.1231", + "readme": "README.md", + "license_file": "COPYING", + "homepage": "", + }, + "file_manifest_file": { + "format": 1, + "ftype": "file", + "chksum_sha256": "4c15a867ceba8ba1eaf2f4a58844bb5dbb82fec00645fc7eb74a3d31964900f6", + "name": "FILES.json", + "chksum_type": "sha256" + }, + "format": 1 +} diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py new file mode 100644 index 0000000..ea4a722 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py @@ -0,0 +1,69 @@ +# (c) 2020 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + cache: notjsonfile + short_description: JSON formatted files. + description: + - This cache uses JSON formatted, per host, files saved to the filesystem. + author: Ansible Core (@ansible-core) + version_added: 0.7.0 + options: + _uri: + required: True + description: + - Path in which the cache plugin will save the JSON files + env: + - name: ANSIBLE_CACHE_PLUGIN_CONNECTION + version_added: 1.2.0 + ini: + - key: fact_caching_connection + section: defaults + deprecated: + alternative: none + why: Test deprecation + version: '2.0.0' + _prefix: + description: User defined prefix to use when creating the JSON files + env: + - name: ANSIBLE_CACHE_PLUGIN_PREFIX + version_added: 1.1.0 + ini: + - key: fact_caching_prefix + section: defaults + deprecated: + alternative: none + why: Another test deprecation + removed_at_date: '2050-01-01' + _timeout: + default: 86400 + description: Expiration timeout for the cache plugin data + env: + - name: ANSIBLE_CACHE_PLUGIN_TIMEOUT + ini: + - key: fact_caching_timeout + section: defaults + vars: + - name: notsjonfile_fact_caching_timeout + version_added: 1.5.0 + deprecated: + alternative: do not use a variable + why: Test deprecation + version: '3.0.0' + type: integer + extends_documentation_fragment: + - testns.testcol2.plugin +''' + +from ansible.plugins.cache import BaseFileCacheModule + + +class CacheModule(BaseFileCacheModule): + """ + A caching module backed by json files. + """ + pass diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/filter_subdir/in_subdir.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/filter_subdir/in_subdir.py new file mode 100644 index 0000000..a8924e1 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/filter_subdir/in_subdir.py @@ -0,0 +1,23 @@ +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.utils.display import Display + +display = Display() + + +def nochange(a): + return a + + +class FilterModule(object): + ''' Ansible core jinja2 filters ''' + + def filters(self): + return { + 'noop': nochange, + 'nested': nochange, + } diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/grouped.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/grouped.py new file mode 100644 index 0000000..a10c7aa --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/grouped.py @@ -0,0 +1,28 @@ +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.utils.display import Display + +display = Display() + + +def nochange(a): + return a + + +def meaningoflife(a): + return 42 + + +class FilterModule(object): + ''' Ansible core jinja2 filters ''' + + def filters(self): + return { + 'noop': nochange, + 'ultimatequestion': meaningoflife, + 'b64decode': nochange, # here to colide with basename of builtin + } diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/ultimatequestion.yml b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/ultimatequestion.yml new file mode 100644 index 0000000..a67654d --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/filter/ultimatequestion.yml @@ -0,0 +1,21 @@ +DOCUMENTATION: + name: ultimatequestion + author: Terry Prachet + version_added: 'histerical' + short_description: Ask any question but it will only respond with the answer to the ulitmate one + description: + - read the book + options: + _input: + description: Anything you want, goign to ignore it anywayss ... + type: raw + required: true + +EXAMPLES: | + # set first 10 volumes rw, rest as dp + meaning: "{{ (stuff|ulmtimatequestion }}" + +RETURN: + _value: + description: guess + type: int diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py new file mode 100644 index 0000000..cbb8f0f --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/inventory/statichost.py @@ -0,0 +1,35 @@ +# Copyright (c) 2018 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + inventory: statichost + short_description: Add a single host + description: Add a single host + extends_documentation_fragment: + - inventory_cache + options: + plugin: + description: plugin name (must be statichost) + required: true + hostname: + description: Toggle display of stderr even when script was successful + required: True +''' + +from ansible.errors import AnsibleParserError +from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable + + +class InventoryModule(BaseInventoryPlugin, Cacheable): + + NAME = 'testns.content_adj.statichost' + + def verify_file(self, path): + pass + + def parse(self, inventory, loader, path, cache=None): + + pass diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py new file mode 100644 index 0000000..7a64a5d --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/lookup/noop.py @@ -0,0 +1,45 @@ +# (c) 2020 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = """ + lookup: noop + author: Ansible core team + short_description: returns input + description: + - this is a noop + deprecated: + alternative: Use some other lookup + why: Test deprecation + removed_in: '3.0.0' + extends_documentation_fragment: + - testns.testcol2.version_added +""" + +EXAMPLES = """ +- name: do nothing + debug: msg="{{ lookup('testns.testcol.noop', [1,2,3,4] }}" +""" + +RETURN = """ + _list: + description: input given + version_added: 1.0.0 +""" + +from collections.abc import Sequence + +from ansible.plugins.lookup import LookupBase +from ansible.errors import AnsibleError + + +class LookupModule(LookupBase): + + def run(self, terms, **kwargs): + if not isinstance(terms, Sequence): + raise AnsibleError("testns.testcol.noop expects a list") + return terms diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/database/database_type/subdir_module.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/database/database_type/subdir_module.py new file mode 100644 index 0000000..dd41305 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/database/database_type/subdir_module.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: subdir_module +short_description: A module in multiple subdirectories +description: + - A module in multiple subdirectories +author: + - Ansible Core Team +version_added: 1.0.0 +options: {} +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py new file mode 100644 index 0000000..6d18c08 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py @@ -0,0 +1,27 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +DOCUMENTATION = """ + module: fakemodule + short_desciption: fake module + description: + - this is a fake module + version_added: 1.0.0 + options: + _notreal: + description: really not a real option + author: + - me +""" + +import json + + +def main(): + print(json.dumps(dict(changed=False, source='testns.testcol.fakemodule'))) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/notrealmodule.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/notrealmodule.py new file mode 100644 index 0000000..4479f23 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/notrealmodule.py @@ -0,0 +1,13 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + + +def main(): + print(json.dumps(dict(changed=False, source='testns.testcol.notrealmodule'))) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py new file mode 100644 index 0000000..f251a69 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py @@ -0,0 +1,95 @@ +#!/usr/bin/python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: randommodule +short_description: A random module +description: + - A random module. +author: + - Ansible Core Team +version_added: 1.0.0 +deprecated: + alternative: Use some other module + why: Test deprecation + removed_in: '3.0.0' +options: + test: + description: Some text. + type: str + version_added: 1.2.0 + sub: + description: Suboptions. + type: dict + suboptions: + subtest: + description: A suboption. + type: int + version_added: 1.1.0 + # The following is the wrong syntax, and should not get processed + # by add_collection_to_versions_and_dates() + options: + subtest2: + description: Another suboption. + type: float + version_added: 1.1.0 + # The following is not supported in modules, and should not get processed + # by add_collection_to_versions_and_dates() + env: + - name: TEST_ENV + version_added: 1.0.0 + deprecated: + alternative: none + why: Test deprecation + removed_in: '2.0.0' + version: '2.0.0' +extends_documentation_fragment: + - testns.testcol2.module +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +z_last: + description: A last result. + type: str + returned: success + version_added: 1.3.0 + +m_middle: + description: + - This should be in the middle. + - Has some more data + type: dict + returned: success and 1st of month + contains: + suboption: + description: A suboption. + type: str + choices: [ARF, BARN, c_without_capital_first_letter] + version_added: 1.4.0 + +a_first: + description: A first result. + type: str + returned: success +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/test_test.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/test_test.py new file mode 100644 index 0000000..f1c2b3a --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/test_test.py @@ -0,0 +1,16 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +def yolo(value): + return True + + +class TestModule(object): + ''' Ansible core jinja2 tests ''' + + def tests(self): + return { + # failure testing + 'yolo': yolo, + } diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml new file mode 100644 index 0000000..cc60945 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/test/yolo.yml @@ -0,0 +1,18 @@ +DOCUMENTATION: + name: yolo + short_description: you only live once + description: + - This is always true + options: + _input: + description: does not matter + type: raw + required: true + +EXAMPLES: | + {{ 'anything' is yolo }} + +RETURN: + output: + type: boolean + description: always true diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py new file mode 100644 index 0000000..94e7feb --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py @@ -0,0 +1,29 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + vars: noop_vars_plugin + short_description: Do NOT load host and group vars + description: don't test loading host and group vars from a collection + options: + stage: + default: all + choices: ['all', 'inventory', 'task'] + type: str + ini: + - key: stage + section: testns.testcol.noop_vars_plugin + env: + - name: ANSIBLE_VARS_PLUGIN_STAGE + extends_documentation_fragment: + - testns.testcol2.deprecation +''' + +from ansible.plugins.vars import BaseVarsPlugin + + +class VarsModule(BaseVarsPlugin): + + def get_vars(self, loader, path, entities, cache=True): + super(VarsModule, self).get_vars(loader, path, entities) + return {'collection': 'yes', 'notreal': 'value'} diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/roles/testrole/meta/main.yml b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/roles/testrole/meta/main.yml new file mode 100644 index 0000000..bc6af69 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/roles/testrole/meta/main.yml @@ -0,0 +1,26 @@ +--- +dependencies: +galaxy_info: + +argument_specs: + main: + short_description: testns.testcol.testrole short description for main entry point + description: + - Longer description for testns.testcol.testrole main entry point. + author: Ansible Core (@ansible) + options: + opt1: + description: opt1 description + type: "str" + required: true + + alternate: + short_description: testns.testcol.testrole short description for alternate entry point + description: + - Longer description for testns.testcol.testrole alternate entry point. + author: Ansible Core (@ansible) + options: + altopt1: + description: altopt1 description + type: "int" + required: true diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/roles/testrole_with_no_argspecs/meta/empty b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/roles/testrole_with_no_argspecs/meta/empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol/roles/testrole_with_no_argspecs/meta/empty diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json new file mode 100644 index 0000000..02ec289 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/MANIFEST.json @@ -0,0 +1,30 @@ +{ + "collection_info": { + "description": null, + "repository": "", + "tags": [], + "dependencies": {}, + "authors": [ + "Ansible (https://ansible.com)" + ], + "issues": "", + "name": "testcol2", + "license": [ + "GPL-3.0-or-later" + ], + "documentation": "", + "namespace": "testns", + "version": "1.2.0", + "readme": "README.md", + "license_file": "COPYING", + "homepage": "", + }, + "file_manifest_file": { + "format": 1, + "ftype": "file", + "chksum_sha256": "4c15a867ceba8ba1eaf2f4a58844bb5dbb82fec00645fc7eb74a3d31964900f6", + "name": "FILES.json", + "chksum_type": "sha256" + }, + "format": 1 +} diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/deprecation.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/deprecation.py new file mode 100644 index 0000000..3942d72 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/deprecation.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + DOCUMENTATION = r''' +options: {} +deprecated: + alternative: Use some other module + why: Test deprecation + removed_in: '3.0.0' +''' diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/module.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/module.py new file mode 100644 index 0000000..a572363 --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/module.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + DOCUMENTATION = r''' +options: + testcol2option: + description: + - An option taken from testcol2 + type: str + version_added: 1.0.0 + testcol2option2: + description: + - Another option taken from testcol2 + type: str +''' diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/plugin.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/plugin.py new file mode 100644 index 0000000..2fe4e4a --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/plugin.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + DOCUMENTATION = r''' +options: + testcol2option: + description: + - A plugin option taken from testcol2 + type: str + version_added: 1.0.0 + ini: + - key: foo + section: bar + version_added: 1.1.0 + deprecated: + alternative: none + why: Test deprecation + version: '3.0.0' + env: + - name: FOO_BAR + version_added: 1.2.0 + deprecated: + alternative: none + why: Test deprecation + removed_at_date: 2020-01-31 + vars: + - name: foobar + version_added: 1.3.0 + deprecated: + alternative: none + why: Test deprecation + removed_at_date: 2040-12-31 + testcol2depr: + description: + - A plugin option taken from testcol2 that is deprecated + type: str + deprecated: + alternative: none + why: Test option deprecation + version: '2.0.0' +''' diff --git a/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/version_added.py b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/version_added.py new file mode 100644 index 0000000..73e5f2f --- /dev/null +++ b/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol2/plugins/doc_fragments/version_added.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + DOCUMENTATION = r''' +options: {} +version_added: 1.0.0 +''' diff --git a/test/integration/targets/ansible-doc/fakecollrole.output b/test/integration/targets/ansible-doc/fakecollrole.output new file mode 100644 index 0000000..3ae9077 --- /dev/null +++ b/test/integration/targets/ansible-doc/fakecollrole.output @@ -0,0 +1,15 @@ +> TESTNS.TESTCOL.TESTROLE (/ansible/test/integration/targets/ansible-doc/collections/ansible_collections/testns/testcol) + +ENTRY POINT: alternate - testns.testcol.testrole short description for alternate entry point + + Longer description for testns.testcol.testrole alternate entry + point. + +OPTIONS (= is mandatory): + += altopt1 + altopt1 description + type: int + + +AUTHOR: Ansible Core (@ansible) diff --git a/test/integration/targets/ansible-doc/fakemodule.output b/test/integration/targets/ansible-doc/fakemodule.output new file mode 100644 index 0000000..4fb0776 --- /dev/null +++ b/test/integration/targets/ansible-doc/fakemodule.output @@ -0,0 +1,16 @@ +> TESTNS.TESTCOL.FAKEMODULE (./collections/ansible_collections/testns/testcol/plugins/modules/fakemodule.py) + + this is a fake module + +ADDED IN: version 1.0.0 of testns.testcol + +OPTIONS (= is mandatory): + +- _notreal + really not a real option + default: null + + +AUTHOR: me + +SHORT_DESCIPTION: fake module diff --git a/test/integration/targets/ansible-doc/fakerole.output b/test/integration/targets/ansible-doc/fakerole.output new file mode 100644 index 0000000..bcb53dc --- /dev/null +++ b/test/integration/targets/ansible-doc/fakerole.output @@ -0,0 +1,32 @@ +> TEST_ROLE1 (/ansible/test/integration/targets/ansible-doc/roles/normal_role1) + +ENTRY POINT: main - test_role1 from roles subdir + + In to am attended desirous raptures *declared* diverted + confined at. Collected instantly remaining up certainly to + `necessary' as. Over walk dull into son boy door went new. At + or happiness commanded daughters as. Is `handsome' an declared + at received in extended vicinity subjects. Into miss on he + over been late pain an. Only week bore boy what fat case left + use. Match round scale now style far times. Your me past an + much. + +OPTIONS (= is mandatory): + += myopt1 + First option. + type: str + +- myopt2 + Second option + default: 8000 + type: int + +- myopt3 + Third option. + choices: [choice1, choice2] + default: null + type: str + + +AUTHOR: John Doe (@john), Jane Doe (@jane) diff --git a/test/integration/targets/ansible-doc/filter_plugins/donothing.yml b/test/integration/targets/ansible-doc/filter_plugins/donothing.yml new file mode 100644 index 0000000..87fe2f9 --- /dev/null +++ b/test/integration/targets/ansible-doc/filter_plugins/donothing.yml @@ -0,0 +1,21 @@ +DOCUMENTATION: + name: donothing + author: lazy + version_added: 'histerical' + short_description: noop + description: + - don't do anything + options: + _input: + description: Anything you want to get back + type: raw + required: true + +EXAMPLES: | + # set first 10 volumes rw, rest as dp + meaning: "{{ (stuff|donothing}}" + +RETURN: + _value: + description: guess + type: raw diff --git a/test/integration/targets/ansible-doc/filter_plugins/other.py b/test/integration/targets/ansible-doc/filter_plugins/other.py new file mode 100644 index 0000000..1bc2e17 --- /dev/null +++ b/test/integration/targets/ansible-doc/filter_plugins/other.py @@ -0,0 +1,25 @@ +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.utils.display import Display + +display = Display() + + +def donothing(a): + return a + + +class FilterModule(object): + ''' Ansible core jinja2 filters ''' + + def filters(self): + return { + 'donothing': donothing, + 'nodocs': donothing, + 'split': donothing, + 'b64decode': donothing, + } diff --git a/test/integration/targets/ansible-doc/filter_plugins/split.yml b/test/integration/targets/ansible-doc/filter_plugins/split.yml new file mode 100644 index 0000000..87fe2f9 --- /dev/null +++ b/test/integration/targets/ansible-doc/filter_plugins/split.yml @@ -0,0 +1,21 @@ +DOCUMENTATION: + name: donothing + author: lazy + version_added: 'histerical' + short_description: noop + description: + - don't do anything + options: + _input: + description: Anything you want to get back + type: raw + required: true + +EXAMPLES: | + # set first 10 volumes rw, rest as dp + meaning: "{{ (stuff|donothing}}" + +RETURN: + _value: + description: guess + type: raw diff --git a/test/integration/targets/ansible-doc/inventory b/test/integration/targets/ansible-doc/inventory new file mode 100644 index 0000000..ab9b62c --- /dev/null +++ b/test/integration/targets/ansible-doc/inventory @@ -0,0 +1 @@ +not_empty # avoid empty empty hosts list warning without defining explicit localhost diff --git a/test/integration/targets/ansible-doc/library/double_doc.py b/test/integration/targets/ansible-doc/library/double_doc.py new file mode 100644 index 0000000..6f0412a --- /dev/null +++ b/test/integration/targets/ansible-doc/library/double_doc.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = r''' +name: double_doc +description: + - module also uses 'DOCUMENTATION' in class +''' + + +class Foo: + + # 2nd ref to documentation string, used to trip up tokinzer doc reader + DOCUMENTATION = None + + def __init__(self): + pass diff --git a/test/integration/targets/ansible-doc/library/test_docs.py b/test/integration/targets/ansible-doc/library/test_docs.py new file mode 100644 index 0000000..39ae372 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['stableinterface'], + 'supported_by': 'core'} + +DOCUMENTATION = ''' +--- +module: test_docs +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_missing_description.py b/test/integration/targets/ansible-doc/library/test_docs_missing_description.py new file mode 100644 index 0000000..6ed4183 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_missing_description.py @@ -0,0 +1,40 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_returns +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +options: + test: + type: str +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict( + test=dict(type='str'), + ), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_no_metadata.py b/test/integration/targets/ansible-doc/library/test_docs_no_metadata.py new file mode 100644 index 0000000..4ea86f0 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_no_metadata.py @@ -0,0 +1,35 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_no_metadata +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_no_status.py b/test/integration/targets/ansible-doc/library/test_docs_no_status.py new file mode 100644 index 0000000..1b0db4e --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_no_status.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'supported_by': 'core'} + +DOCUMENTATION = ''' +--- +module: test_docs_no_status +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_non_iterable_status.py b/test/integration/targets/ansible-doc/library/test_docs_non_iterable_status.py new file mode 100644 index 0000000..63d080f --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_non_iterable_status.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': 1, + 'supported_by': 'core'} + +DOCUMENTATION = ''' +--- +module: test_docs_non_iterable_status +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_removed_precedence.py b/test/integration/targets/ansible-doc/library/test_docs_removed_precedence.py new file mode 100644 index 0000000..3de1c69 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_removed_precedence.py @@ -0,0 +1,40 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_removed_precedence +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +deprecated: + alternative: new_module + why: Updated module released with more functionality + removed_at_date: '2022-06-01' + removed_in: '2.14' +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_removed_status.py b/test/integration/targets/ansible-doc/library/test_docs_removed_status.py new file mode 100644 index 0000000..cb48c16 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_removed_status.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['removed'], + 'supported_by': 'core'} + +DOCUMENTATION = ''' +--- +module: test_docs_removed_status +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_returns.py b/test/integration/targets/ansible-doc/library/test_docs_returns.py new file mode 100644 index 0000000..77c1376 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_returns.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_returns +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +z_last: + description: A last result. + type: str + returned: success + +m_middle: + description: + - This should be in the middle. + - Has some more data + type: dict + returned: success and 1st of month + contains: + suboption: + description: A suboption. + type: str + choices: [ARF, BARN, c_without_capital_first_letter] + +a_first: + description: A first result. + type: str + returned: success +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_returns_broken.py b/test/integration/targets/ansible-doc/library/test_docs_returns_broken.py new file mode 100644 index 0000000..d6d6264 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_returns_broken.py @@ -0,0 +1,40 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_returns_broken +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +test: + description: A test return value. + type: str + +broken_key: [ +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_suboptions.py b/test/integration/targets/ansible-doc/library/test_docs_suboptions.py new file mode 100644 index 0000000..c922d1d --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_suboptions.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_suboptions +short_description: Test module +description: + - Test module +author: + - Ansible Core Team +options: + with_suboptions: + description: + - An option with suboptions. + - Use with care. + type: dict + suboptions: + z_last: + description: The last suboption. + type: str + m_middle: + description: + - The suboption in the middle. + - Has its own suboptions. + suboptions: + a_suboption: + description: A sub-suboption. + type: str + a_first: + description: The first suboption. + type: str +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict( + test_docs_suboptions=dict( + type='dict', + options=dict( + a_first=dict(type='str'), + m_middle=dict( + type='dict', + options=dict( + a_suboption=dict(type='str') + ), + ), + z_last=dict(type='str'), + ), + ), + ), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_docs_yaml_anchors.py b/test/integration/targets/ansible-doc/library/test_docs_yaml_anchors.py new file mode 100644 index 0000000..bec0292 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_docs_yaml_anchors.py @@ -0,0 +1,71 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: test_docs_yaml_anchors +short_description: Test module with YAML anchors in docs +description: + - Test module +author: + - Ansible Core Team +options: + at_the_top: &toplevel_anchor + description: + - Short desc + default: some string + type: str + + last_one: *toplevel_anchor + + egress: + description: + - Egress firewall rules + type: list + elements: dict + suboptions: &sub_anchor + port: + description: + - Rule port + type: int + required: true + + ingress: + description: + - Ingress firewall rules + type: list + elements: dict + suboptions: *sub_anchor +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict( + at_the_top=dict(type='str', default='some string'), + last_one=dict(type='str', default='some string'), + egress=dict(type='list', elements='dict', options=dict( + port=dict(type='int', required=True), + )), + ingress=dict(type='list', elements='dict', options=dict( + port=dict(type='int', required=True), + )), + ), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_empty.py b/test/integration/targets/ansible-doc/library/test_empty.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_empty.py diff --git a/test/integration/targets/ansible-doc/library/test_no_docs.py b/test/integration/targets/ansible-doc/library/test_no_docs.py new file mode 100644 index 0000000..5503aed --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_no_docs.py @@ -0,0 +1,23 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['stableinterface'], + 'supported_by': 'core'} + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_no_docs_no_metadata.py b/test/integration/targets/ansible-doc/library/test_no_docs_no_metadata.py new file mode 100644 index 0000000..4887268 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_no_docs_no_metadata.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_no_docs_no_status.py b/test/integration/targets/ansible-doc/library/test_no_docs_no_status.py new file mode 100644 index 0000000..f90c5c7 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_no_docs_no_status.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'supported_by': 'core'} + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_no_docs_non_iterable_status.py b/test/integration/targets/ansible-doc/library/test_no_docs_non_iterable_status.py new file mode 100644 index 0000000..44fbede --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_no_docs_non_iterable_status.py @@ -0,0 +1,23 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': 1, + 'supported_by': 'core'} + + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + module = AnsibleModule( + argument_spec=dict(), + ) + + module.exit_json() + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ansible-doc/library/test_win_module.ps1 b/test/integration/targets/ansible-doc/library/test_win_module.ps1 new file mode 100644 index 0000000..5653c8b --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_win_module.ps1 @@ -0,0 +1,21 @@ +#!powershell +# Copyright: (c) Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#AnsibleRequires -CSharpUtil Ansible.Basic + +$spec = @{ + options = @{ + hello = @{ type = 'str'; required = $true } + } + supports_check_mode = $true +} + +$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) + +$hello = $module.Params.hello + +$module.Result.msg = $hello +$module.Result.changed = $false + +$module.ExitJson() diff --git a/test/integration/targets/ansible-doc/library/test_win_module.yml b/test/integration/targets/ansible-doc/library/test_win_module.yml new file mode 100644 index 0000000..0547c70 --- /dev/null +++ b/test/integration/targets/ansible-doc/library/test_win_module.yml @@ -0,0 +1,9 @@ +DOCUMENTATION: + module: test_win_module + short_description: Test win module + description: + - Test win module with sidecar docs + author: + - Ansible Core Team +EXAMPLES: '' +RETURN: '' diff --git a/test/integration/targets/ansible-doc/lookup_plugins/_deprecated_with_adj_docs.py b/test/integration/targets/ansible-doc/lookup_plugins/_deprecated_with_adj_docs.py new file mode 100644 index 0000000..81d401d --- /dev/null +++ b/test/integration/targets/ansible-doc/lookup_plugins/_deprecated_with_adj_docs.py @@ -0,0 +1,5 @@ +# Copyright (c) 2022 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type diff --git a/test/integration/targets/ansible-doc/lookup_plugins/_deprecated_with_docs.py b/test/integration/targets/ansible-doc/lookup_plugins/_deprecated_with_docs.py new file mode 100644 index 0000000..4fd63aa --- /dev/null +++ b/test/integration/targets/ansible-doc/lookup_plugins/_deprecated_with_docs.py @@ -0,0 +1,26 @@ +# Copyright (c) 2022 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +DOCUMENTATION = ''' + name: deprecated_with_docs + short_description: test lookup + description: test lookup + author: Ansible Core Team + version_added: "2.14" + deprecated: + why: reasons + alternative: other thing + removed_in: "2.16" + removed_from_collection: "ansible.legacy" + options: {} +''' + +EXAMPLE = ''' +''' + +RETURN = ''' +''' diff --git a/test/integration/targets/ansible-doc/lookup_plugins/deprecated_with_adj_docs.yml b/test/integration/targets/ansible-doc/lookup_plugins/deprecated_with_adj_docs.yml new file mode 100644 index 0000000..6349c39 --- /dev/null +++ b/test/integration/targets/ansible-doc/lookup_plugins/deprecated_with_adj_docs.yml @@ -0,0 +1,16 @@ +DOCUMENTATION: + name: deprecated_with_adj_docs + short_description: test lookup + description: test lookup + author: Ansible Core Team + version_added: "2.14" + deprecated: + why: reasons + alternative: use other thing + removed_in: "2.16" + removed_from_collection: "ansible.legacy" + options: {} + +EXAMPLE: "" + +RETURN: {} diff --git a/test/integration/targets/ansible-doc/noop.output b/test/integration/targets/ansible-doc/noop.output new file mode 100644 index 0000000..567150a --- /dev/null +++ b/test/integration/targets/ansible-doc/noop.output @@ -0,0 +1,32 @@ +{ + "testns.testcol.noop": { + "doc": { + "author": "Ansible core team", + "collection": "testns.testcol", + "deprecated": { + "alternative": "Use some other lookup", + "removed_from_collection": "testns.testcol", + "removed_in": "3.0.0", + "why": "Test deprecation" + }, + "description": [ + "this is a noop" + ], + "filename": "./collections/ansible_collections/testns/testcol/plugins/lookup/noop.py", + "lookup": "noop", + "options": {}, + "short_description": "returns input", + "version_added": "1.0.0", + "version_added_collection": "testns.testcol2" + }, + "examples": "\n- name: do nothing\n debug: msg=\"{{ lookup('testns.testcol.noop', [1,2,3,4] }}\"\n", + "metadata": null, + "return": { + "_list": { + "description": "input given", + "version_added": "1.0.0", + "version_added_collection": "testns.testcol" + } + } + } +} diff --git a/test/integration/targets/ansible-doc/noop_vars_plugin.output b/test/integration/targets/ansible-doc/noop_vars_plugin.output new file mode 100644 index 0000000..5c42af3 --- /dev/null +++ b/test/integration/targets/ansible-doc/noop_vars_plugin.output @@ -0,0 +1,42 @@ +{ + "testns.testcol.noop_vars_plugin": { + "doc": { + "collection": "testns.testcol", + "deprecated": { + "alternative": "Use some other module", + "removed_from_collection": "testns.testcol2", + "removed_in": "3.0.0", + "why": "Test deprecation" + }, + "description": "don't test loading host and group vars from a collection", + "filename": "./collections/ansible_collections/testns/testcol/plugins/vars/noop_vars_plugin.py", + "options": { + "stage": { + "choices": [ + "all", + "inventory", + "task" + ], + "default": "all", + "env": [ + { + "name": "ANSIBLE_VARS_PLUGIN_STAGE" + } + ], + "ini": [ + { + "key": "stage", + "section": "testns.testcol.noop_vars_plugin" + } + ], + "type": "str" + } + }, + "short_description": "Do NOT load host and group vars", + "vars": "noop_vars_plugin" + }, + "examples": null, + "metadata": null, + "return": null + } +} diff --git a/test/integration/targets/ansible-doc/notjsonfile.output b/test/integration/targets/ansible-doc/notjsonfile.output new file mode 100644 index 0000000..a73b1a9 --- /dev/null +++ b/test/integration/targets/ansible-doc/notjsonfile.output @@ -0,0 +1,157 @@ +{ + "testns.testcol.notjsonfile": { + "doc": { + "author": "Ansible Core (@ansible-core)", + "cache": "notjsonfile", + "collection": "testns.testcol", + "description": [ + "This cache uses JSON formatted, per host, files saved to the filesystem." + ], + "filename": "./collections/ansible_collections/testns/testcol/plugins/cache/notjsonfile.py", + "options": { + "_prefix": { + "deprecated": { + "alternative": "none", + "collection_name": "testns.testcol", + "removed_at_date": "2050-01-01", + "why": "Another test deprecation" + }, + "description": "User defined prefix to use when creating the JSON files", + "env": [ + { + "name": "ANSIBLE_CACHE_PLUGIN_PREFIX", + "version_added": "1.1.0", + "version_added_collection": "testns.testcol" + } + ], + "ini": [ + { + "key": "fact_caching_prefix", + "section": "defaults" + } + ] + }, + "_timeout": { + "default": 86400, + "description": "Expiration timeout for the cache plugin data", + "env": [ + { + "name": "ANSIBLE_CACHE_PLUGIN_TIMEOUT" + } + ], + "ini": [ + { + "key": "fact_caching_timeout", + "section": "defaults" + } + ], + "type": "integer", + "vars": [ + { + "deprecated": { + "alternative": "do not use a variable", + "collection_name": "testns.testcol", + "version": "3.0.0", + "why": "Test deprecation" + }, + "name": "notsjonfile_fact_caching_timeout", + "version_added": "1.5.0", + "version_added_collection": "testns.testcol" + } + ] + }, + "_uri": { + "description": [ + "Path in which the cache plugin will save the JSON files" + ], + "env": [ + { + "name": "ANSIBLE_CACHE_PLUGIN_CONNECTION", + "version_added": "1.2.0", + "version_added_collection": "testns.testcol" + } + ], + "ini": [ + { + "deprecated": { + "alternative": "none", + "collection_name": "testns.testcol", + "version": "2.0.0", + "why": "Test deprecation" + }, + "key": "fact_caching_connection", + "section": "defaults" + } + ], + "required": true + }, + "testcol2depr": { + "deprecated": { + "alternative": "none", + "collection_name": "testns.testcol2", + "version": "2.0.0", + "why": "Test option deprecation" + }, + "description": [ + "A plugin option taken from testcol2 that is deprecated" + ], + "type": "str" + }, + "testcol2option": { + "description": [ + "A plugin option taken from testcol2" + ], + "env": [ + { + "deprecated": { + "alternative": "none", + "collection_name": "testns.testcol2", + "removed_at_date": "2020-01-31", + "why": "Test deprecation" + }, + "name": "FOO_BAR", + "version_added": "1.2.0", + "version_added_collection": "testns.testcol2" + } + ], + "ini": [ + { + "deprecated": { + "alternative": "none", + "collection_name": "testns.testcol2", + "version": "3.0.0", + "why": "Test deprecation" + }, + "key": "foo", + "section": "bar", + "version_added": "1.1.0", + "version_added_collection": "testns.testcol2" + } + ], + "type": "str", + "vars": [ + { + "deprecated": { + "alternative": "none", + "collection_name": "testns.testcol2", + "removed_at_date": "2040-12-31", + "why": "Test deprecation" + }, + "name": "foobar", + "version_added": "1.3.0", + "version_added_collection": "testns.testcol2" + } + ], + "version_added": "1.0.0", + "version_added_collection": "testns.testcol2" + } + }, + "short_description": "JSON formatted files.", + "version_added": "0.7.0", + "version_added_collection": "testns.testcol" + }, + "examples": null, + "metadata": null, + "return": null + } +} diff --git a/test/integration/targets/ansible-doc/randommodule-text.output b/test/integration/targets/ansible-doc/randommodule-text.output new file mode 100644 index 0000000..51d7930 --- /dev/null +++ b/test/integration/targets/ansible-doc/randommodule-text.output @@ -0,0 +1,101 @@ +> TESTNS.TESTCOL.RANDOMMODULE (./collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py) + + A random module. + +ADDED IN: version 1.0.0 of testns.testcol + +DEPRECATED: + + Reason: Test deprecation + Will be removed in: Ansible 3.0.0 + Alternatives: Use some other module + + +OPTIONS (= is mandatory): + +- sub + Suboptions. + set_via: + env: + - deprecated: + alternative: none + removed_in: 2.0.0 + version: 2.0.0 + why: Test deprecation + name: TEST_ENV + default: null + type: dict + + OPTIONS: + + - subtest2 + Another suboption. + default: null + type: float + added in: version 1.1.0 + + + + SUBOPTIONS: + + - subtest + A suboption. + default: null + type: int + added in: version 1.1.0 of testns.testcol + + +- test + Some text. + default: null + type: str + added in: version 1.2.0 of testns.testcol + + +- testcol2option + An option taken from testcol2 + default: null + type: str + added in: version 1.0.0 of testns.testcol2 + + +- testcol2option2 + Another option taken from testcol2 + default: null + type: str + + +AUTHOR: Ansible Core Team + +EXAMPLES: + + + + +RETURN VALUES: +- a_first + A first result. + returned: success + type: str + +- m_middle + This should be in the middle. + Has some more data + returned: success and 1st of month + type: dict + + CONTAINS: + + - suboption + A suboption. + choices: [ARF, BARN, c_without_capital_first_letter] + type: str + added in: version 1.4.0 of testns.testcol + + +- z_last + A last result. + returned: success + type: str + added in: version 1.3.0 of testns.testcol + diff --git a/test/integration/targets/ansible-doc/randommodule.output b/test/integration/targets/ansible-doc/randommodule.output new file mode 100644 index 0000000..25f46c3 --- /dev/null +++ b/test/integration/targets/ansible-doc/randommodule.output @@ -0,0 +1,115 @@ +{ + "testns.testcol.randommodule": { + "doc": { + "author": [ + "Ansible Core Team" + ], + "collection": "testns.testcol", + "deprecated": { + "alternative": "Use some other module", + "removed_from_collection": "testns.testcol", + "removed_in": "3.0.0", + "why": "Test deprecation" + }, + "description": [ + "A random module." + ], + "filename": "./collections/ansible_collections/testns/testcol/plugins/modules/randommodule.py", + "has_action": false, + "module": "randommodule", + "options": { + "sub": { + "description": "Suboptions.", + "env": [ + { + "deprecated": { + "alternative": "none", + "removed_in": "2.0.0", + "version": "2.0.0", + "why": "Test deprecation" + }, + "name": "TEST_ENV", + "version_added": "1.0.0" + } + ], + "options": { + "subtest2": { + "description": "Another suboption.", + "type": "float", + "version_added": "1.1.0" + } + }, + "suboptions": { + "subtest": { + "description": "A suboption.", + "type": "int", + "version_added": "1.1.0", + "version_added_collection": "testns.testcol" + } + }, + "type": "dict" + }, + "test": { + "description": "Some text.", + "type": "str", + "version_added": "1.2.0", + "version_added_collection": "testns.testcol" + }, + "testcol2option": { + "description": [ + "An option taken from testcol2" + ], + "type": "str", + "version_added": "1.0.0", + "version_added_collection": "testns.testcol2" + }, + "testcol2option2": { + "description": [ + "Another option taken from testcol2" + ], + "type": "str" + } + }, + "short_description": "A random module", + "version_added": "1.0.0", + "version_added_collection": "testns.testcol" + }, + "examples": "\n", + "metadata": null, + "return": { + "a_first": { + "description": "A first result.", + "returned": "success", + "type": "str" + }, + "m_middle": { + "contains": { + "suboption": { + "choices": [ + "ARF", + "BARN", + "c_without_capital_first_letter" + ], + "description": "A suboption.", + "type": "str", + "version_added": "1.4.0", + "version_added_collection": "testns.testcol" + } + }, + "description": [ + "This should be in the middle.", + "Has some more data" + ], + "returned": "success and 1st of month", + "type": "dict" + }, + "z_last": { + "description": "A last result.", + "returned": "success", + "type": "str", + "version_added": "1.3.0", + "version_added_collection": "testns.testcol" + } + } + } +} diff --git a/test/integration/targets/ansible-doc/roles/test_role1/meta/argument_specs.yml b/test/integration/targets/ansible-doc/roles/test_role1/meta/argument_specs.yml new file mode 100644 index 0000000..0315a1f --- /dev/null +++ b/test/integration/targets/ansible-doc/roles/test_role1/meta/argument_specs.yml @@ -0,0 +1,34 @@ +--- +argument_specs: + main: + short_description: test_role1 from roles subdir + description: + - In to am attended desirous raptures B(declared) diverted confined at. Collected instantly remaining + up certainly to C(necessary) as. Over walk dull into son boy door went new. + - At or happiness commanded daughters as. Is I(handsome) an declared at received in extended vicinity + subjects. Into miss on he over been late pain an. Only week bore boy what fat case left use. Match round + scale now style far times. Your me past an much. + author: + - John Doe (@john) + - Jane Doe (@jane) + + options: + myopt1: + description: + - First option. + type: "str" + required: true + + myopt2: + description: + - Second option + type: "int" + default: 8000 + + myopt3: + description: + - Third option. + type: "str" + choices: + - choice1 + - choice2 diff --git a/test/integration/targets/ansible-doc/roles/test_role1/meta/main.yml b/test/integration/targets/ansible-doc/roles/test_role1/meta/main.yml new file mode 100644 index 0000000..19f6162 --- /dev/null +++ b/test/integration/targets/ansible-doc/roles/test_role1/meta/main.yml @@ -0,0 +1,13 @@ +# This meta/main.yml exists to test that it is NOT read, with preference being +# given to the meta/argument_specs.yml file. This spec contains additional +# entry points (groot, foo) that the argument_specs.yml does not. If this file +# were read, the additional entrypoints would show up in --list output, breaking +# tests. +--- +argument_specs: + main: + short_description: test_role1 from roles subdir + groot: + short_description: I am Groot + foo: + short_description: I am Foo diff --git a/test/integration/targets/ansible-doc/roles/test_role2/meta/empty b/test/integration/targets/ansible-doc/roles/test_role2/meta/empty new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/ansible-doc/roles/test_role2/meta/empty diff --git a/test/integration/targets/ansible-doc/roles/test_role3/meta/main.yml b/test/integration/targets/ansible-doc/roles/test_role3/meta/main.yml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/ansible-doc/roles/test_role3/meta/main.yml diff --git a/test/integration/targets/ansible-doc/runme.sh b/test/integration/targets/ansible-doc/runme.sh new file mode 100755 index 0000000..887d3c4 --- /dev/null +++ b/test/integration/targets/ansible-doc/runme.sh @@ -0,0 +1,214 @@ +#!/usr/bin/env bash + +set -eux +ansible-playbook test.yml -i inventory "$@" + +# test keyword docs +ansible-doc -t keyword -l | grep 'vars_prompt: list of variables to prompt for.' +ansible-doc -t keyword vars_prompt | grep 'description: list of variables to prompt for.' +ansible-doc -t keyword asldkfjaslidfhals 2>&1 | grep 'Skipping Invalid keyword' + +# collections testing +( +unset ANSIBLE_PLAYBOOK_DIR +cd "$(dirname "$0")" + +# test module docs from collection +# we use sed to strip the module path from the first line +current_out="$(ansible-doc --playbook-dir ./ testns.testcol.fakemodule | sed '1 s/\(^> TESTNS\.TESTCOL\.FAKEMODULE\).*(.*)$/\1/')" +expected_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.FAKEMODULE\).*(.*)$/\1/' fakemodule.output)" +test "$current_out" == "$expected_out" + +# we use sed to strip the module path from the first line +current_out="$(ansible-doc --playbook-dir ./ testns.testcol.randommodule | sed '1 s/\(^> TESTNS\.TESTCOL\.RANDOMMODULE\).*(.*)$/\1/')" +expected_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.RANDOMMODULE\).*(.*)$/\1/' randommodule-text.output)" +test "$current_out" == "$expected_out" + +# ensure we do work with valid collection name for list +ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | grep -v "Invalid collection name" + +# ensure we dont break on invalid collection name for list +ansible-doc --list testns.testcol.fakemodule --playbook-dir ./ 2>&1 | grep "Invalid collection name" + +# test listing diff plugin types from collection +for ptype in cache inventory lookup vars filter module +do + # each plugin type adds 1 from collection + # FIXME pre=$(ansible-doc -l -t ${ptype}|wc -l) + # FIXME post=$(ansible-doc -l -t ${ptype} --playbook-dir ./|wc -l) + # FIXME test "$pre" -eq $((post - 1)) + if [ "${ptype}" == "filter" ]; then + expected=5 + expected_names=("b64decode" "filter_subdir.nested" "filter_subdir.noop" "noop" "ultimatequestion") + elif [ "${ptype}" == "module" ]; then + expected=4 + expected_names=("fakemodule" "notrealmodule" "randommodule" "database.database_type.subdir_module") + else + expected=1 + if [ "${ptype}" == "cache" ]; then expected_names=("notjsonfile"); + elif [ "${ptype}" == "inventory" ]; then expected_names=("statichost"); + elif [ "${ptype}" == "lookup" ]; then expected_names=("noop"); + elif [ "${ptype}" == "vars" ]; then expected_names=("noop_vars_plugin"); fi + fi + # ensure we ONLY list from the collection + justcol=$(ansible-doc -l -t ${ptype} --playbook-dir ./ testns.testcol|wc -l) + test "$justcol" -eq "$expected" + + # ensure the right names are displayed + list_result=$(ansible-doc -l -t ${ptype} --playbook-dir ./ testns.testcol) + metadata_result=$(ansible-doc --metadata-dump --no-fail-on-errors -t ${ptype} --playbook-dir ./ testns.testcol) + for name in "${expected_names[@]}"; do + echo "${list_result}" | grep "testns.testcol.${name}" + echo "${metadata_result}" | grep "testns.testcol.${name}" + done + + # ensure we get error if passinginvalid collection, much less any plugins + ansible-doc -l -t ${ptype} testns.testcol 2>&1 | grep "unable to locate collection" + + # TODO: do we want per namespace? + # ensure we get 1 plugins when restricting namespace + #justcol=$(ansible-doc -l -t ${ptype} --playbook-dir ./ testns|wc -l) + #test "$justcol" -eq 1 +done + +#### test role functionality + +# Test role text output +# we use sed to strip the role path from the first line +current_role_out="$(ansible-doc -t role -r ./roles test_role1 | sed '1 s/\(^> TEST_ROLE1\).*(.*)$/\1/')" +expected_role_out="$(sed '1 s/\(^> TEST_ROLE1\).*(.*)$/\1/' fakerole.output)" +test "$current_role_out" == "$expected_role_out" + +# Two collection roles are defined, but only 1 has a role arg spec with 2 entry points +output=$(ansible-doc -t role -l --playbook-dir . testns.testcol | wc -l) +test "$output" -eq 2 + +# Include normal roles (no collection filter) +output=$(ansible-doc -t role -l --playbook-dir . | wc -l) +test "$output" -eq 3 + +# Test that a role in the playbook dir with the same name as a role in the +# 'roles' subdir of the playbook dir does not appear (lower precedence). +output=$(ansible-doc -t role -l --playbook-dir . | grep -c "test_role1 from roles subdir") +test "$output" -eq 1 +output=$(ansible-doc -t role -l --playbook-dir . | grep -c "test_role1 from playbook dir" || true) +test "$output" -eq 0 + +# Test entry point filter +current_role_out="$(ansible-doc -t role --playbook-dir . testns.testcol.testrole -e alternate| sed '1 s/\(^> TESTNS\.TESTCOL\.TESTROLE\).*(.*)$/\1/')" +expected_role_out="$(sed '1 s/\(^> TESTNS\.TESTCOL\.TESTROLE\).*(.*)$/\1/' fakecollrole.output)" +test "$current_role_out" == "$expected_role_out" + +) + +#### test add_collection_to_versions_and_dates() + +current_out="$(ansible-doc --json --playbook-dir ./ testns.testcol.randommodule | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')" +expected_out="$(sed 's/ *"filename": "[^"]*",$//' randommodule.output)" +test "$current_out" == "$expected_out" + +current_out="$(ansible-doc --json --playbook-dir ./ -t cache testns.testcol.notjsonfile | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')" +expected_out="$(sed 's/ *"filename": "[^"]*",$//' notjsonfile.output)" +test "$current_out" == "$expected_out" + +current_out="$(ansible-doc --json --playbook-dir ./ -t lookup testns.testcol.noop | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')" +expected_out="$(sed 's/ *"filename": "[^"]*",$//' noop.output)" +test "$current_out" == "$expected_out" + +current_out="$(ansible-doc --json --playbook-dir ./ -t vars testns.testcol.noop_vars_plugin | sed 's/ *$//' | sed 's/ *"filename": "[^"]*",$//')" +expected_out="$(sed 's/ *"filename": "[^"]*",$//' noop_vars_plugin.output)" +test "$current_out" == "$expected_out" + +# just ensure it runs +ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --playbook-dir /dev/null >/dev/null + +# create broken role argument spec +mkdir -p broken-docs/collections/ansible_collections/testns/testcol/roles/testrole/meta +cat <<EOF > broken-docs/collections/ansible_collections/testns/testcol/roles/testrole/meta/main.yml +--- +dependencies: +galaxy_info: + +argument_specs: + main: + short_description: testns.testcol.testrole short description for main entry point + description: + - Longer description for testns.testcol.testrole main entry point. + author: Ansible Core (@ansible) + options: + opt1: + description: opt1 description + broken: + type: "str" + required: true +EOF + +# ensure that --metadata-dump does not fail when --no-fail-on-errors is supplied +ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --no-fail-on-errors --playbook-dir broken-docs testns.testcol >/dev/null + +# ensure that --metadata-dump does fail when --no-fail-on-errors is not supplied +output=$(ANSIBLE_LIBRARY='./nolibrary' ansible-doc --metadata-dump --playbook-dir broken-docs testns.testcol 2>&1 | grep -c 'ERROR!' || true) +test "${output}" -eq 1 + +# ensure we list the 'legacy plugins' +[ "$(ansible-doc -M ./library -l ansible.legacy |wc -l)" -gt "0" ] + +# playbook dir should work the same +[ "$(ansible-doc -l ansible.legacy --playbook-dir ./|wc -l)" -gt "0" ] + +# see that we show undocumented when missing docs +[ "$(ansible-doc -M ./library -l ansible.legacy |grep -c UNDOCUMENTED)" == "6" ] + +# ensure filtering works and does not include any 'test_' modules +[ "$(ansible-doc -M ./library -l ansible.builtin |grep -c test_)" == 0 ] +[ "$(ansible-doc --playbook-dir ./ -l ansible.builtin |grep -c test_)" == 0 ] + +# ensure filtering still shows modules +count=$(ANSIBLE_LIBRARY='./nolibrary' ansible-doc -l ansible.builtin |wc -l) +[ "${count}" -gt "0" ] +[ "$(ansible-doc -M ./library -l ansible.builtin |wc -l)" == "${count}" ] +[ "$(ansible-doc --playbook-dir ./ -l ansible.builtin |wc -l)" == "${count}" ] + + +# produce 'sidecar' docs for test +[ "$(ansible-doc -t test --playbook-dir ./ testns.testcol.yolo| wc -l)" -gt "0" ] +[ "$(ansible-doc -t filter --playbook-dir ./ donothing| wc -l)" -gt "0" ] +[ "$(ansible-doc -t filter --playbook-dir ./ ansible.legacy.donothing| wc -l)" -gt "0" ] + +# no docs and no sidecar +ansible-doc -t filter --playbook-dir ./ nodocs 2>&1| grep -c 'missing documentation' || true + +# produce 'sidecar' docs for module +[ "$(ansible-doc -M ./library test_win_module| wc -l)" -gt "0" ] +[ "$(ansible-doc --playbook-dir ./ test_win_module| wc -l)" -gt "0" ] + +# test 'double DOCUMENTATION' use +[ "$(ansible-doc --playbook-dir ./ double_doc| wc -l)" -gt "0" ] + +# don't break on module dir +ansible-doc --list --module-path ./modules > /dev/null + +# ensure we dedupe by fqcn and not base name +[ "$(ansible-doc -l -t filter --playbook-dir ./ |grep -c 'b64decode')" -eq "3" ] + +# ensure we don't show duplicates for plugins that only exist in ansible.builtin when listing ansible.legacy plugins +[ "$(ansible-doc -l -t filter --playbook-dir ./ |grep -c 'b64encode')" -eq "1" ] + +# with playbook dir, legacy should override +ansible-doc -t filter split --playbook-dir ./ |grep histerical + +pyc_src="$(pwd)/filter_plugins/other.py" +pyc_1="$(pwd)/filter_plugins/split.pyc" +pyc_2="$(pwd)/library/notaplugin.pyc" +trap 'rm -rf "$pyc_1" "$pyc_2"' EXIT + +# test pyc files are not used as adjacent documentation +python -c "import py_compile; py_compile.compile('$pyc_src', cfile='$pyc_1')" +ansible-doc -t filter split --playbook-dir ./ |grep histerical + +# test pyc files are not listed as plugins +python -c "import py_compile; py_compile.compile('$pyc_src', cfile='$pyc_2')" +test "$(ansible-doc -l -t module --playbook-dir ./ 2>&1 1>/dev/null |grep -c "notaplugin")" == 0 + +# without playbook dir, builtin should return +ansible-doc -t filter split |grep -v histerical diff --git a/test/integration/targets/ansible-doc/test.yml b/test/integration/targets/ansible-doc/test.yml new file mode 100644 index 0000000..a8c992e --- /dev/null +++ b/test/integration/targets/ansible-doc/test.yml @@ -0,0 +1,172 @@ +- hosts: localhost + gather_facts: no + environment: + ANSIBLE_LIBRARY: "{{ playbook_dir }}/library" + tasks: + - name: module with missing description return docs + command: ansible-doc test_docs_missing_description + register: result + ignore_errors: true + + - assert: + that: + - result is failed + - | + "ERROR! Unable to retrieve documentation from 'test_docs_missing_description' due to: All (sub-)options and return values must have a 'description' field" + in result.stderr + + - name: module with suboptions (avoid first line as it has full path) + shell: ansible-doc test_docs_suboptions| tail -n +2 + register: result + ignore_errors: true + + - set_fact: + actual_output: >- + {{ result.stdout | regex_replace('^(> [A-Z_]+ +\().+library/([a-z_]+.py)\)$', '\1library/\2)', multiline=true) }} + expected_output: "{{ lookup('file', 'test_docs_suboptions.output') }}" + + - assert: + that: + - result is succeeded + - actual_output == expected_output + + - name: module with return docs + shell: ansible-doc test_docs_returns| tail -n +2 + register: result + ignore_errors: true + + - set_fact: + actual_output: >- + {{ result.stdout | regex_replace('^(> [A-Z_]+ +\().+library/([a-z_]+.py)\)$', '\1library/\2)', multiline=true) }} + expected_output: "{{ lookup('file', 'test_docs_returns.output') }}" + + - assert: + that: + - result is succeeded + - actual_output == expected_output + + - name: module with broken return docs + command: ansible-doc test_docs_returns_broken + register: result + ignore_errors: true + + - assert: + that: + - result is failed + - '"module test_docs_returns_broken missing documentation (or could not parse documentation)" in result.stderr' + + - name: non-existent module + command: ansible-doc test_does_not_exist + register: result + - assert: + that: + - '"test_does_not_exist was not found" in result.stderr' + + - name: documented module + command: ansible-doc test_docs + register: result + - assert: + that: + - '"WARNING" not in result.stderr' + - '"TEST_DOCS " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' + + - name: documented module without metadata + command: ansible-doc test_docs_no_metadata + register: result + - assert: + that: + - '"WARNING" not in result.stderr' + - '"TEST_DOCS_NO_METADATA " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' + + - name: documented module with no status in metadata + command: ansible-doc test_docs_no_status + register: result + - assert: + that: + - '"WARNING" not in result.stderr' + - '"TEST_DOCS_NO_STATUS " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' + + - name: documented module with non-iterable status in metadata + command: ansible-doc test_docs_non_iterable_status + register: result + - assert: + that: + - '"WARNING" not in result.stderr' + - '"TEST_DOCS_NON_ITERABLE_STATUS " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' + + - name: documented module with removed status + command: ansible-doc test_docs_removed_status + register: result + + - assert: + that: + - '"WARNING" not in result.stderr' + - '"TEST_DOCS_REMOVED_STATUS " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' + + - name: empty module + command: ansible-doc test_empty + register: result + ignore_errors: true + + - assert: + that: + - result is failed + + - name: module with no documentation + command: ansible-doc test_no_docs + register: result + ignore_errors: true + + - assert: + that: + - result is failed + + - name: deprecated module with both removed date and version (date should get precedence) + command: ansible-doc test_docs_removed_precedence + register: result + + - assert: + that: + - '"DEPRECATED" in result.stdout' + - '"Reason: Updated module released with more functionality" in result.stdout' + - '"Will be removed in a release after 2022-06-01" in result.stdout' + - '"Alternatives: new_module" in result.stdout' + + - name: documented module with YAML anchors + shell: ansible-doc test_docs_yaml_anchors |tail -n +2 + register: result + - set_fact: + actual_output: >- + {{ result.stdout | regex_replace('^(> [A-Z_]+ +\().+library/([a-z_]+.py)\)$', '\1library/\2)', multiline=true) }} + expected_output: "{{ lookup('file', 'test_docs_yaml_anchors.output') }}" + - assert: + that: + - actual_output == expected_output + + - name: ensure 'donothing' adjacent filter is loaded + assert: + that: + - "'x' == ('x'|donothing)" + + - name: docs for deprecated plugin + command: ansible-doc deprecated_with_docs -t lookup + register: result + - assert: + that: + - '"WARNING" not in result.stderr' + - '"DEPRECATED_WITH_DOCS " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' + + - name: adjacent docs for deprecated plugin + command: ansible-doc deprecated_with_adj_docs -t lookup + register: result + - assert: + that: + - '"WARNING" not in result.stderr' + - '"DEPRECATED_WITH_ADJ_DOCS " in result.stdout' + - '"AUTHOR: Ansible Core Team" in result.stdout' diff --git a/test/integration/targets/ansible-doc/test_docs_returns.output b/test/integration/targets/ansible-doc/test_docs_returns.output new file mode 100644 index 0000000..3e23645 --- /dev/null +++ b/test/integration/targets/ansible-doc/test_docs_returns.output @@ -0,0 +1,33 @@ + + Test module + +AUTHOR: Ansible Core Team + +EXAMPLES: + + + + +RETURN VALUES: +- a_first + A first result. + returned: success + type: str + +- m_middle + This should be in the middle. + Has some more data + returned: success and 1st of month + type: dict + + CONTAINS: + + - suboption + A suboption. + choices: [ARF, BARN, c_without_capital_first_letter] + type: str + +- z_last + A last result. + returned: success + type: str diff --git a/test/integration/targets/ansible-doc/test_docs_suboptions.output b/test/integration/targets/ansible-doc/test_docs_suboptions.output new file mode 100644 index 0000000..350f90f --- /dev/null +++ b/test/integration/targets/ansible-doc/test_docs_suboptions.output @@ -0,0 +1,42 @@ + + Test module + +OPTIONS (= is mandatory): + +- with_suboptions + An option with suboptions. + Use with care. + default: null + type: dict + + SUBOPTIONS: + + - a_first + The first suboption. + default: null + type: str + + - m_middle + The suboption in the middle. + Has its own suboptions. + default: null + + SUBOPTIONS: + + - a_suboption + A sub-suboption. + default: null + type: str + + - z_last + The last suboption. + default: null + type: str + + +AUTHOR: Ansible Core Team + +EXAMPLES: + + + diff --git a/test/integration/targets/ansible-doc/test_docs_yaml_anchors.output b/test/integration/targets/ansible-doc/test_docs_yaml_anchors.output new file mode 100644 index 0000000..5eb2eee --- /dev/null +++ b/test/integration/targets/ansible-doc/test_docs_yaml_anchors.output @@ -0,0 +1,46 @@ + + Test module + +OPTIONS (= is mandatory): + +- at_the_top + Short desc + default: some string + type: str + +- egress + Egress firewall rules + default: null + elements: dict + type: list + + SUBOPTIONS: + + = port + Rule port + type: int + +- ingress + Ingress firewall rules + default: null + elements: dict + type: list + + SUBOPTIONS: + + = port + Rule port + type: int + +- last_one + Short desc + default: some string + type: str + + +AUTHOR: Ansible Core Team + +EXAMPLES: + + + diff --git a/test/integration/targets/ansible-doc/test_role1/README.txt b/test/integration/targets/ansible-doc/test_role1/README.txt new file mode 100644 index 0000000..98983c8 --- /dev/null +++ b/test/integration/targets/ansible-doc/test_role1/README.txt @@ -0,0 +1,3 @@ +Test role that exists in the playbook directory so we can validate +that a role of the same name that exists in the 'roles' subdirectory +will take precedence over this one. diff --git a/test/integration/targets/ansible-doc/test_role1/meta/main.yml b/test/integration/targets/ansible-doc/test_role1/meta/main.yml new file mode 100644 index 0000000..4f7abcc --- /dev/null +++ b/test/integration/targets/ansible-doc/test_role1/meta/main.yml @@ -0,0 +1,8 @@ +--- +dependencies: +galaxy_info: + +argument_specs: + main: + short_description: test_role1 from playbook dir + description: This should not appear in `ansible-doc --list` output. |