diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3c3ddd20c4..f580432f8b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,7 @@ repos: exclude: ^projects/control-service/projects/helm_charts - id: check-json - id: check-ast + exclude: ^projects/vdk-core/tests/functional/run/jobs/syntax-error-job/1_step.py - id: check-added-large-files - id: end-of-file-fixer - id: trailing-whitespace @@ -27,6 +28,7 @@ repos: hooks: - id: black language_version: python3 + exclude: ^projects/vdk-core/tests/functional/run/jobs/syntax-error-job/1_step.py # ensure pydoc is up-to standard - repo: https://github.com/pycqa/pydocstyle rev: 6.1.1 diff --git a/projects/vdk-core/src/vdk/internal/builtin_plugins/run/file_based_step.py b/projects/vdk-core/src/vdk/internal/builtin_plugins/run/file_based_step.py index 511cae2b6c..6bff73cc07 100644 --- a/projects/vdk-core/src/vdk/internal/builtin_plugins/run/file_based_step.py +++ b/projects/vdk-core/src/vdk/internal/builtin_plugins/run/file_based_step.py @@ -74,8 +74,27 @@ def run(job_input) sys.path.insert(0, str(step.job_dir)) filename = step.file_path.name namespace = "step_" + str(filename).lower().strip(".py") - python_module = imp.load_source(namespace, str(step.file_path)) success = False + + try: + log.debug("Loading %s ..." % filename) + python_module = imp.load_source(namespace, str(step.file_path)) + log.debug("Loading %s SUCCESS" % filename) + except BaseException as e: + log.info("Loading %s FAILURE" % filename) + errors.log_and_rethrow( + to_be_fixed_by=errors.ResolvableBy.USER_ERROR, + log=log, + what_happened="Failed loading job sources of %s" % filename, + why_it_happened=errors.MSG_WHY_FROM_EXCEPTION(e), + consequences=errors.MSG_CONSEQUENCE_TERMINATING_APP, + countermeasures=errors.MSG_COUNTERMEASURE_FIX_PARENT_EXCEPTION + + " Most likely importing a dependency or data job step failed, see" + + " logs for details and fix the failed step (details in stacktrace).", + exception=e, + wrap_in_vdk_error=True, + ) + for _, func in inspect.getmembers(python_module, inspect.isfunction): if func.__name__ == "run": try: diff --git a/projects/vdk-core/tests/functional/run/jobs/syntax-error-job/1_step.py b/projects/vdk-core/tests/functional/run/jobs/syntax-error-job/1_step.py new file mode 100644 index 0000000000..e059a2491b --- /dev/null +++ b/projects/vdk-core/tests/functional/run/jobs/syntax-error-job/1_step.py @@ -0,0 +1,7 @@ +# Copyright 2021 VMware, Inc. +# SPDX-License-Identifier: Apache-2.0 +from vdk.api.job_input import IJobInput + + +def run(job_input: IJobInput): + syntax error # type: ignore diff --git a/projects/vdk-core/tests/functional/run/test_run_errors.py b/projects/vdk-core/tests/functional/run/test_run_errors.py index 748ae2cf4b..4bd5aba26a 100644 --- a/projects/vdk-core/tests/functional/run/test_run_errors.py +++ b/projects/vdk-core/tests/functional/run/test_run_errors.py @@ -28,6 +28,15 @@ def tmp_termination_msg_file(tmpdir) -> pathlib.Path: yield pathlib.Path(out_file) +def test_initialize_step_user_error(tmp_termination_msg_file): + errors.clear_intermediate_errors() + runner = CliEntryBasedTestRunner() + + result: Result = runner.invoke(["run", util.job_path("syntax-error-job")]) + cli_assert_equal(1, result) + assert (json.loads(tmp_termination_msg_file.read_text())["status"]) == "User error" + + def test_run_user_error(tmp_termination_msg_file): errors.clear_intermediate_errors() runner = CliEntryBasedTestRunner()