summaryrefslogtreecommitdiffstats
path: root/src/ansiblelint/_mockings.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/ansiblelint/_mockings.py')
-rw-r--r--src/ansiblelint/_mockings.py86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/ansiblelint/_mockings.py b/src/ansiblelint/_mockings.py
new file mode 100644
index 0000000..6b57d6c
--- /dev/null
+++ b/src/ansiblelint/_mockings.py
@@ -0,0 +1,86 @@
+"""Utilities for mocking ansible modules and roles."""
+from __future__ import annotations
+
+import logging
+import os
+import re
+import sys
+
+from ansiblelint.config import options
+from ansiblelint.constants import ANSIBLE_MOCKED_MODULE, INVALID_CONFIG_RC
+
+_logger = logging.getLogger(__name__)
+
+
+def _make_module_stub(module_name: str) -> None:
+ # a.b.c is treated a collection
+ if re.match(r"^(\w+|\w+\.\w+\.[\.\w]+)$", module_name):
+ parts = module_name.split(".")
+ if len(parts) < 3:
+ path = f"{options.cache_dir}/modules"
+ module_file = f"{options.cache_dir}/modules/{module_name}.py"
+ namespace = None
+ collection = None
+ else:
+ namespace = parts[0]
+ collection = parts[1]
+ path = f"{ options.cache_dir }/collections/ansible_collections/{ namespace }/{ collection }/plugins/modules/{ '/'.join(parts[2:-1]) }"
+ module_file = f"{path}/{parts[-1]}.py"
+ os.makedirs(path, exist_ok=True)
+ _write_module_stub(
+ filename=module_file,
+ name=module_file,
+ namespace=namespace,
+ collection=collection,
+ )
+ else:
+ _logger.error("Config error: %s is not a valid module name.", module_name)
+ sys.exit(INVALID_CONFIG_RC)
+
+
+def _write_module_stub(
+ filename: str,
+ name: str,
+ namespace: str | None = None,
+ collection: str | None = None,
+) -> None:
+ """Write module stub to disk."""
+ body = ANSIBLE_MOCKED_MODULE.format(
+ name=name, collection=collection, namespace=namespace
+ )
+ with open(filename, "w", encoding="utf-8") as f:
+ f.write(body)
+
+
+# pylint: disable=too-many-branches
+def _perform_mockings() -> None: # noqa: C901
+ """Mock modules and roles."""
+ for role_name in options.mock_roles:
+ if re.match(r"\w+\.\w+\.\w+$", role_name):
+ namespace, collection, role_dir = role_name.split(".")
+ path = f"{options.cache_dir}/collections/ansible_collections/{ namespace }/{ collection }/roles/{ role_dir }/"
+ else:
+ path = f"{options.cache_dir}/roles/{role_name}"
+ # Avoid error from makedirs if destination is a broken symlink
+ if os.path.islink(path) and not os.path.exists(path): # pragma: no cover
+ _logger.warning("Removed broken symlink from %s", path)
+ os.unlink(path)
+ os.makedirs(path, exist_ok=True)
+
+ if options.mock_modules:
+ for module_name in options.mock_modules:
+ _make_module_stub(module_name)
+
+
+def _perform_mockings_cleanup() -> None: # noqa: C901
+ """Clean up mocked modules and roles."""
+ for role_name in options.mock_roles:
+ if re.match(r"\w+\.\w+\.\w+$", role_name):
+ namespace, collection, role_dir = role_name.split(".")
+ path = f"{options.cache_dir}/collections/ansible_collections/{ namespace }/{ collection }/roles/{ role_dir }/"
+ else:
+ path = f"{options.cache_dir}/roles/{role_name}"
+ try:
+ os.rmdir(path)
+ except OSError:
+ pass