From df59f06d6aa374613c1f76f32eefc00aa8e24bdc Mon Sep 17 00:00:00 2001 From: Matt Clay Date: Thu, 8 Aug 2019 23:51:03 -0700 Subject: [PATCH] Additional ansible-test path fixes. (#60300) * Add missing ansible-test injector symlink. * More ansible-test path fixes. * Expand bin-symlinks docs. --- .../dev_guide/testing/sanity/bin-symlinks.rst | 4 ++++ .../ansible_test/_data/injector/ansible-test | 1 + test/lib/ansible_test/_internal/data.py | 17 ++++++++--------- test/lib/ansible_test/_internal/payload.py | 4 ++-- .../_internal/provider/layout/__init__.py | 4 ++-- .../_internal/sanity/bin_symlinks.py | 19 ++++++++++++++++--- test/lib/ansible_test/_internal/util.py | 4 ++-- 7 files changed, 35 insertions(+), 18 deletions(-) create mode 120000 test/lib/ansible_test/_data/injector/ansible-test diff --git a/docs/docsite/rst/dev_guide/testing/sanity/bin-symlinks.rst b/docs/docsite/rst/dev_guide/testing/sanity/bin-symlinks.rst index fd63318ac20..dcec7ed380d 100644 --- a/docs/docsite/rst/dev_guide/testing/sanity/bin-symlinks.rst +++ b/docs/docsite/rst/dev_guide/testing/sanity/bin-symlinks.rst @@ -5,3 +5,7 @@ The ``bin/`` directory in Ansible must contain only symbolic links to executable These files must reside in the ``lib/ansible/`` or ``test/lib/ansible_test/`` directories. This is required to allow ``ansible-test`` to work with containers and remote hosts when running from an installed version of Ansible. + +Symlinks for each entry point in ``bin/`` must also be present in ``test/lib/ansible_test/_data/injector/``. +Each symlink should point to the ``python.py`` script in the same directory. +This facilitates running with the correct Python interpreter and enabling code coverage. diff --git a/test/lib/ansible_test/_data/injector/ansible-test b/test/lib/ansible_test/_data/injector/ansible-test new file mode 120000 index 00000000000..6bbbfe4d919 --- /dev/null +++ b/test/lib/ansible_test/_data/injector/ansible-test @@ -0,0 +1 @@ +python.py \ No newline at end of file diff --git a/test/lib/ansible_test/_internal/data.py b/test/lib/ansible_test/_internal/data.py index 6beb8f63569..b28b5b86669 100644 --- a/test/lib/ansible_test/_internal/data.py +++ b/test/lib/ansible_test/_internal/data.py @@ -9,11 +9,10 @@ from . import types as t from .util import ( ApplicationError, import_plugins, - ANSIBLE_ROOT, is_subdir, - ANSIBLE_IS_INSTALLED, ANSIBLE_LIB_ROOT, ANSIBLE_TEST_ROOT, + ANSIBLE_SOURCE_ROOT, ) from .provider import ( @@ -65,8 +64,8 @@ class DataContext: if content_path: content = self.__create_content_layout(layout_providers, source_providers, content_path, False) - elif is_subdir(current_path, ANSIBLE_ROOT): - content = self.__create_content_layout(layout_providers, source_providers, ANSIBLE_ROOT, False) + elif ANSIBLE_SOURCE_ROOT and is_subdir(current_path, ANSIBLE_SOURCE_ROOT): + content = self.__create_content_layout(layout_providers, source_providers, ANSIBLE_SOURCE_ROOT, False) else: content = self.__create_content_layout(layout_providers, source_providers, current_path, True) @@ -95,7 +94,7 @@ class DataContext: def __create_ansible_source(self): """Return a tuple of Ansible source files with both absolute and relative paths.""" - if ANSIBLE_IS_INSTALLED: + if not ANSIBLE_SOURCE_ROOT: sources = [] source_provider = InstalledSource(ANSIBLE_LIB_ROOT) @@ -112,9 +111,9 @@ class DataContext: return tuple((os.path.join(self.content.root, path), path) for path in self.content.all_files()) try: - source_provider = find_path_provider(SourceProvider, self.__source_providers, ANSIBLE_ROOT, False) + source_provider = find_path_provider(SourceProvider, self.__source_providers, ANSIBLE_SOURCE_ROOT, False) except ProviderNotFoundForPath: - source_provider = UnversionedSource(ANSIBLE_ROOT) + source_provider = UnversionedSource(ANSIBLE_SOURCE_ROOT) return tuple((os.path.join(source_provider.root, path), path) for path in source_provider.get_paths(source_provider.root)) @@ -148,8 +147,8 @@ def data_init(): # type: () -> DataContext ' - an Ansible collection: {...}/ansible_collections/{namespace}/{collection}/', ] - if not ANSIBLE_IS_INSTALLED: - options.insert(0, ' - the Ansible source: %s/' % ANSIBLE_ROOT) + if ANSIBLE_SOURCE_ROOT: + options.insert(0, ' - the Ansible source: %s/' % ANSIBLE_SOURCE_ROOT) raise ApplicationError('''The current working directory must be at or below: diff --git a/test/lib/ansible_test/_internal/payload.py b/test/lib/ansible_test/_internal/payload.py index db1df19031a..4635bc19a98 100644 --- a/test/lib/ansible_test/_internal/payload.py +++ b/test/lib/ansible_test/_internal/payload.py @@ -18,7 +18,7 @@ from .config import ( from .util import ( display, ANSIBLE_ROOT, - ANSIBLE_IS_INSTALLED, + ANSIBLE_SOURCE_ROOT, remove_tree, is_subdir, ) @@ -59,7 +59,7 @@ def create_payload(args, dst_path): # type: (CommonConfig, str) -> None files = list(data_context().ansible_source) - if ANSIBLE_IS_INSTALLED: + if not ANSIBLE_SOURCE_ROOT: # reconstruct the bin directory which is not available when running from an ansible install files.extend(create_temporary_bin_files(args)) diff --git a/test/lib/ansible_test/_internal/provider/layout/__init__.py b/test/lib/ansible_test/_internal/provider/layout/__init__.py index fae057bf764..fc7de7119a9 100644 --- a/test/lib/ansible_test/_internal/provider/layout/__init__.py +++ b/test/lib/ansible_test/_internal/provider/layout/__init__.py @@ -9,7 +9,7 @@ import os from ... import types as t from ...util import ( - ANSIBLE_ROOT, + ANSIBLE_SOURCE_ROOT, ) from .. import ( @@ -82,7 +82,7 @@ class ContentLayout(Layout): self.unit_path = unit_path self.unit_module_path = unit_module_path self.unit_module_utils_path = unit_module_utils_path - self.is_ansible = root == ANSIBLE_ROOT + self.is_ansible = root == ANSIBLE_SOURCE_ROOT @property def prefix(self): # type: () -> str diff --git a/test/lib/ansible_test/_internal/sanity/bin_symlinks.py b/test/lib/ansible_test/_internal/sanity/bin_symlinks.py index 54fe515810d..bd0ba58e802 100644 --- a/test/lib/ansible_test/_internal/sanity/bin_symlinks.py +++ b/test/lib/ansible_test/_internal/sanity/bin_symlinks.py @@ -26,6 +26,11 @@ from ..payload import ( __file__ as symlink_map_full_path, ) +from ..util import ( + ANSIBLE_BIN_PATH, + ANSIBLE_TEST_DATA_ROOT, +) + class BinSymlinksTest(SanityVersionNeutral): """Sanity test for symlinks in the bin directory.""" @@ -48,10 +53,13 @@ class BinSymlinksTest(SanityVersionNeutral): :type targets: SanityTargets :rtype: TestResult """ - bin_root = os.path.join(data_context().content.root, 'bin') + bin_root = ANSIBLE_BIN_PATH bin_names = os.listdir(bin_root) bin_paths = sorted(os.path.join(bin_root, path) for path in bin_names) + injector_root = os.path.join(ANSIBLE_TEST_DATA_ROOT, 'injector') + injector_names = os.listdir(injector_root) + errors = [] # type: t.List[t.Tuple[str, str]] symlink_map_path = os.path.relpath(symlink_map_full_path, data_context().content.root) @@ -85,10 +93,15 @@ class BinSymlinksTest(SanityVersionNeutral): errors.append((bin_path, 'points to non-executable file "%s"' % dest)) continue - for bin_path, dest in ANSIBLE_BIN_SYMLINK_MAP.items(): - if bin_path not in bin_names: + for bin_name, dest in ANSIBLE_BIN_SYMLINK_MAP.items(): + if bin_name not in bin_names: + bin_path = os.path.join(bin_root, bin_name) errors.append((bin_path, 'missing symlink to "%s" defined in ANSIBLE_BIN_SYMLINK_MAP in file "%s"' % (dest, symlink_map_path))) + if bin_name not in injector_names: + injector_path = os.path.join(injector_root, bin_name) + errors.append((injector_path, 'missing symlink to "python.py"')) + messages = [SanityMessage(message=message, path=os.path.relpath(path, data_context().content.root), confidence=100) for path, message in errors] if errors: diff --git a/test/lib/ansible_test/_internal/util.py b/test/lib/ansible_test/_internal/util.py index b13c39034d0..f9873388220 100644 --- a/test/lib/ansible_test/_internal/util.py +++ b/test/lib/ansible_test/_internal/util.py @@ -68,14 +68,14 @@ ANSIBLE_TEST_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) ANSIBLE_ROOT = os.path.dirname(ANSIBLE_TEST_ROOT) ANSIBLE_BIN_PATH = os.path.dirname(os.path.abspath(sys.argv[0])) ANSIBLE_LIB_ROOT = os.path.join(ANSIBLE_ROOT, 'ansible') -ANSIBLE_IS_INSTALLED = True +ANSIBLE_SOURCE_ROOT = None if not os.path.exists(ANSIBLE_LIB_ROOT): # running from source ANSIBLE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(ANSIBLE_TEST_ROOT))) ANSIBLE_BIN_PATH = os.path.join(ANSIBLE_ROOT, 'bin') ANSIBLE_LIB_ROOT = os.path.join(ANSIBLE_ROOT, 'lib', 'ansible') - ANSIBLE_IS_INSTALLED = False + ANSIBLE_SOURCE_ROOT = ANSIBLE_ROOT ANSIBLE_TEST_DATA_ROOT = os.path.join(ANSIBLE_TEST_ROOT, '_data') ANSIBLE_TEST_CONFIG_ROOT = os.path.join(ANSIBLE_TEST_ROOT, 'config')