diff --git a/leapp/actors/__init__.py b/leapp/actors/__init__.py index 65f0f069..aaa35bc1 100644 --- a/leapp/actors/__init__.py +++ b/leapp/actors/__init__.py @@ -2,7 +2,13 @@ import logging import os import sys -from collections.abc import Sequence + +try: + # Python 3.3+ + from collections.abc import Sequence +except ImportError: + # Python 2.6 through 3.2 + from collections import Sequence from leapp.actors.config import Config, retrieve_config from leapp.compat import string_types diff --git a/leapp/configs/__init__.py b/leapp/configs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/leapp/configs/actor/__init__.py b/leapp/configs/actor/__init__.py new file mode 100644 index 00000000..c48e433d --- /dev/null +++ b/leapp/configs/actor/__init__.py @@ -0,0 +1,13 @@ +""" +:py:mod:`leapp.configs.actor` represents the import location for private actor config schema that +are placed in the actor's configs folder. + + +Example: + If your actor has a configs folder with a schemas.py python module, import it + from the actor like this:: + + from leapp.libraries.actor import schemas + +This directory is intended for the definitions of actor configuration fields. +""" diff --git a/leapp/repository/__init__.py b/leapp/repository/__init__.py index 58b6d164..bc75ef22 100644 --- a/leapp/repository/__init__.py +++ b/leapp/repository/__init__.py @@ -144,8 +144,10 @@ def load(self, resolve=True, stage=None, skip_actors_discovery=False): self.log.debug("Extending LEAPP_COMMON_FILES for common file paths") self._extend_environ_paths('LEAPP_COMMON_FILES', self.files) self.log.debug("Installing repository provided common libraries loader hook") + sys.meta_path.append(LeappLibrariesFinder(module_prefix='leapp.libraries.common', paths=self.libraries)) sys.meta_path.append(LeappLibrariesFinder(module_prefix='leapp.workflows.api', paths=self.apis)) + sys.meta_path.append(LeappLibrariesFinder(module_prefix='leapp.configs', paths=self.configs)) if not skip_actors_discovery: if not stage or stage is _LoadStage.ACTORS: @@ -189,6 +191,15 @@ def mapped_actor_data(data): }) return data + # Note: `configs` are not present here because we are not yet making + # them globally accessible. This is to force people to copy the config + # schema to their Actors instead of importing them from other Actors. + # That copy, in turn, is a good idea so the framework can return an + # error if two Actors share the same config but they have different + # schemafor it (for instance, if Actor Foo and Bar were sharing the + # same config entry but Actor Foo updated the entry in a later version. + # We need to error so Actor Bar can either be ported to the new + # definition or use a different config entry for it's needs.) return { 'repo_dir': self._repo_dir, 'actors': [mapped_actor_data(a.serialize()) for a in self.actors], @@ -199,7 +210,8 @@ def mapped_actor_data(data): 'workflows': filtered_serialization(get_workflows, self.workflows), 'tools': [dict([('path', path)]) for path in self.relative_paths(self.tools)], 'files': [dict([('path', path)]) for path in self.relative_paths(self.files)], - 'libraries': [dict([('path', path)]) for path in self.relative_paths(self.libraries)] + 'libraries': [dict([('path', path)]) for path in self.relative_paths(self.libraries)], + 'configs': [dict([('path', path)]) for path in self.relative_paths(self.configs)], } def _extend_environ_paths(self, name, paths): @@ -268,6 +280,13 @@ def libraries(self): """ return tuple(self._definitions.get(DefinitionKind.LIBRARIES, ())) + @property + def configs(self): + """ + :return: Tuple of configs in the repository + """ + return tuple(self._definitions.get(DefinitionKind.CONFIGS, ())) + @property def files(self): """ diff --git a/leapp/repository/actor_definition.py b/leapp/repository/actor_definition.py index bab23e22..2ba177ac 100644 --- a/leapp/repository/actor_definition.py +++ b/leapp/repository/actor_definition.py @@ -314,6 +314,11 @@ def injected_context(self): module_prefix='leapp.libraries.actor', paths=[os.path.join(self._repo_dir, self.directory, x) for x in self.libraries])) + sys.meta_path.append( + LeappLibrariesFinder( + module_prefix='leapp.configs.actor', + paths=[os.path.join(self._repo_dir, self.directory, x) for x in self.configs])) + previous_path = os.getcwd() os.chdir(os.path.join(self._repo_dir, self._directory)) try: diff --git a/leapp/repository/scan.py b/leapp/repository/scan.py index 378940a4..94e0512f 100644 --- a/leapp/repository/scan.py +++ b/leapp/repository/scan.py @@ -89,6 +89,7 @@ def scan(repository, path): ('workflows', scan_workflows), ('files', scan_files), ('libraries', scan_libraries), + ('configs', scan_configs), ('tests', scan_tests), ('tools', scan_tools), ('apis', scan_apis)) @@ -224,6 +225,21 @@ def scan_libraries(repo, path, repo_path): repo.add(DefinitionKind.LIBRARIES, os.path.relpath(path, repo_path)) +def scan_configs(repo, path, repo_path): + """ + Scans configs and adds them to the repository. + + :param repo: Instance of the repository + :type repo: :py:class:`leapp.repository.Repository` + :param path: path to the configs + :type path: str + :param repo_path: path to the repository + :type repo_path: str + """ + if os.listdir(path): + repo.add(DefinitionKind.CONFIGS, os.path.relpath(path, repo_path)) + + def scan_tools(repo, path, repo_path): """ Scans tools and adds them to the repository.