Skip to content
This repository has been archived by the owner on Jan 14, 2024. It is now read-only.

Commit

Permalink
#59: Add RKD_IMPORTS environment variable
Browse files Browse the repository at this point in the history
  • Loading branch information
blackandred committed Nov 22, 2020
1 parent 6bc8a8d commit 24619a5
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 14 deletions.
26 changes: 26 additions & 0 deletions docs/source/usage/global-envs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ Logs output of each executed task, when set to "true".

.. code:: bash
# Note: This example requires "rkd-harbor" package to be installed from PyPI
RKD_AUDIT_SESSION_LOG=true harbor :service:list # RiotKit Harbor is another project based on RKD
# ls .rkd/logs/2020-06-11/11\:06\:02.068556/
task-1-init.log task-2-harbor_service_list.log
Expand All @@ -68,3 +71,26 @@ RKD_SYS_LOG_LEVEL
~~~~~~~~~~~~~~~~~

Use for debugging. The variable is read in very early stage of RKD initialization, before :code:`:init` task, and before context preparation.

.. code:: bash
RKD_SYS_LOG_LEVEL=debug rkd :tasks
.. _RKD_IMPORTS:

RKD_IMPORTS
~~~~~~~~~~~

Allows to import a task, or group of tasks (module) inline, without need to create a Makefile.
Useful in daily tasks to create handy shortcuts, also very useful for testing tasks and embedding them inside other applications.

"**:**" character is a separator for multiple imports.


.. code:: bash
# note: Those examples requires "rkt_utils" package from PyPI
RKD_IMPORTS="rkt_utils.docker" rkd :docker:tag
RKD_IMPORTS="rkt_utils.docker:rkt_ciutils.boatci:rkd_python" rkd :tasks
14 changes: 14 additions & 0 deletions docs/source/usage/importing-tasks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,19 @@ Example: Given we want to import task "InjectQEMUBinaryIntoContainerTask", or we
IMPORTS += [TaskDeclaration(InjectQEMUBinaryIntoContainerTask)]
3) Inline syntax
----------------

Tasks could be imported also in shell, for quick check, handy scripts, or for embedding inside other applications.

.. code:: bash
# note: Those examples requires "rkt_utils" package from PyPI
RKD_IMPORTS="rkt_utils.docker" rkd :docker:tag
RKD_IMPORTS="rkt_utils.docker:rkt_ciutils.boatci:rkd_python" rkd :tasks
For more information about this environment variable check it's documentation page: :ref:`RKD_IMPORTS`

Ready to go? Check :ref:`Built-in tasks` that you can import in your Makefile
-----------------------------------------------------------------------------
28 changes: 20 additions & 8 deletions src/rkd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from .resolver import TaskResolver
from .validator import TaskDeclarationValidator
from .execution.executor import OneByOneTaskExecutor
from .exception import TaskNotFoundException
from .api.inputoutput import SystemIO, LEVEL_INFO as LOG_LEVEL_INFO
from .exception import TaskNotFoundException, ParsingException, YamlParsingException
from .api.inputoutput import SystemIO
from .api.inputoutput import UnbufferedStdout
from .aliasgroups import parse_alias_groups_from_env

Expand Down Expand Up @@ -47,20 +47,32 @@ def main(self, argv: list):
io.silent = True
io.set_log_level(os.getenv('RKD_SYS_LOG_LEVEL', 'info'))

# load context of components
self._ctx = ContextFactory(io).create_unified_context()

resolver = TaskResolver(self._ctx, parse_alias_groups_from_env(os.getenv('RKD_ALIAS_GROUPS', '')))
# load context of components - all tasks, plugins etc.
try:
self._ctx = ContextFactory(io).create_unified_context(
additional_imports=os.getenv('RKD_IMPORTS', '').split(':') if os.getenv('RKD_IMPORTS') else []
)
except ParsingException as e:
io.silent = False
io.error_msg('Cannot import tasks/module from RKD_IMPORTS environment variable. Details: {}'.format(str(e)))
sys.exit(1)

except YamlParsingException as e:
io.silent = False
io.error_msg('Cannot import tasks/module from one of makefile.yaml files. Details: {}'.format(str(e)))
sys.exit(1)

task_resolver = TaskResolver(self._ctx, parse_alias_groups_from_env(os.getenv('RKD_ALIAS_GROUPS', '')))
executor = OneByOneTaskExecutor(self._ctx)

# iterate over each task, parse commandline arguments
requested_tasks = CommandlineParsingHelper.create_grouped_arguments([':init'] + argv[1:])

# validate all tasks
resolver.resolve(requested_tasks, TaskDeclarationValidator.assert_declaration_is_valid)
task_resolver.resolve(requested_tasks, TaskDeclarationValidator.assert_declaration_is_valid)

# execute all tasks
resolver.resolve(requested_tasks, executor.execute)
task_resolver.resolve(requested_tasks, executor.execute)

executor.get_observer().execution_finished()

Expand Down
22 changes: 20 additions & 2 deletions src/rkd/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .api.syntax import TaskAliasDeclaration
from .api.syntax import GroupDeclaration
from .api.contract import ContextInterface
from .api.parsing import SyntaxParsing
from .argparsing import CommandlineParsingHelper
from .api.inputoutput import SystemIO
from .exception import TaskNotFoundException
Expand Down Expand Up @@ -225,7 +226,20 @@ def _load_from_py(path: str):
directory=path
)

def create_unified_context(self, chdir: str = '') -> ApplicationContext:
def _load_context_from_list_of_imports(self, additional_imports: List[str]) -> ApplicationContext:
"""
Creates ApplicationContext from simple list of imports
:param additional_imports:
:return:
"""

declarations = SyntaxParsing.parse_imports_by_list_of_classes(additional_imports)
ctx = ApplicationContext(declarations, [], '')

return ctx

def create_unified_context(self, chdir: str = '', additional_imports: List[str] = None) -> ApplicationContext:
"""
Creates a merged context in order:
- Internal/Core (this package)
Expand Down Expand Up @@ -261,10 +275,14 @@ def create_unified_context(self, chdir: str = '') -> ApplicationContext:

try:
ctx = ApplicationContext.merge(ctx, self._load_context_from_directory(path))
ctx.io = self._io
except ContextFileNotFoundException:
pass

# imports added by eg. environment variable
if additional_imports:
ctx = ApplicationContext.merge(ctx, self._load_context_from_list_of_imports(additional_imports))

ctx.io = self._io
ctx.compile()

return ctx
Expand Down
2 changes: 1 addition & 1 deletion src/rkd/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def from_import_error(cls, import_str: str, class_name: str, error: Exception) -
def from_class_not_found_in_module_error(cls, import_str: str, class_name: str,
import_path: str) -> 'ParsingException':
return cls(
'Import "%s" is invalid. Class "%s" not found in module "%s"' % (
'Import "%s" is invalid. Class or method "%s" not found in module "%s"' % (
import_str, class_name, import_path
)
)
Expand Down
7 changes: 4 additions & 3 deletions src/rkd/standardlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ def get_group_name(self) -> str:
def get_declared_envs(self) -> Dict[str, str]:
return {
'RKD_DEPTH': '0',
'RKD_PATH': '',
'RKD_ALIAS_GROUPS': '',
'RKD_PATH': '', # supported by core, here only for documentation in CLI
'RKD_ALIAS_GROUPS': '', # supported by core, here only for documentation in CLI
'RKD_UI': 'true',
'RKD_SYS_LOG_LEVEL': 'info'
'RKD_SYS_LOG_LEVEL': 'info', # supported by core, here only for documentation in CLI
'RKD_IMPORTS': '' # supported by core, here only for documentation in CLI
}

def configure_argparse(self, parser: ArgumentParser):
Expand Down

0 comments on commit 24619a5

Please sign in to comment.