summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fontein <felix@fontein.de>2021-03-02 01:10:46 +0100
committerGitHub <noreply@github.com>2021-03-02 01:10:46 +0100
commit3cc693b92c0cbaec6af133e6f73427f1c4f1b28f (patch)
treed97547f5e6389514a36fec8bd758ba5679fe7d42
parentReduce complexity of Templar._lookup slightly (#73277) (diff)
downloadansible-3cc693b92c0cbaec6af133e6f73427f1c4f1b28f.tar.xz
ansible-3cc693b92c0cbaec6af133e6f73427f1c4f1b28f.zip
Import test: improve docs, add more tests (#73600)
-rw-r--r--docs/docsite/rst/dev_guide/testing/sanity/import.rst67
-rw-r--r--test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/bad.py31
-rw-r--r--test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/world.py29
-rw-r--r--test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/random_directory/bad.py8
-rw-r--r--test/integration/targets/ansible-test/ansible_collections/ns/col/tests/sanity/ignore.txt1
-rwxr-xr-xtest/integration/targets/ansible-test/collection-tests/coverage.sh8
-rwxr-xr-xtest/integration/targets/ansible-test/collection-tests/venv.sh8
7 files changed, 148 insertions, 4 deletions
diff --git a/docs/docsite/rst/dev_guide/testing/sanity/import.rst b/docs/docsite/rst/dev_guide/testing/sanity/import.rst
index 4b29636a54..045afee718 100644
--- a/docs/docsite/rst/dev_guide/testing/sanity/import.rst
+++ b/docs/docsite/rst/dev_guide/testing/sanity/import.rst
@@ -1,5 +1,68 @@
import
======
-All Python imports in ``lib/ansible/modules/`` and ``lib/ansible/module_utils/`` which are not from the Python standard library
-must be imported in a try/except ImportError block.
+Ansible allows unchecked imports of some libraries from specific directories, listed at the bottom of this section. Import all other Python libraries in a try/except ImportError block to support sanity tests such as ``validate-modules`` and to allow Ansible to give better error messages to the user. To import a library in a try/except ImportError block:
+
+1. In modules:
+
+ .. code-block:: python
+
+ # Instead of 'import another_library', do:
+
+ import traceback
+
+ try:
+ import another_library
+ except ImportError:
+ HAS_ANOTHER_LIBRARY = False
+ ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
+ else:
+ HAS_ANOTHER_LIBRARY = True
+
+
+ # Later in module code:
+
+ module = AnsibleModule(...)
+
+ if not HAS_ANOTHER_LIBRARY:
+ # Needs: from ansible.module_utils.basic import missing_required_lib
+ module.fail_json(
+ msg=missing_required_lib('another_library'),
+ exception=ANOTHER_LIBRARY_IMPORT_ERROR)
+
+2. In plugins:
+
+ .. code-block:: python
+
+ # Instead of 'import another_library', do:
+
+ from ansible.module_utils.six import raise_from
+
+ try:
+ import another_library
+ except ImportError as imp_exc:
+ ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc
+ else:
+ ANOTHER_LIBRARY_IMPORT_ERROR = None
+
+
+ # Later in plugin code, for example in __init__ of the plugin:
+
+ if ANOTHER_LIBRARY_IMPORT_ERROR:
+ raise_from(
+ AnsibleError('another_library must be installed to use this plugin'),
+ ANOTHER_LIBRARY_IMPORT_ERROR)
+ # If you target only newer Python 3 versions, you can also use the
+ # 'raise ... from ...' syntax.
+
+Ansible allows the following unchecked imports from these specific directories:
+
+* ansible-core:
+
+ * For ``lib/ansible/modules/`` and ``lib/ansible/module_utils/``, unchecked imports are only allowed from the Python standard library;
+ * For ``lib/ansible/plugins/``, unchecked imports are only allowed from the Python standard library, from dependencies of ansible-core, and from ansible-core itself;
+
+* collections:
+
+ * For ``plugins/modules/`` and ``plugins/module_utils/``, unchecked imports are only allowed from the Python standard library;
+ * For other directories in ``plugins/`` (see `the community collection requirements <https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#modules-plugins>`_ for a list), unchecked imports are only allowed from the Python standard library, from dependencies of ansible-core, and from ansible-core itself.
diff --git a/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/bad.py b/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/bad.py
new file mode 100644
index 0000000000..580f9d87b7
--- /dev/null
+++ b/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/bad.py
@@ -0,0 +1,31 @@
+# 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: bad
+short_description: Bad lookup
+description: A bad lookup.
+author:
+ - Ansible Core Team
+'''
+
+EXAMPLES = '''
+- debug:
+ msg: "{{ lookup('ns.col.bad') }}"
+'''
+
+RETURN = ''' # '''
+
+from ansible.plugins.lookup import LookupBase
+from ansible import constants
+
+import lxml
+
+
+class LookupModule(LookupBase):
+ def run(self, terms, variables, **kwargs):
+ self.set_options(var_options=variables, direct=kwargs)
+
+ return terms
diff --git a/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/world.py b/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/world.py
new file mode 100644
index 0000000000..dbb479a726
--- /dev/null
+++ b/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/lookup/world.py
@@ -0,0 +1,29 @@
+# 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: world
+short_description: World lookup
+description: A world lookup.
+author:
+ - Ansible Core Team
+'''
+
+EXAMPLES = '''
+- debug:
+ msg: "{{ lookup('ns.col.world') }}"
+'''
+
+RETURN = ''' # '''
+
+from ansible.plugins.lookup import LookupBase
+from ansible import constants
+
+
+class LookupModule(LookupBase):
+ def run(self, terms, variables, **kwargs):
+ self.set_options(var_options=variables, direct=kwargs)
+
+ return terms
diff --git a/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/random_directory/bad.py b/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/random_directory/bad.py
new file mode 100644
index 0000000000..2e35cf85cd
--- /dev/null
+++ b/test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/random_directory/bad.py
@@ -0,0 +1,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
+
+# This is not an allowed import, but since this file is in a plugins/ subdirectory that is not checked,
+# the import sanity test will not complain.
+import lxml
diff --git a/test/integration/targets/ansible-test/ansible_collections/ns/col/tests/sanity/ignore.txt b/test/integration/targets/ansible-test/ansible_collections/ns/col/tests/sanity/ignore.txt
index 6d7877ba1e..e1b3f4ca09 100644
--- a/test/integration/targets/ansible-test/ansible_collections/ns/col/tests/sanity/ignore.txt
+++ b/test/integration/targets/ansible-test/ansible_collections/ns/col/tests/sanity/ignore.txt
@@ -1,5 +1,6 @@
plugins/modules/bad.py import
plugins/modules/bad.py pylint:ansible-bad-module-import
+plugins/lookup/bad.py import
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-function
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import-from
diff --git a/test/integration/targets/ansible-test/collection-tests/coverage.sh b/test/integration/targets/ansible-test/collection-tests/coverage.sh
index 3d01dd4bc1..033a9836ea 100755
--- a/test/integration/targets/ansible-test/collection-tests/coverage.sh
+++ b/test/integration/targets/ansible-test/collection-tests/coverage.sh
@@ -7,7 +7,13 @@ cd "${WORK_DIR}/ansible_collections/ns/col"
# rename the sanity ignore file to match the current ansible version and update import ignores with the python version
ansible_version="$(python -c 'import ansible.release; print(".".join(ansible.release.__version__.split(".")[:2]))')"
-sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
+if [ "${ANSIBLE_TEST_PYTHON_VERSION}" == "2.6" ]; then
+ # Non-module/module_utils plugins are not checked on this remote-only Python versions
+ sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" | grep -v 'plugins/[^m].* import' > "tests/sanity/ignore-${ansible_version}.txt"
+else
+ sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
+fi
+cat "tests/sanity/ignore-${ansible_version}.txt"
# common args for all tests
common=(--venv --color --truncate 0 "${@}")
diff --git a/test/integration/targets/ansible-test/collection-tests/venv.sh b/test/integration/targets/ansible-test/collection-tests/venv.sh
index 862c8ad989..ba0d2628d6 100755
--- a/test/integration/targets/ansible-test/collection-tests/venv.sh
+++ b/test/integration/targets/ansible-test/collection-tests/venv.sh
@@ -7,7 +7,13 @@ cd "${WORK_DIR}/ansible_collections/ns/col"
# rename the sanity ignore file to match the current ansible version and update import ignores with the python version
ansible_version="$(python -c 'import ansible.release; print(".".join(ansible.release.__version__.split(".")[:2]))')"
-sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
+if [ "${ANSIBLE_TEST_PYTHON_VERSION}" == "2.6" ]; then
+ # Non-module/module_utils plugins are not checked on this remote-only Python versions
+ sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" | grep -v 'plugins/[^m].* import' > "tests/sanity/ignore-${ansible_version}.txt"
+else
+ sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
+fi
+cat "tests/sanity/ignore-${ansible_version}.txt"
# common args for all tests
# each test will be run in a separate venv to verify that requirements have been properly specified