diff options
Diffstat (limited to 'test/integration/targets/module_utils/library')
12 files changed, 398 insertions, 0 deletions
diff --git a/test/integration/targets/module_utils/library/test.py b/test/integration/targets/module_utils/library/test.py new file mode 100644 index 0000000..fb6c8a8 --- /dev/null +++ b/test/integration/targets/module_utils/library/test.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# Most of these names are only available via PluginLoader so pylint doesn't +# know they exist +# pylint: disable=no-name-in-module +__metaclass__ = type + +results = {} + +# Test import with no from +import ansible.module_utils.foo0 +results['foo0'] = ansible.module_utils.foo0.data + +# Test depthful import with no from +import ansible.module_utils.bar0.foo +results['bar0'] = ansible.module_utils.bar0.foo.data + +# Test import of module_utils/foo1.py +from ansible.module_utils import foo1 +results['foo1'] = foo1.data + +# Test import of an identifier inside of module_utils/foo2.py +from ansible.module_utils.foo2 import data +results['foo2'] = data + +# Test import of module_utils/bar1/__init__.py +from ansible.module_utils import bar1 +results['bar1'] = bar1.data + +# Test import of an identifier inside of module_utils/bar2/__init__.py +from ansible.module_utils.bar2 import data +results['bar2'] = data + +# Test import of module_utils/baz1/one.py +from ansible.module_utils.baz1 import one +results['baz1'] = one.data + +# Test import of an identifier inside of module_utils/baz2/one.py +from ansible.module_utils.baz2.one import data +results['baz2'] = data + +# Test import of module_utils/spam1/ham/eggs/__init__.py +from ansible.module_utils.spam1.ham import eggs +results['spam1'] = eggs.data + +# Test import of an identifier inside module_utils/spam2/ham/eggs/__init__.py +from ansible.module_utils.spam2.ham.eggs import data +results['spam2'] = data + +# Test import of module_utils/spam3/ham/bacon.py +from ansible.module_utils.spam3.ham import bacon +results['spam3'] = bacon.data + +# Test import of an identifier inside of module_utils/spam4/ham/bacon.py +from ansible.module_utils.spam4.ham.bacon import data +results['spam4'] = data + +# Test import of module_utils.spam5.ham bacon and eggs (modules) +from ansible.module_utils.spam5.ham import bacon, eggs +results['spam5'] = (bacon.data, eggs.data) + +# Test import of module_utils.spam6.ham bacon and eggs (identifiers) +from ansible.module_utils.spam6.ham import bacon, eggs +results['spam6'] = (bacon, eggs) + +# Test import of module_utils.spam7.ham bacon and eggs (module and identifier) +from ansible.module_utils.spam7.ham import bacon, eggs +results['spam7'] = (bacon.data, eggs) + +# Test import of module_utils/spam8/ham/bacon.py and module_utils/spam8/ham/eggs.py separately +from ansible.module_utils.spam8.ham import bacon +from ansible.module_utils.spam8.ham import eggs +results['spam8'] = (bacon.data, eggs) + +# Test that import of module_utils/qux1/quux.py using as works +from ansible.module_utils.qux1 import quux as one +results['qux1'] = one.data + +# Test that importing qux2/quux.py and qux2/quuz.py using as works +from ansible.module_utils.qux2 import quux as one, quuz as two +results['qux2'] = (one.data, two.data) + +# Test depth +from ansible.module_utils.a.b.c.d.e.f.g.h import data + +results['abcdefgh'] = data +from ansible.module_utils.basic import AnsibleModule +AnsibleModule(argument_spec=dict()).exit_json(**results) diff --git a/test/integration/targets/module_utils/library/test_alias_deprecation.py b/test/integration/targets/module_utils/library/test_alias_deprecation.py new file mode 100644 index 0000000..dc36aba --- /dev/null +++ b/test/integration/targets/module_utils/library/test_alias_deprecation.py @@ -0,0 +1,16 @@ +#!/usr/bin/python + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils.basic import AnsibleModule +# overridden +from ansible.module_utils.ansible_release import data + +results = {"data": data} + +arg_spec = dict( + foo=dict(type='str', aliases=['baz'], deprecated_aliases=[dict(name='baz', version='9.99')]) +) + +AnsibleModule(argument_spec=arg_spec).exit_json(**results) diff --git a/test/integration/targets/module_utils/library/test_cwd_missing.py b/test/integration/targets/module_utils/library/test_cwd_missing.py new file mode 100644 index 0000000..cd1f9c7 --- /dev/null +++ b/test/integration/targets/module_utils/library/test_cwd_missing.py @@ -0,0 +1,33 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import os + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + # This module verifies that AnsibleModule works when cwd does not exist. + # This situation can occur as a race condition when the following conditions are met: + # + # 1) Execute a module which has high startup overhead prior to instantiating AnsibleModule (0.5s is enough in many cases). + # 2) Run the module async as the last task in a playbook using connection=local (a fire-and-forget task). + # 3) Remove the directory containing the playbook immediately after playbook execution ends (playbook in a temp dir). + # + # To ease testing of this race condition the deletion of cwd is handled in this module. + # This avoids race conditions in the test, including timing cwd deletion between AnsiballZ wrapper execution and AnsibleModule instantiation. + # The timing issue with AnsiballZ is due to cwd checking in the wrapper when code coverage is enabled. + + temp = os.path.abspath('temp') + + os.mkdir(temp) + os.chdir(temp) + os.rmdir(temp) + + module = AnsibleModule(argument_spec=dict()) + module.exit_json(before=temp, after=os.getcwd()) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/module_utils/library/test_cwd_unreadable.py b/test/integration/targets/module_utils/library/test_cwd_unreadable.py new file mode 100644 index 0000000..d65f31a --- /dev/null +++ b/test/integration/targets/module_utils/library/test_cwd_unreadable.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import os + +from ansible.module_utils.basic import AnsibleModule + + +def main(): + # This module verifies that AnsibleModule works when cwd exists but is unreadable. + # This situation can occur when running tasks as an unprivileged user. + + try: + cwd = os.getcwd() + except OSError: + # Compensate for macOS being unable to access cwd as an unprivileged user. + # This test is a no-op in this case. + # Testing for os.getcwd() failures is handled by the test_cwd_missing module. + cwd = '/' + os.chdir(cwd) + + module = AnsibleModule(argument_spec=dict()) + module.exit_json(before=cwd, after=os.getcwd()) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/module_utils/library/test_datetime.py b/test/integration/targets/module_utils/library/test_datetime.py new file mode 100644 index 0000000..493a186 --- /dev/null +++ b/test/integration/targets/module_utils/library/test_datetime.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# Most of these names are only available via PluginLoader so pylint doesn't +# know they exist +# pylint: disable=no-name-in-module +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils.basic import AnsibleModule +import datetime + +module = AnsibleModule(argument_spec=dict( + datetime=dict(type=str, required=True), + date=dict(type=str, required=True), +)) +result = { + 'datetime': datetime.datetime.strptime(module.params.get('datetime'), '%Y-%m-%dT%H:%M:%S'), + 'date': datetime.datetime.strptime(module.params.get('date'), '%Y-%m-%d').date(), +} +module.exit_json(**result) diff --git a/test/integration/targets/module_utils/library/test_env_override.py b/test/integration/targets/module_utils/library/test_env_override.py new file mode 100644 index 0000000..ebfb5dd --- /dev/null +++ b/test/integration/targets/module_utils/library/test_env_override.py @@ -0,0 +1,14 @@ +#!/usr/bin/python +# Most of these names are only available via PluginLoader so pylint doesn't +# know they exist +# pylint: disable=no-name-in-module +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.json_utils import data +from ansible.module_utils.mork import data as mork_data + +results = {"json_utils": data, "mork": mork_data} + +AnsibleModule(argument_spec=dict()).exit_json(**results) diff --git a/test/integration/targets/module_utils/library/test_failure.py b/test/integration/targets/module_utils/library/test_failure.py new file mode 100644 index 0000000..efb3dda --- /dev/null +++ b/test/integration/targets/module_utils/library/test_failure.py @@ -0,0 +1,14 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +results = {} +# Test that we are rooted correctly +# Following files: +# module_utils/yak/zebra/foo.py +from ansible.module_utils.zebra import foo + +results['zebra'] = foo.data + +from ansible.module_utils.basic import AnsibleModule +AnsibleModule(argument_spec=dict()).exit_json(**results) diff --git a/test/integration/targets/module_utils/library/test_network.py b/test/integration/targets/module_utils/library/test_network.py new file mode 100644 index 0000000..c6a5390 --- /dev/null +++ b/test/integration/targets/module_utils/library/test_network.py @@ -0,0 +1,28 @@ +#!/usr/bin/python + +# Copyright: (c) 2021, 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 + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.network import to_subnet + + +def main(): + module = AnsibleModule(argument_spec=dict( + subnet=dict(), + )) + + subnet = module.params['subnet'] + + if subnet is not None: + split_addr = subnet.split('/') + if len(split_addr) != 2: + module.fail_json("Invalid CIDR notation: expected a subnet mask (e.g. 10.0.0.0/32)") + module.exit_json(resolved=to_subnet(split_addr[0], split_addr[1])) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/module_utils/library/test_no_log.py b/test/integration/targets/module_utils/library/test_no_log.py new file mode 100644 index 0000000..770e0b3 --- /dev/null +++ b/test/integration/targets/module_utils/library/test_no_log.py @@ -0,0 +1,35 @@ +#!/usr/bin/python +# (c) 2021 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 + + +from ansible.module_utils.basic import AnsibleModule, env_fallback + + +def main(): + module = AnsibleModule( + argument_spec=dict( + explicit_pass=dict(type='str', no_log=True), + fallback_pass=dict(type='str', no_log=True, fallback=(env_fallback, ['SECRET_ENV'])), + default_pass=dict(type='str', no_log=True, default='zyx'), + normal=dict(type='str', default='plaintext'), + suboption=dict( + type='dict', + options=dict( + explicit_sub_pass=dict(type='str', no_log=True), + fallback_sub_pass=dict(type='str', no_log=True, fallback=(env_fallback, ['SECRET_SUB_ENV'])), + default_sub_pass=dict(type='str', no_log=True, default='xvu'), + normal=dict(type='str', default='plaintext'), + ), + ), + ), + ) + + module.exit_json(changed=False) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/module_utils/library/test_optional.py b/test/integration/targets/module_utils/library/test_optional.py new file mode 100644 index 0000000..4d0225d --- /dev/null +++ b/test/integration/targets/module_utils/library/test_optional.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# Most of these names are only available via PluginLoader so pylint doesn't +# know they exist +# pylint: disable=no-name-in-module +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils.basic import AnsibleModule + +# internal constants to keep pylint from griping about constant-valued conditionals +_private_false = False +_private_true = True + +# module_utils import statements nested below any block are considered optional "best-effort" for AnsiballZ to include. +# test a number of different import shapes and nesting types to exercise this... + +# first, some nested imports that should succeed... +try: + from ansible.module_utils.urls import fetch_url as yep1 +except ImportError: + yep1 = None + +try: + import ansible.module_utils.common.text.converters as yep2 +except ImportError: + yep2 = None + +try: + # optional import from a legit collection + from ansible_collections.testns.testcoll.plugins.module_utils.legit import importme as yep3 +except ImportError: + yep3 = None + +# and a bunch that should fail to be found, but not break the module_utils payload build in the process... +try: + from ansible.module_utils.bogus import fromnope1 +except ImportError: + fromnope1 = None + +if _private_false: + from ansible.module_utils.alsobogus import fromnope2 +else: + fromnope2 = None + +try: + import ansible.module_utils.verybogus + nope1 = ansible.module_utils.verybogus +except ImportError: + nope1 = None + +# deepish nested with multiple block types- make sure the AST walker made it all the way down +try: + if _private_true: + if _private_true: + if _private_true: + if _private_true: + try: + import ansible.module_utils.stillbogus as nope2 + except ImportError: + raise +except ImportError: + nope2 = None + +try: + # optional import from a valid collection with an invalid package + from ansible_collections.testns.testcoll.plugins.module_utils.bogus import collnope1 +except ImportError: + collnope1 = None + +try: + # optional import from a bogus collection + from ansible_collections.bogusns.boguscoll.plugins.module_utils.bogus import collnope2 +except ImportError: + collnope2 = None + +module = AnsibleModule(argument_spec={}) + +if not all([yep1, yep2, yep3]): + module.fail_json(msg='one or more existing optional imports did not resolve') + +if any([fromnope1, fromnope2, nope1, nope2, collnope1, collnope2]): + module.fail_json(msg='one or more missing optional imports resolved unexpectedly') + +module.exit_json(msg='all missing optional imports behaved as expected') diff --git a/test/integration/targets/module_utils/library/test_override.py b/test/integration/targets/module_utils/library/test_override.py new file mode 100644 index 0000000..7f6e7a5 --- /dev/null +++ b/test/integration/targets/module_utils/library/test_override.py @@ -0,0 +1,11 @@ +#!/usr/bin/python +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils.basic import AnsibleModule +# overridden +from ansible.module_utils.ansible_release import data + +results = {"data": data} + +AnsibleModule(argument_spec=dict()).exit_json(**results) diff --git a/test/integration/targets/module_utils/library/test_recursive_diff.py b/test/integration/targets/module_utils/library/test_recursive_diff.py new file mode 100644 index 0000000..0cf39d9 --- /dev/null +++ b/test/integration/targets/module_utils/library/test_recursive_diff.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +# Copyright: (c) 2020, Matt Martz <matt@sivel.net> +# 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 + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.dict_transformations import recursive_diff + + +def main(): + module = AnsibleModule( + { + 'a': {'type': 'dict'}, + 'b': {'type': 'dict'}, + } + ) + + module.exit_json( + the_diff=recursive_diff( + module.params['a'], + module.params['b'], + ), + ) + + +if __name__ == '__main__': + main() |