frogml-cli 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- frogml_cli/__init__.py +10 -0
- frogml_cli/cli.py +40 -0
- frogml_cli/commands/__init__.py +0 -0
- frogml_cli/commands/_logic/__init__.py +0 -0
- frogml_cli/commands/_logic/tools.py +6 -0
- frogml_cli/commands/alerts/__init__.py +0 -0
- frogml_cli/commands/alerts/alerts_commnad_group.py +18 -0
- frogml_cli/commands/alerts/delete/__init__.py +0 -0
- frogml_cli/commands/alerts/delete/_logic.py +5 -0
- frogml_cli/commands/alerts/delete/ui.py +10 -0
- frogml_cli/commands/alerts/list/__init__.py +0 -0
- frogml_cli/commands/alerts/list/_logic.py +23 -0
- frogml_cli/commands/alerts/list/ui.py +17 -0
- frogml_cli/commands/alerts/register/__init__.py +0 -0
- frogml_cli/commands/alerts/register/_logic.py +72 -0
- frogml_cli/commands/alerts/register/ui.py +30 -0
- frogml_cli/commands/audience/__init__.py +0 -0
- frogml_cli/commands/audience/_logic/__init__.py +0 -0
- frogml_cli/commands/audience/_logic/config/__init__.py +0 -0
- frogml_cli/commands/audience/_logic/config/config_base.py +15 -0
- frogml_cli/commands/audience/_logic/config/parser.py +30 -0
- frogml_cli/commands/audience/_logic/config/v1/__init__.py +0 -0
- frogml_cli/commands/audience/_logic/config/v1/audience_config.py +25 -0
- frogml_cli/commands/audience/_logic/config/v1/conditions_config.py +59 -0
- frogml_cli/commands/audience/_logic/config/v1/config_v1.py +23 -0
- frogml_cli/commands/audience/_logic/config/v1/route_config.py +15 -0
- frogml_cli/commands/audience/_logic/config/v1/spec.py +9 -0
- frogml_cli/commands/audience/audience_api_dump.py +86 -0
- frogml_cli/commands/audience/audience_commands_group.py +30 -0
- frogml_cli/commands/audience/create/__init__.py +0 -0
- frogml_cli/commands/audience/create/logic.py +41 -0
- frogml_cli/commands/audience/create/ui.py +21 -0
- frogml_cli/commands/audience/delete/__init__.py +0 -0
- frogml_cli/commands/audience/delete/logic.py +13 -0
- frogml_cli/commands/audience/delete/ui.py +17 -0
- frogml_cli/commands/audience/get/__init__.py +0 -0
- frogml_cli/commands/audience/get/logic.py +14 -0
- frogml_cli/commands/audience/get/ui.py +25 -0
- frogml_cli/commands/audience/list/__init__.py +0 -0
- frogml_cli/commands/audience/list/logic.py +16 -0
- frogml_cli/commands/audience/list/ui.py +26 -0
- frogml_cli/commands/audience/update/__init__.py +0 -0
- frogml_cli/commands/audience/update/logic.py +37 -0
- frogml_cli/commands/audience/update/ui.py +26 -0
- frogml_cli/commands/auto_scalling/__init__.py +0 -0
- frogml_cli/commands/auto_scalling/_logic/__init__.py +0 -0
- frogml_cli/commands/auto_scalling/_logic/config/__init__.py +3 -0
- frogml_cli/commands/auto_scalling/_logic/config/config.py +152 -0
- frogml_cli/commands/auto_scalling/_logic/config/parser.py +21 -0
- frogml_cli/commands/auto_scalling/attach/__init__.py +0 -0
- frogml_cli/commands/auto_scalling/attach/_logic.py +43 -0
- frogml_cli/commands/auto_scalling/attach/ui.py +21 -0
- frogml_cli/commands/auto_scalling/autoscaling_commands_group.py +15 -0
- frogml_cli/commands/automations/__init__.py +0 -0
- frogml_cli/commands/automations/automations_commands_group.py +30 -0
- frogml_cli/commands/automations/delete/__init__.py +0 -0
- frogml_cli/commands/automations/delete/_logic.py +6 -0
- frogml_cli/commands/automations/delete/ui.py +23 -0
- frogml_cli/commands/automations/executions/__init__.py +0 -0
- frogml_cli/commands/automations/executions/executions_commands_group.py +14 -0
- frogml_cli/commands/automations/executions/list/__init__.py +0 -0
- frogml_cli/commands/automations/executions/list/_logic.py +8 -0
- frogml_cli/commands/automations/executions/list/ui.py +27 -0
- frogml_cli/commands/automations/list/__init__.py +0 -0
- frogml_cli/commands/automations/list/_logic.py +36 -0
- frogml_cli/commands/automations/list/ui.py +21 -0
- frogml_cli/commands/automations/register/__init__.py +0 -0
- frogml_cli/commands/automations/register/_logic.py +43 -0
- frogml_cli/commands/automations/register/ui.py +44 -0
- frogml_cli/commands/config/__init__.py +0 -0
- frogml_cli/commands/config/add/__init__.py +0 -0
- frogml_cli/commands/config/add/ui.py +62 -0
- frogml_cli/commands/config/config_commands_group.py +11 -0
- frogml_cli/commands/feature_store/__init__.py +0 -0
- frogml_cli/commands/feature_store/backfill/__init__.py +0 -0
- frogml_cli/commands/feature_store/backfill/_logic.py +140 -0
- frogml_cli/commands/feature_store/backfill/ui.py +129 -0
- frogml_cli/commands/feature_store/delete/__init__.py +0 -0
- frogml_cli/commands/feature_store/delete/_logic.py +107 -0
- frogml_cli/commands/feature_store/delete/ui.py +40 -0
- frogml_cli/commands/feature_store/execution/__init__.py +0 -0
- frogml_cli/commands/feature_store/execution/ui.py +19 -0
- frogml_cli/commands/feature_store/feature_store_command_group.py +29 -0
- frogml_cli/commands/feature_store/list/__init__.py +0 -0
- frogml_cli/commands/feature_store/list/ui.py +140 -0
- frogml_cli/commands/feature_store/pause/__init__.py +0 -0
- frogml_cli/commands/feature_store/pause/ui.py +18 -0
- frogml_cli/commands/feature_store/register/__init__.py +0 -0
- frogml_cli/commands/feature_store/register/_logic.py +369 -0
- frogml_cli/commands/feature_store/register/ui.py +111 -0
- frogml_cli/commands/feature_store/resume/__init__.py +0 -0
- frogml_cli/commands/feature_store/resume/ui.py +18 -0
- frogml_cli/commands/feature_store/trigger/__init__.py +0 -0
- frogml_cli/commands/feature_store/trigger/ui.py +39 -0
- frogml_cli/commands/models/__init__.py +0 -0
- frogml_cli/commands/models/build/__init__.py +0 -0
- frogml_cli/commands/models/build/_logic/__init__.py +0 -0
- frogml_cli/commands/models/build/_logic/build_steps.py +42 -0
- frogml_cli/commands/models/build/_logic/client_logs/__init__.py +0 -0
- frogml_cli/commands/models/build/_logic/client_logs/cli_phase_run_handler.py +123 -0
- frogml_cli/commands/models/build/_logic/client_logs/cli_trigger_build_logger.py +19 -0
- frogml_cli/commands/models/build/_logic/client_logs/logger.py +88 -0
- frogml_cli/commands/models/build/_logic/client_logs/messages.py +36 -0
- frogml_cli/commands/models/build/_logic/client_logs/spinner.py +14 -0
- frogml_cli/commands/models/build/_logic/client_logs/trigger_build_logger.py +54 -0
- frogml_cli/commands/models/build/_logic/client_logs/utils.py +12 -0
- frogml_cli/commands/models/build/_logic/phase/__init__.py +0 -0
- frogml_cli/commands/models/build/_logic/phase/a_fetch_model_code/__init__.py +20 -0
- frogml_cli/commands/models/build/_logic/phase/a_fetch_model_code/get_sdk_version_step.py +15 -0
- frogml_cli/commands/models/build/_logic/phase/b_remote_register_frogml_build/__init__.py +16 -0
- frogml_cli/commands/models/build/_logic/phase/c_deploy/__init__.py +6 -0
- frogml_cli/commands/models/build/_logic/phase/c_deploy/build_polling_status.py +55 -0
- frogml_cli/commands/models/build/_logic/phase/c_deploy/deploy_build.py +61 -0
- frogml_cli/commands/models/build/_logic/util/__init__.py +0 -0
- frogml_cli/commands/models/build/_logic/util/protobuf_factory.py +45 -0
- frogml_cli/commands/models/build/_logic/util/step_decorator.py +60 -0
- frogml_cli/commands/models/build/_logic/util/text.py +9 -0
- frogml_cli/commands/models/build/_logic/wait_until_finished.py +27 -0
- frogml_cli/commands/models/build/ui.py +337 -0
- frogml_cli/commands/models/builds/__init__.py +0 -0
- frogml_cli/commands/models/builds/builds_commands_group.py +16 -0
- frogml_cli/commands/models/builds/cancel/__init__.py +0 -0
- frogml_cli/commands/models/builds/cancel/_logic.py +5 -0
- frogml_cli/commands/models/builds/cancel/ui.py +15 -0
- frogml_cli/commands/models/builds/logs/__init__.py +0 -0
- frogml_cli/commands/models/builds/logs/ui.py +35 -0
- frogml_cli/commands/models/builds/status/__init__.py +0 -0
- frogml_cli/commands/models/builds/status/_logic.py +6 -0
- frogml_cli/commands/models/builds/status/ui.py +39 -0
- frogml_cli/commands/models/create/__init__.py +0 -0
- frogml_cli/commands/models/create/_logic.py +40 -0
- frogml_cli/commands/models/create/ui.py +46 -0
- frogml_cli/commands/models/delete/__init__.py +0 -0
- frogml_cli/commands/models/delete/_logic.py +18 -0
- frogml_cli/commands/models/delete/ui.py +25 -0
- frogml_cli/commands/models/deployments/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/_logic/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/_logic/advance_deployment_options_handler.py +31 -0
- frogml_cli/commands/models/deployments/deploy/_logic/base_deploy_executor.py +70 -0
- frogml_cli/commands/models/deployments/deploy/_logic/deploy_config.py +261 -0
- frogml_cli/commands/models/deployments/deploy/_logic/deployment.py +407 -0
- frogml_cli/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +116 -0
- frogml_cli/commands/models/deployments/deploy/_logic/deployment_response_handler.py +156 -0
- frogml_cli/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +98 -0
- frogml_cli/commands/models/deployments/deploy/_logic/get_latest_successful_build.py +28 -0
- frogml_cli/commands/models/deployments/deploy/_logic/local_deployment.py +193 -0
- frogml_cli/commands/models/deployments/deploy/batch/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/batch/_logic/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/batch/_logic/advanced_deployment_mapper.py +15 -0
- frogml_cli/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +24 -0
- frogml_cli/commands/models/deployments/deploy/batch/ui.py +119 -0
- frogml_cli/commands/models/deployments/deploy/deploy_commands_group.py +19 -0
- frogml_cli/commands/models/deployments/deploy/realtime/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/realtime/_logic/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/realtime/_logic/advanced_deployment_mapper.py +21 -0
- frogml_cli/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py +24 -0
- frogml_cli/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py +75 -0
- frogml_cli/commands/models/deployments/deploy/realtime/ui.py +202 -0
- frogml_cli/commands/models/deployments/deploy/streaming/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/streaming/_logic/__init__.py +0 -0
- frogml_cli/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py +24 -0
- frogml_cli/commands/models/deployments/deploy/streaming/_logic/serving_strategy_mapper.py +38 -0
- frogml_cli/commands/models/deployments/deploy/streaming/ui.py +206 -0
- frogml_cli/commands/models/deployments/undeploy/__init__.py +0 -0
- frogml_cli/commands/models/deployments/undeploy/_logic/__init__.py +0 -0
- frogml_cli/commands/models/deployments/undeploy/_logic/request_undeploy.py +249 -0
- frogml_cli/commands/models/deployments/undeploy/ui.py +61 -0
- frogml_cli/commands/models/describe/__init__.py +0 -0
- frogml_cli/commands/models/describe/_logic.py +169 -0
- frogml_cli/commands/models/describe/ui.py +35 -0
- frogml_cli/commands/models/executions/__init__.py +0 -0
- frogml_cli/commands/models/executions/cancel/__init__.py +0 -0
- frogml_cli/commands/models/executions/cancel/_logic.py +9 -0
- frogml_cli/commands/models/executions/cancel/ui.py +27 -0
- frogml_cli/commands/models/executions/execution_commands_group.py +24 -0
- frogml_cli/commands/models/executions/report/__init__.py +0 -0
- frogml_cli/commands/models/executions/report/_logic.py +14 -0
- frogml_cli/commands/models/executions/report/ui.py +43 -0
- frogml_cli/commands/models/executions/start/__init__.py +0 -0
- frogml_cli/commands/models/executions/start/_logic.py +83 -0
- frogml_cli/commands/models/executions/start/ui.py +208 -0
- frogml_cli/commands/models/executions/status/__init__.py +0 -0
- frogml_cli/commands/models/executions/status/_logic.py +13 -0
- frogml_cli/commands/models/executions/status/ui.py +27 -0
- frogml_cli/commands/models/init/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/initialize_model_structure.py +40 -0
- frogml_cli/commands/models/init/_logic/template/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/churn/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/churn/cookiecutter.json +3 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/model.py +99 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/test_churn.py +32 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/cookiecutter.json +3 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/conda.yml +11 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
- frogml_cli/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/model.py +108 -0
- frogml_cli/commands/models/init/_logic/template/general/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/general/cookiecutter.json +6 -0
- frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/__init__.py +5 -0
- frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/conda.yml +8 -0
- frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/model.py +66 -0
- frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/test_qwak_model.py +5 -0
- frogml_cli/commands/models/init/_logic/template/titanic/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic/cookiecutter.json +3 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/conda.yml +11 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/model.py +98 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +24 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/cookiecutter.json +3 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/model.py +98 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/pyproject.toml +20 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- frogml_cli/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +25 -0
- frogml_cli/commands/models/init/ui.py +61 -0
- frogml_cli/commands/models/list/__init__.py +0 -0
- frogml_cli/commands/models/list/_logic.py +5 -0
- frogml_cli/commands/models/list/ui.py +41 -0
- frogml_cli/commands/models/list_models/__init__.py +0 -0
- frogml_cli/commands/models/list_models/_logic.py +11 -0
- frogml_cli/commands/models/list_models/ui.py +60 -0
- frogml_cli/commands/models/metadata/__init__.py +0 -0
- frogml_cli/commands/models/metadata/_logic.py +12 -0
- frogml_cli/commands/models/metadata/ui.py +60 -0
- frogml_cli/commands/models/models_command_group.py +44 -0
- frogml_cli/commands/models/runtime/__init__.py +0 -0
- frogml_cli/commands/models/runtime/logs/__init__.py +0 -0
- frogml_cli/commands/models/runtime/logs/ui.py +63 -0
- frogml_cli/commands/models/runtime/runtime_commands_group.py +17 -0
- frogml_cli/commands/models/runtime/update/__init__.py +0 -0
- frogml_cli/commands/models/runtime/update/_logic.py +9 -0
- frogml_cli/commands/models/runtime/update/ui.py +17 -0
- frogml_cli/commands/secrets/__init__.py +0 -0
- frogml_cli/commands/secrets/delete/__init__.py +0 -0
- frogml_cli/commands/secrets/delete/_logic.py +5 -0
- frogml_cli/commands/secrets/delete/ui.py +21 -0
- frogml_cli/commands/secrets/get/__init__.py +0 -0
- frogml_cli/commands/secrets/get/_logic.py +5 -0
- frogml_cli/commands/secrets/get/ui.py +17 -0
- frogml_cli/commands/secrets/secrets_commands_group.py +19 -0
- frogml_cli/commands/secrets/set/__init__.py +0 -0
- frogml_cli/commands/secrets/set/_logic.py +5 -0
- frogml_cli/commands/secrets/set/ui.py +16 -0
- frogml_cli/commands/ui_tools.py +18 -0
- frogml_cli/exceptions/__init__.py +14 -0
- frogml_cli/exceptions/frogml_command_exception.py +2 -0
- frogml_cli/exceptions/frogml_deploy_new_build_failed.py +5 -0
- frogml_cli/exceptions/frogml_resource_not_found.py +2 -0
- frogml_cli/inner/__init__.py +0 -0
- frogml_cli/inner/file_registry.py +98 -0
- frogml_cli/inner/tools/__init__.py +0 -0
- frogml_cli/inner/tools/cli_tools.py +179 -0
- frogml_cli/inner/tools/config_handler.py +29 -0
- frogml_cli/inner/tools/dataclasses_utils.py +21 -0
- frogml_cli/inner/tools/logger/__init__.py +3 -0
- frogml_cli/inner/tools/logger/logger.py +278 -0
- frogml_cli/inner/tools/logger/logging.yml +79 -0
- frogml_cli/inner/tools/tracking.py +47 -0
- frogml_cli/main.py +9 -0
- frogml_cli/tools/__init__.py +0 -0
- frogml_cli/tools/colors.py +13 -0
- frogml_cli/tools/const.py +3 -0
- frogml_cli/tools/files.py +63 -0
- frogml_cli/tools/log_handling.py +159 -0
- frogml_cli/tools/utils.py +45 -0
- frogml_cli-0.0.1.dist-info/METADATA +51 -0
- frogml_cli-0.0.1.dist-info/RECORD +287 -0
- frogml_cli-0.0.1.dist-info/WHEEL +4 -0
- frogml_cli-0.0.1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
import click
|
2
|
+
from frogml._proto.qwak.feature_store.features.feature_set_service_pb2 import (
|
3
|
+
RunBatchFeatureSetResponse,
|
4
|
+
)
|
5
|
+
from frogml.core.clients.feature_store import FeatureRegistryClient
|
6
|
+
from frogml.core.exceptions import FrogmlException
|
7
|
+
|
8
|
+
from frogml_cli.inner.tools.cli_tools import FrogMLCommand
|
9
|
+
from frogml_cli.tools.colors import Color
|
10
|
+
|
11
|
+
|
12
|
+
@click.command(
|
13
|
+
"trigger", cls=FrogMLCommand, help="Trigger a batch feature set job ingestion job"
|
14
|
+
)
|
15
|
+
@click.argument("name")
|
16
|
+
def trigger_feature_set(name, **kwargs):
|
17
|
+
"""
|
18
|
+
Trigger a batch feature set ingestion job
|
19
|
+
|
20
|
+
Args:
|
21
|
+
name: Feature set name that will be triggered.
|
22
|
+
"""
|
23
|
+
try:
|
24
|
+
result: RunBatchFeatureSetResponse = FeatureRegistryClient().run_feature_set(
|
25
|
+
feature_set_name=name
|
26
|
+
)
|
27
|
+
except Exception as e:
|
28
|
+
print(
|
29
|
+
f"{Color.RED} Failed to trigger a batch feature set ingestion for feature set {name} {Color.END}"
|
30
|
+
)
|
31
|
+
raise FrogmlException(
|
32
|
+
f"Failed to trigger a batch feature set ingestion for feature set {name}"
|
33
|
+
) from e
|
34
|
+
|
35
|
+
print(
|
36
|
+
f"{Color.GREEN}Successfully triggered a batch feature set ingestion for feature set: {Color.YELLOW}{name}"
|
37
|
+
)
|
38
|
+
if result.execution_id:
|
39
|
+
print(f"{Color.WHITE} Execution ID: {Color.YELLOW}{result.execution_id}")
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from typing import Tuple
|
2
|
+
|
3
|
+
from frogml.core.inner.build_config.build_config_v1 import BuildConfigV1
|
4
|
+
from frogml.core.inner.build_logic.interface.build_phase import BuildPhase
|
5
|
+
from frogml.core.inner.build_logic.phases.phases_pipeline import PhasesPipeline
|
6
|
+
from frogml.core.inner.build_logic.trigger_build_context import TriggerBuildContext
|
7
|
+
|
8
|
+
from .client_logs.messages import SUCCESS_MSG_REMOTE_WITH_DEPLOY, SUCCESS_MSG_REMOTE
|
9
|
+
from .phase.a_fetch_model_code import get_fetch_model_code_steps
|
10
|
+
from .phase.b_remote_register_frogml_build import get_remote_register_frogml_build_steps
|
11
|
+
from .phase.c_deploy import get_deploy_steps
|
12
|
+
|
13
|
+
|
14
|
+
def remote_build_steps(config: BuildConfigV1) -> PhasesPipeline:
|
15
|
+
steps_root = PhasesPipeline(config=config, context=TriggerBuildContext())
|
16
|
+
steps_root.add_phase(
|
17
|
+
steps=get_fetch_model_code_steps(),
|
18
|
+
build_phase=BuildPhase(phase_id="FETCHING_MODEL_CODE"),
|
19
|
+
)
|
20
|
+
steps_root.add_phase(
|
21
|
+
steps=get_remote_register_frogml_build_steps(),
|
22
|
+
build_phase=BuildPhase(phase_id="REGISTERING_FROGML_BUILD"),
|
23
|
+
)
|
24
|
+
|
25
|
+
if config.deploy:
|
26
|
+
steps_root.add_phase(
|
27
|
+
steps=get_deploy_steps(),
|
28
|
+
build_phase=BuildPhase(phase_id="DEPLOYING_PHASE", name="Deploying", description="Deploying"),
|
29
|
+
)
|
30
|
+
|
31
|
+
return steps_root
|
32
|
+
|
33
|
+
|
34
|
+
def create_pipeline(
|
35
|
+
config: BuildConfigV1,
|
36
|
+
) -> Tuple[PhasesPipeline, str]:
|
37
|
+
success_message = (
|
38
|
+
SUCCESS_MSG_REMOTE_WITH_DEPLOY if config.deploy else SUCCESS_MSG_REMOTE
|
39
|
+
)
|
40
|
+
pipeline = remote_build_steps(config)
|
41
|
+
|
42
|
+
return pipeline, success_message
|
File without changes
|
@@ -0,0 +1,123 @@
|
|
1
|
+
from contextlib import contextmanager
|
2
|
+
from logging import Logger
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
from frogml.core.inner.build_logic.interface.build_phase import BuildPhase
|
6
|
+
from frogml.core.inner.build_logic.interface.phase_run_handler import PhaseRunHandler
|
7
|
+
from frogml.core.inner.build_logic.phases.phases_pipeline import PhasesPipeline
|
8
|
+
from yaspin import yaspin
|
9
|
+
|
10
|
+
from frogml_cli.tools.colors import Color
|
11
|
+
from .cli_trigger_build_logger import CliTriggerBuildLogger
|
12
|
+
from .messages import (
|
13
|
+
FAILED_CONTACT_JFROG_SUPPORT,
|
14
|
+
)
|
15
|
+
from .utils import zip_logs
|
16
|
+
|
17
|
+
|
18
|
+
class CLIPhaseRunHandler(PhaseRunHandler):
|
19
|
+
BUILD_IN_PROGRESS_FORMAT = "Build phase in progress: {}"
|
20
|
+
BUILD_FINISHED_FORMAT = "Phase successfully finished: {} after {} seconds"
|
21
|
+
KEYBOARD_INTERRUPT_FORMAT = "\n{color}Stopping Qwak build (ctrl-c)"
|
22
|
+
BUILD_FAILURE_FORMAT = "Build phase failed: {} after {} seconds"
|
23
|
+
PIPELINE_ERROR = "\n{color}{ex}"
|
24
|
+
SPINNER_FINISH = "✅"
|
25
|
+
SPINNER_FAIL = "💥"
|
26
|
+
SPINNER_OK = "‼️"
|
27
|
+
|
28
|
+
def __init__(self, python_logger: Logger, log_path: Path, verbose: int, json_logs: bool):
|
29
|
+
self.sp = None
|
30
|
+
self.build_logger = None
|
31
|
+
self.log_path = str(log_path)
|
32
|
+
self.python_logger = python_logger
|
33
|
+
self.json_logs = json_logs
|
34
|
+
self.verbose = verbose
|
35
|
+
|
36
|
+
@contextmanager
|
37
|
+
def handle_current_phase(self, phase: PhasesPipeline):
|
38
|
+
build_logger = CliTriggerBuildLogger(
|
39
|
+
self.python_logger,
|
40
|
+
prefix="" if self.json_logs else phase.build_phase.description,
|
41
|
+
build_phase=phase.build_phase,
|
42
|
+
)
|
43
|
+
show = (self.verbose == 0 and not self.json_logs)
|
44
|
+
text = phase.build_phase.description
|
45
|
+
if show:
|
46
|
+
with yaspin(text=text, color="blue", timer=True).bold as sp:
|
47
|
+
self.sp = sp
|
48
|
+
build_logger.set_spinner(sp)
|
49
|
+
self.build_logger = build_logger
|
50
|
+
yield
|
51
|
+
else:
|
52
|
+
self.build_logger = build_logger
|
53
|
+
yield
|
54
|
+
|
55
|
+
def handle_phase_in_progress(self, build_phase: BuildPhase):
|
56
|
+
logger = self.build_logger or self.python_logger
|
57
|
+
logger.debug(
|
58
|
+
self.BUILD_IN_PROGRESS_FORMAT.format(build_phase.name)
|
59
|
+
)
|
60
|
+
|
61
|
+
def handle_phase_finished_successfully(
|
62
|
+
self, build_phase: BuildPhase, duration_in_seconds: int
|
63
|
+
):
|
64
|
+
if self.sp:
|
65
|
+
self.sp.ok(self.SPINNER_FINISH)
|
66
|
+
|
67
|
+
logger = self.build_logger or self.python_logger
|
68
|
+
logger.debug(
|
69
|
+
self.BUILD_FINISHED_FORMAT.format(build_phase.name, duration_in_seconds))
|
70
|
+
|
71
|
+
def _report_failure(self, build_phase: BuildPhase, duration_in_seconds: int):
|
72
|
+
logger = self.build_logger or self.python_logger
|
73
|
+
logger.debug(
|
74
|
+
self.BUILD_FAILURE_FORMAT.format(build_phase.name, duration_in_seconds))
|
75
|
+
|
76
|
+
def handle_contact_support_error(
|
77
|
+
self, build_id: str, build_phase: BuildPhase, ex: BaseException, duration_in_seconds: int
|
78
|
+
):
|
79
|
+
print(f"\n{ex}\n{FAILED_CONTACT_JFROG_SUPPORT.format(build_id=build_id, log_file=Path(self.log_path).parent / build_id)}")
|
80
|
+
zip_logs(log_path=self.log_path, build_id=build_id)
|
81
|
+
self._report_failure(build_phase, duration_in_seconds)
|
82
|
+
exit(1)
|
83
|
+
|
84
|
+
def handle_remote_build_error(
|
85
|
+
self, build_id: str, build_phase: BuildPhase, ex: BaseException, duration_in_seconds: int
|
86
|
+
):
|
87
|
+
if self.sp:
|
88
|
+
self.sp.fail(self.SPINNER_FAIL)
|
89
|
+
print(self.PIPELINE_ERROR.format(color=Color.RED, ex=ex))
|
90
|
+
else:
|
91
|
+
print(f"\n{ex}")
|
92
|
+
self._report_failure(build_phase, duration_in_seconds)
|
93
|
+
exit(1)
|
94
|
+
|
95
|
+
def handle_keyboard_interrupt(
|
96
|
+
self, build_id: str, build_phase: BuildPhase, duration_in_seconds: int
|
97
|
+
):
|
98
|
+
print(self.KEYBOARD_INTERRUPT_FORMAT.format(color=Color.RED))
|
99
|
+
zip_logs(log_path=self.log_path, build_id=build_id)
|
100
|
+
self._report_failure(build_phase, duration_in_seconds)
|
101
|
+
exit(1)
|
102
|
+
|
103
|
+
def handle_pipeline_exception(
|
104
|
+
self, build_id: str, build_phase: BuildPhase, ex: BaseException, duration_in_seconds: int
|
105
|
+
):
|
106
|
+
if self.sp:
|
107
|
+
self.sp.fail("💥")
|
108
|
+
print(f"\n{Color.RED}{ex}")
|
109
|
+
zip_logs(
|
110
|
+
log_path=self.log_path,
|
111
|
+
build_id=build_id,
|
112
|
+
)
|
113
|
+
self._report_failure(build_phase, duration_in_seconds)
|
114
|
+
exit(1)
|
115
|
+
|
116
|
+
def handle_pipeline_quiet_exception(
|
117
|
+
self, build_id: str, build_phase: BuildPhase, ex: BaseException, duration_in_seconds: int
|
118
|
+
):
|
119
|
+
if self.sp:
|
120
|
+
self.sp.ok(self.SPINNER_OK)
|
121
|
+
print(self.PIPELINE_ERROR.format(color=Color.RED, ex=ex))
|
122
|
+
self._report_failure(build_phase, duration_in_seconds)
|
123
|
+
exit(1)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from logging import Logger
|
2
|
+
|
3
|
+
from frogml.core.inner.build_logic.build_loggers.trigger_build_logger import TriggerBuildLogger
|
4
|
+
from frogml.core.inner.build_logic.interface.build_phase import BuildPhase
|
5
|
+
from yaspin.core import Yaspin
|
6
|
+
|
7
|
+
|
8
|
+
class CliTriggerBuildLogger(TriggerBuildLogger):
|
9
|
+
def __init__(self, logger: Logger, prefix: str, build_phase: BuildPhase, verbose: int = 0,
|
10
|
+
json_logs: bool = False) -> None:
|
11
|
+
super().__init__(logger, prefix, build_phase, verbose, json_logs)
|
12
|
+
self.spinner = None
|
13
|
+
|
14
|
+
def set_spinner(self, spinner: Yaspin):
|
15
|
+
self.spinner = spinner
|
16
|
+
|
17
|
+
def spinner_text(self, line: str) -> None:
|
18
|
+
if self.spinner:
|
19
|
+
self.spinner.text = f"{self.prefix}{line}"
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import contextlib
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
import platform
|
5
|
+
import shutil
|
6
|
+
import sys
|
7
|
+
import uuid
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
from frogml.core.inner.build_config.build_config_v1 import BuildConfigV1
|
11
|
+
from frogml.core.inner.build_logic.constants.host_resource import HOST_FROGML_HIDDEN_FOLDER
|
12
|
+
|
13
|
+
from frogml_cli import __version__ as qwak_sdk_version
|
14
|
+
from frogml_cli.inner.tools.logger import setup_frogml_logger
|
15
|
+
from frogml_cli.inner.tools.logger.logger import (
|
16
|
+
BUILD_LOCAL_FILE_HANDLER_NAME,
|
17
|
+
BUILD_LOCAL_LOGGER_NAME,
|
18
|
+
CONSOLE_HANDLER_NAME,
|
19
|
+
REMOTE_CONSOLE_HANDLER_NAME,
|
20
|
+
REMOTE_LOGGER_NAME,
|
21
|
+
VERBOSITY_LEVEL_MAPPING,
|
22
|
+
get_frogml_logger,
|
23
|
+
non_frogml_logger_enabled,
|
24
|
+
set_file_handler_log_file,
|
25
|
+
set_handler_verbosity,
|
26
|
+
)
|
27
|
+
|
28
|
+
BUILDS_LOGS = HOST_FROGML_HIDDEN_FOLDER / "logs" / "build"
|
29
|
+
BUILD_LOG_NAME = "build.log"
|
30
|
+
MAX_LOGS_NUMBER = 15
|
31
|
+
DEBUG_LEVEL = 2
|
32
|
+
|
33
|
+
|
34
|
+
@contextlib.contextmanager
|
35
|
+
def get_build_logger(config: BuildConfigV1, json_logs: bool):
|
36
|
+
log_path = BUILDS_LOGS / config.build_properties.model_id / str(uuid.uuid4())[:4]
|
37
|
+
log_path.mkdir(parents=True, exist_ok=True)
|
38
|
+
try:
|
39
|
+
(log_path / "build_config.yml").write_text(config.to_yaml())
|
40
|
+
log_system_information(log_path)
|
41
|
+
|
42
|
+
log_file = log_path / BUILD_LOG_NAME
|
43
|
+
setup_frogml_logger()
|
44
|
+
yield setup_logger(
|
45
|
+
log_file=log_file, verbosity_level=config.verbose, json_logs=json_logs
|
46
|
+
), log_path
|
47
|
+
finally:
|
48
|
+
# Cleanup - Save only x last zips
|
49
|
+
logs_zip_sorted_by_data = sorted(
|
50
|
+
BUILDS_LOGS.rglob("**/*"), key=os.path.getmtime
|
51
|
+
)[:-MAX_LOGS_NUMBER]
|
52
|
+
path: Path
|
53
|
+
for path in logs_zip_sorted_by_data:
|
54
|
+
if path.is_file():
|
55
|
+
os.remove(path)
|
56
|
+
elif path.is_dir():
|
57
|
+
shutil.rmtree(path, ignore_errors=True)
|
58
|
+
|
59
|
+
|
60
|
+
def setup_logger(
|
61
|
+
log_file: Path, verbosity_level: int, json_logs: bool
|
62
|
+
) -> logging.Logger:
|
63
|
+
# Init logger
|
64
|
+
fallback_logger_name = (
|
65
|
+
BUILD_LOCAL_LOGGER_NAME if not json_logs else REMOTE_LOGGER_NAME
|
66
|
+
)
|
67
|
+
logger = get_frogml_logger(fallback_logger_name=fallback_logger_name)
|
68
|
+
|
69
|
+
if not non_frogml_logger_enabled():
|
70
|
+
if logger.name == BUILD_LOCAL_LOGGER_NAME:
|
71
|
+
set_file_handler_log_file(logger, BUILD_LOCAL_FILE_HANDLER_NAME, log_file)
|
72
|
+
set_handler_verbosity(
|
73
|
+
logger, CONSOLE_HANDLER_NAME, VERBOSITY_LEVEL_MAPPING[verbosity_level]
|
74
|
+
)
|
75
|
+
elif logger.name == REMOTE_LOGGER_NAME and json_logs:
|
76
|
+
set_handler_verbosity(
|
77
|
+
logger,
|
78
|
+
REMOTE_CONSOLE_HANDLER_NAME,
|
79
|
+
VERBOSITY_LEVEL_MAPPING[DEBUG_LEVEL],
|
80
|
+
)
|
81
|
+
|
82
|
+
return logger
|
83
|
+
|
84
|
+
|
85
|
+
def log_system_information(destination: Path):
|
86
|
+
(destination / "python_version").write_text(sys.version)
|
87
|
+
(destination / "qwak_sdk_version").write_text(qwak_sdk_version)
|
88
|
+
(destination / "os_detail").write_text(platform.platform())
|
@@ -0,0 +1,36 @@
|
|
1
|
+
BUILD_LOGS_URL = (
|
2
|
+
"{base_url}/models/{model_id}/build/{build_id}"
|
3
|
+
)
|
4
|
+
|
5
|
+
SUCCESS_MSG_REMOTE = """
|
6
|
+
Build ID \033[4m{build_id}\033[0m triggered remotely
|
7
|
+
|
8
|
+
########### Follow build logs in the CLI
|
9
|
+
frogml models builds logs -b {build_id} --follow
|
10
|
+
|
11
|
+
########### Follow build logs in the platform
|
12
|
+
{base_url}/models/{model_id}/build/{build_id}
|
13
|
+
"""
|
14
|
+
|
15
|
+
SUCCESS_MSG_REMOTE_WITH_DEPLOY = """
|
16
|
+
Build ID \033[4m{build_id}\033[0m finished successfully and deployed
|
17
|
+
|
18
|
+
########### View the model using platform
|
19
|
+
{base_url}/models/{model_id}
|
20
|
+
"""
|
21
|
+
|
22
|
+
FAILED_CONTACT_JFROG_SUPPORT = """
|
23
|
+
Build ID \033[4m{build_id}\033[0m failed!!
|
24
|
+
You can share the logs from \033[4m{log_file}.zip\033[0m with the support team.
|
25
|
+
"""
|
26
|
+
|
27
|
+
FAILED_REMOTE_BUILD_SUGGESTION = """
|
28
|
+
Your build failed. Check the failure reason in the platform:
|
29
|
+
{base_url}/models/{model_id}/build/{build_id}
|
30
|
+
"""
|
31
|
+
|
32
|
+
FAILED_DEPLOY_BUILD_SUGGESTION = """
|
33
|
+
Deploying the build failed. Check the failure reason in the platform:
|
34
|
+
{base_url}/models/{model_id}?tabId=1
|
35
|
+
Try and redeploy this build either from the platform or the CLI
|
36
|
+
"""
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from contextlib import contextmanager
|
2
|
+
from typing import Generator, Optional
|
3
|
+
|
4
|
+
from yaspin import yaspin
|
5
|
+
from yaspin.core import Yaspin
|
6
|
+
|
7
|
+
|
8
|
+
@contextmanager
|
9
|
+
def spinner(text: Optional[str], show: bool) -> Generator[Yaspin, None, None]:
|
10
|
+
if show:
|
11
|
+
with yaspin(text=text, color="blue", timer=True).bold as sp:
|
12
|
+
yield sp
|
13
|
+
else:
|
14
|
+
yield
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import logging
|
2
|
+
from logging import Logger
|
3
|
+
|
4
|
+
from frogml.core.inner.build_logic.interface.build_logger_interface import BuildLogger
|
5
|
+
from frogml.core.inner.build_logic.interface.build_phase import BuildPhase
|
6
|
+
from yaspin.core import Yaspin
|
7
|
+
|
8
|
+
|
9
|
+
PREFIX_FORMAT = "{prefix} - "
|
10
|
+
EXCEPTION_FORMAT = """Message: {line}
|
11
|
+
Exception: {e}
|
12
|
+
"""
|
13
|
+
|
14
|
+
|
15
|
+
class TriggerBuildLogger(BuildLogger):
|
16
|
+
def __init__(
|
17
|
+
self, logger: Logger, prefix: str, build_phase: BuildPhase, verbose: int = 0, json_logs: bool = False,
|
18
|
+
) -> None:
|
19
|
+
self.logger = logging.LoggerAdapter(
|
20
|
+
logger,
|
21
|
+
{
|
22
|
+
"phase": build_phase.description,
|
23
|
+
"phase_id": build_phase.phase_id,
|
24
|
+
},
|
25
|
+
)
|
26
|
+
self.prefix = PREFIX_FORMAT.format(prefix=prefix) if prefix else ""
|
27
|
+
self.spinner = None
|
28
|
+
self.verbose = verbose
|
29
|
+
self.json_logs = json_logs
|
30
|
+
|
31
|
+
def set_spinner(self, spinner: Yaspin):
|
32
|
+
self.spinner = spinner
|
33
|
+
|
34
|
+
def exception(self, line: str, e: BaseException) -> None:
|
35
|
+
self.logger.error(
|
36
|
+
EXCEPTION_FORMAT.format(line=line, e=e),
|
37
|
+
exc_info=False,
|
38
|
+
)
|
39
|
+
|
40
|
+
def error(self, line: str) -> None:
|
41
|
+
self.logger.error(f"{self.prefix}{line}")
|
42
|
+
|
43
|
+
def warning(self, line: str) -> None:
|
44
|
+
self.logger.warning(f"{self.prefix}{line}")
|
45
|
+
|
46
|
+
def info(self, line: str) -> None:
|
47
|
+
self.logger.info(f"{self.prefix}{line}")
|
48
|
+
|
49
|
+
def debug(self, line: str) -> None:
|
50
|
+
self.logger.debug(f"{self.prefix}{line}")
|
51
|
+
|
52
|
+
def spinner_text(self, line: str) -> None:
|
53
|
+
if self.spinner:
|
54
|
+
self.spinner.text = f"{self.prefix}{line}"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import shutil
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
|
5
|
+
def zip_logs(log_path: str, build_id: str):
|
6
|
+
if build_id:
|
7
|
+
shutil.make_archive(
|
8
|
+
base_name=str(Path(log_path).parent / build_id),
|
9
|
+
format="zip",
|
10
|
+
root_dir=log_path,
|
11
|
+
)
|
12
|
+
shutil.rmtree(log_path, ignore_errors=True)
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from frogml.core.inner.build_logic.interface.step_inteface import Step
|
4
|
+
from frogml.core.inner.build_logic.phases.phase_010_fetch_model.fetch_model_step import FetchModelStep
|
5
|
+
from frogml.core.inner.build_logic.phases.phase_010_fetch_model.post_fetch_validation_step import PostFetchValidationStep
|
6
|
+
from frogml.core.inner.build_logic.phases.phase_010_fetch_model.pre_fetch_validation_step import PreFetchValidationStep
|
7
|
+
|
8
|
+
from frogml_cli.commands.models.build._logic.phase.a_fetch_model_code.get_sdk_version_step import SdkVersionStep
|
9
|
+
from frogml_cli.commands.models.build._logic.util.step_decorator import add_decorator_to_steps
|
10
|
+
|
11
|
+
|
12
|
+
def get_fetch_model_code_steps() -> List[Step]:
|
13
|
+
phase_steps = [
|
14
|
+
SdkVersionStep(),
|
15
|
+
PreFetchValidationStep(),
|
16
|
+
FetchModelStep(),
|
17
|
+
PostFetchValidationStep(),
|
18
|
+
]
|
19
|
+
|
20
|
+
return add_decorator_to_steps(phase_steps)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from frogml.core.inner.build_logic.interface.step_inteface import Step
|
2
|
+
|
3
|
+
from frogml_cli import __version__ as frogml_cli_version
|
4
|
+
from frogml_cli import __name__ as frogml_cli_name
|
5
|
+
|
6
|
+
|
7
|
+
class SdkVersionStep(Step):
|
8
|
+
def description(self) -> str:
|
9
|
+
return "Getting SDK Version"
|
10
|
+
|
11
|
+
def execute(self) -> None:
|
12
|
+
self.build_logger.debug(
|
13
|
+
"Getting sdk version"
|
14
|
+
)
|
15
|
+
self.context.frogml_cli_version = f"{frogml_cli_name}/{frogml_cli_version}"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from frogml.core.inner.build_logic.phases.phase_020_remote_register_frogml_build.cleanup_step import CleanupStep
|
2
|
+
from frogml.core.inner.build_logic.phases.phase_020_remote_register_frogml_build.start_remote_build_step import \
|
3
|
+
StartRemoteBuildStep
|
4
|
+
from frogml.core.inner.build_logic.phases.phase_020_remote_register_frogml_build.upload_step import UploadStep
|
5
|
+
|
6
|
+
from ...util.step_decorator import add_decorator_to_steps
|
7
|
+
|
8
|
+
|
9
|
+
def get_remote_register_frogml_build_steps():
|
10
|
+
phase_steps = [
|
11
|
+
UploadStep(),
|
12
|
+
StartRemoteBuildStep(),
|
13
|
+
CleanupStep(),
|
14
|
+
]
|
15
|
+
|
16
|
+
return add_decorator_to_steps(phase_steps)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import time
|
4
|
+
|
5
|
+
from frogml._proto.qwak.build.v1.build_api_pb2 import GetBuildResponse
|
6
|
+
from frogml._proto.qwak.build.v1.build_pb2 import BuildStatus
|
7
|
+
|
8
|
+
from frogml_cli.commands.models.build._logic.client_logs.messages import (
|
9
|
+
FAILED_REMOTE_BUILD_SUGGESTION,
|
10
|
+
)
|
11
|
+
from frogml.core.inner.build_logic.interface.step_inteface import Step
|
12
|
+
from frogml.core.exceptions import FrogmlRemoteBuildFailedException
|
13
|
+
|
14
|
+
|
15
|
+
class BuildPollingStatusStep(Step):
|
16
|
+
FINITE_BUILD_STATUSES = {
|
17
|
+
BuildStatus.REMOTE_BUILD_CANCELLED,
|
18
|
+
BuildStatus.REMOTE_BUILD_TIMED_OUT,
|
19
|
+
BuildStatus.FAILED,
|
20
|
+
BuildStatus.SUCCESSFUL,
|
21
|
+
}
|
22
|
+
SLEEP_BETWEEN_STATUS_CHECK = 10
|
23
|
+
REMOTE_BUILD_FAILURE_EXCEPTION_FORMAT = "Your build failed with status {status}"
|
24
|
+
|
25
|
+
def description(self) -> str:
|
26
|
+
return "Polling on Build Status"
|
27
|
+
|
28
|
+
def execute(self) -> None:
|
29
|
+
self.build_logger.info("Waiting for build to finish")
|
30
|
+
status = self.wait_for_finite_build_status()
|
31
|
+
if status != BuildStatus.SUCCESSFUL:
|
32
|
+
raise FrogmlRemoteBuildFailedException(
|
33
|
+
message=self.REMOTE_BUILD_FAILURE_EXCEPTION_FORMAT.format(
|
34
|
+
status=BuildStatus.Name(status)
|
35
|
+
),
|
36
|
+
suggestion=FAILED_REMOTE_BUILD_SUGGESTION.format(
|
37
|
+
base_url=self.context.platform_url,
|
38
|
+
build_id=self.context.build_id,
|
39
|
+
model_id=self.context.model_id,
|
40
|
+
project_uuid=self.context.project_uuid,
|
41
|
+
),
|
42
|
+
)
|
43
|
+
self.build_logger.info("Your build finished successfully")
|
44
|
+
|
45
|
+
def wait_for_finite_build_status(self) -> BuildStatus:
|
46
|
+
self.build_logger.spinner_text(line="Waiting for build to finish")
|
47
|
+
while True:
|
48
|
+
result: GetBuildResponse = (
|
49
|
+
self.context.client_builds_orchestrator.get_build(self.context.build_id)
|
50
|
+
)
|
51
|
+
status: BuildStatus = result.build.build_status
|
52
|
+
if status in self.FINITE_BUILD_STATUSES:
|
53
|
+
return status
|
54
|
+
self.build_logger.debug(f"Build status is currently {BuildStatus.Name(status)}")
|
55
|
+
time.sleep(self.SLEEP_BETWEEN_STATUS_CHECK)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import List
|
4
|
+
|
5
|
+
from frogml._proto.qwak.instance_template.instance_template_pb2 import (
|
6
|
+
InstanceTemplateSpec,
|
7
|
+
InstanceType,
|
8
|
+
)
|
9
|
+
|
10
|
+
from frogml_cli.commands.models.build._logic.client_logs.messages import (
|
11
|
+
FAILED_DEPLOY_BUILD_SUGGESTION,
|
12
|
+
)
|
13
|
+
from frogml.core.inner.build_logic.interface.step_inteface import Step
|
14
|
+
from frogml_cli.commands.models.deployments.deploy.realtime.ui import deploy_realtime
|
15
|
+
from frogml_cli.exceptions.frogml_deploy_new_build_failed import (
|
16
|
+
FrogmlDeployNewBuildFailedException,
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
class DeployBuildStep(Step):
|
21
|
+
DEPLOY_FAILURE_EXCEPTION_MESSAGE = "Deploying the build failed due to {e}"
|
22
|
+
|
23
|
+
def description(self) -> str:
|
24
|
+
return "Deploying Build"
|
25
|
+
|
26
|
+
def execute(self) -> None:
|
27
|
+
self.build_logger.info(f"Deploying build {self.context.build_id}")
|
28
|
+
try:
|
29
|
+
if self.config.deployment_instance:
|
30
|
+
template_id = self.config.deployment_instance
|
31
|
+
else:
|
32
|
+
template_id = self.get_smallest_deployment_template_id()
|
33
|
+
deploy_config = {
|
34
|
+
"build_id": self.context.build_id,
|
35
|
+
"model_id": self.context.model_id,
|
36
|
+
"instance": template_id,
|
37
|
+
}
|
38
|
+
deploy_realtime(from_file=None, out_conf=False, sync=False, **deploy_config)
|
39
|
+
self.build_logger.info(f"Finished deploying build {self.context.build_id}")
|
40
|
+
except Exception as e:
|
41
|
+
raise FrogmlDeployNewBuildFailedException(
|
42
|
+
message=self.DEPLOY_FAILURE_EXCEPTION_MESSAGE.format(e=e),
|
43
|
+
suggestion=FAILED_DEPLOY_BUILD_SUGGESTION.format(
|
44
|
+
base_url=self.context.platform_url,
|
45
|
+
build_id=self.context.build_id,
|
46
|
+
model_id=self.context.model_id,
|
47
|
+
project_uuid=self.context.project_uuid,
|
48
|
+
),
|
49
|
+
)
|
50
|
+
|
51
|
+
def get_smallest_deployment_template_id(self):
|
52
|
+
instances: List[
|
53
|
+
InstanceTemplateSpec
|
54
|
+
] = self.context.client_instance_template.list_instance_templates()
|
55
|
+
return list(
|
56
|
+
filter(
|
57
|
+
lambda template: template.order == 1
|
58
|
+
and template.instance_type == InstanceType.INSTANCE_TYPE_CPU,
|
59
|
+
instances,
|
60
|
+
)
|
61
|
+
)[0].id
|
File without changes
|
@@ -0,0 +1,45 @@
|
|
1
|
+
from frogml.core.exceptions import FrogmlException
|
2
|
+
|
3
|
+
|
4
|
+
def protobuf_factory(
|
5
|
+
protobuf_class, exclude_fields=None, include_only=None, mapping=None
|
6
|
+
):
|
7
|
+
def get_final_field_names(cls):
|
8
|
+
fields = dict(cls.__dataclass_fields__)
|
9
|
+
all_field_names = set(fields.keys())
|
10
|
+
excluded_fields = set(exclude_fields) if exclude_fields else set()
|
11
|
+
included_fields = set(include_only) if include_only else all_field_names
|
12
|
+
unrecognized_fields = included_fields.difference(all_field_names)
|
13
|
+
if unrecognized_fields:
|
14
|
+
raise FrogmlException(
|
15
|
+
f"Unknown fields were included: {list(unrecognized_fields)}"
|
16
|
+
)
|
17
|
+
return included_fields.difference(excluded_fields)
|
18
|
+
|
19
|
+
def protofy_decorator(cls):
|
20
|
+
if not hasattr(cls, "__dataclass_fields__"):
|
21
|
+
raise FrogmlException("Protofy must receive a dataclass")
|
22
|
+
|
23
|
+
fields_mapping = mapping if mapping else {}
|
24
|
+
final_field_names = get_final_field_names(cls)
|
25
|
+
|
26
|
+
def to_proto(self) -> protobuf_class:
|
27
|
+
final_fields = {}
|
28
|
+
for field_name in final_field_names:
|
29
|
+
field_val = self.__getattribute__(field_name)
|
30
|
+
field_name = (
|
31
|
+
fields_mapping[field_name]
|
32
|
+
if field_name in fields_mapping
|
33
|
+
else field_name
|
34
|
+
)
|
35
|
+
final_fields[field_name] = (
|
36
|
+
field_val.to_proto()
|
37
|
+
if hasattr(field_val, "to_proto")
|
38
|
+
else field_val
|
39
|
+
)
|
40
|
+
return protobuf_class(**final_fields)
|
41
|
+
|
42
|
+
setattr(cls, "to_proto", to_proto)
|
43
|
+
return cls
|
44
|
+
|
45
|
+
return protofy_decorator
|