qwak-sdk 0.1.0__py3-none-any.whl → 0.2.21rc0__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.
Potentially problematic release.
This version of qwak-sdk might be problematic. Click here for more details.
- qwak_sdk/__init__.py +9 -0
- qwak_sdk/cli.py +51 -0
- qwak_sdk/commands/admin/__init__.py +0 -0
- qwak_sdk/commands/admin/admin_commands_group.py +17 -0
- qwak_sdk/commands/admin/apikeys/__init__.py +0 -0
- qwak_sdk/commands/admin/apikeys/api_keys_commands_group.py +17 -0
- qwak_sdk/commands/admin/apikeys/generate/__init__.py +0 -0
- qwak_sdk/commands/admin/apikeys/generate/_logic.py +21 -0
- qwak_sdk/commands/admin/apikeys/generate/ui.py +45 -0
- qwak_sdk/commands/admin/apikeys/revoke/__init__.py +0 -0
- qwak_sdk/commands/admin/apikeys/revoke/_logic.py +22 -0
- qwak_sdk/commands/admin/apikeys/revoke/ui.py +31 -0
- qwak_sdk/commands/audience/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/config/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/config/config_base.py +16 -0
- qwak_sdk/commands/audience/_logic/config/parser.py +28 -0
- qwak_sdk/commands/audience/_logic/config/v1/__init__.py +0 -0
- qwak_sdk/commands/audience/_logic/config/v1/audience_config.py +26 -0
- qwak_sdk/commands/audience/_logic/config/v1/conditions_config.py +60 -0
- qwak_sdk/commands/audience/_logic/config/v1/config_v1.py +24 -0
- qwak_sdk/commands/audience/_logic/config/v1/route_config.py +14 -0
- qwak_sdk/commands/audience/_logic/config/v1/spec.py +11 -0
- qwak_sdk/commands/auto_scalling/__init__.py +0 -0
- qwak_sdk/commands/auto_scalling/_logic/__init__.py +0 -0
- qwak_sdk/commands/auto_scalling/_logic/config/__init__.py +3 -0
- qwak_sdk/commands/auto_scalling/_logic/config/config.py +100 -0
- qwak_sdk/commands/auto_scalling/_logic/config/parser.py +21 -0
- qwak_sdk/commands/auto_scalling/attach/__init__.py +0 -0
- qwak_sdk/commands/auto_scalling/attach/_logic.py +43 -0
- qwak_sdk/commands/auto_scalling/attach/ui.py +21 -0
- qwak_sdk/commands/auto_scalling/autoscaling_commands_group.py +15 -0
- qwak_sdk/commands/automations/__init__.py +0 -0
- qwak_sdk/commands/automations/automations_commands_group.py +30 -0
- qwak_sdk/commands/automations/delete/__init__.py +0 -0
- qwak_sdk/commands/automations/delete/_logic.py +6 -0
- qwak_sdk/commands/automations/delete/ui.py +23 -0
- qwak_sdk/commands/automations/executions/__init__.py +0 -0
- qwak_sdk/commands/automations/executions/executions_commands_group.py +14 -0
- qwak_sdk/commands/automations/executions/list/__init__.py +0 -0
- qwak_sdk/commands/automations/executions/list/_logic.py +8 -0
- qwak_sdk/commands/automations/executions/list/ui.py +25 -0
- qwak_sdk/commands/automations/list/__init__.py +0 -0
- qwak_sdk/commands/automations/list/_logic.py +8 -0
- qwak_sdk/commands/automations/list/ui.py +21 -0
- qwak_sdk/commands/automations/register/__init__.py +0 -0
- qwak_sdk/commands/automations/register/_logic.py +43 -0
- qwak_sdk/commands/automations/register/ui.py +44 -0
- qwak_sdk/commands/feature_store/__init__.py +0 -0
- qwak_sdk/commands/feature_store/delete/__init__.py +0 -0
- qwak_sdk/commands/feature_store/delete/_logic.py +52 -0
- qwak_sdk/commands/feature_store/delete/ui.py +40 -0
- qwak_sdk/commands/feature_store/feature_store_command_group.py +25 -0
- qwak_sdk/commands/feature_store/list/__init__.py +0 -0
- qwak_sdk/commands/feature_store/list/ui.py +140 -0
- qwak_sdk/commands/feature_store/pause/__init__.py +0 -0
- qwak_sdk/commands/feature_store/pause/ui.py +18 -0
- qwak_sdk/commands/feature_store/register/__init__.py +0 -0
- qwak_sdk/commands/feature_store/register/_logic.py +289 -0
- qwak_sdk/commands/feature_store/register/ui.py +105 -0
- qwak_sdk/commands/feature_store/resume/__init__.py +0 -0
- qwak_sdk/commands/feature_store/resume/ui.py +18 -0
- qwak_sdk/commands/feature_store/trigger/__init__.py +0 -0
- qwak_sdk/commands/feature_store/trigger/ui.py +32 -0
- qwak_sdk/commands/models/__init__.py +0 -0
- qwak_sdk/commands/models/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/_logic/variations.py +55 -0
- qwak_sdk/commands/models/build/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/build_steps.py +68 -0
- qwak_sdk/commands/models/build/_logic/client_logs/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/client_logs/build_run_handlers.py +189 -0
- qwak_sdk/commands/models/build/_logic/client_logs/cli_ui.py +125 -0
- qwak_sdk/commands/models/build/_logic/client_logs/logger.py +88 -0
- qwak_sdk/commands/models/build/_logic/client_logs/messages.py +40 -0
- qwak_sdk/commands/models/build/_logic/client_logs/notifier_impl.py +49 -0
- qwak_sdk/commands/models/build/_logic/client_logs/spinner.py +14 -0
- qwak_sdk/commands/models/build/_logic/client_logs/time_source.py +37 -0
- qwak_sdk/commands/models/build/_logic/client_logs/utils.py +12 -0
- qwak_sdk/commands/models/build/_logic/config/config_v1.py +253 -0
- qwak_sdk/commands/models/build/_logic/constant/host_resource.py +4 -0
- qwak_sdk/commands/models/build/_logic/constant/step_description.py +29 -0
- qwak_sdk/commands/models/build/_logic/constant/temp_dir.py +2 -0
- qwak_sdk/commands/models/build/_logic/constant/upload_tag.py +5 -0
- qwak_sdk/commands/models/build/_logic/context.py +62 -0
- qwak_sdk/commands/models/build/_logic/interface/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/interface/notifier_interface.py +29 -0
- qwak_sdk/commands/models/build/_logic/interface/step_inteface.py +29 -0
- qwak_sdk/commands/models/build/_logic/phase/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/__init__.py +14 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_model_step.py +42 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/common.py +33 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/fetch_strategy_manager.py +60 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/folder/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/folder/folder_strategy.py +73 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/git/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/git/git_strategy.py +149 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/strategy.py +69 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/zip/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/fetch_model_step/fetch_strategy_manager/strategy/zip/zip_strategy.py +64 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/post_fetch_validation_step.py +117 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/pre_fetch_validation_step.py +135 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/__init__.py +11 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/cleanup_step.py +20 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/start_remote_build_step.py +42 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/upload_step.py +349 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/__init__.py +6 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/build_polling_status.py +54 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/deploy_build.py +44 -0
- qwak_sdk/commands/models/build/_logic/util/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/util/protobuf_factory.py +45 -0
- qwak_sdk/commands/models/build/_logic/util/step_decorator.py +37 -0
- qwak_sdk/commands/models/build/_logic/util/text.py +9 -0
- qwak_sdk/commands/models/build/ui.py +241 -0
- qwak_sdk/commands/models/builds/__init__.py +0 -0
- qwak_sdk/commands/models/builds/builds_commands_group.py +16 -0
- qwak_sdk/commands/models/builds/cancel/__init__.py +0 -0
- qwak_sdk/commands/models/builds/cancel/_logic.py +5 -0
- qwak_sdk/commands/models/builds/cancel/ui.py +15 -0
- qwak_sdk/commands/models/builds/logs/__init__.py +0 -0
- qwak_sdk/commands/models/builds/logs/ui.py +35 -0
- qwak_sdk/commands/models/builds/status/__init__.py +0 -0
- qwak_sdk/commands/models/builds/status/_logic.py +6 -0
- qwak_sdk/commands/models/builds/status/ui.py +30 -0
- qwak_sdk/commands/models/create/__init__.py +0 -0
- qwak_sdk/commands/models/create/_logic.py +35 -0
- qwak_sdk/commands/models/create/ui.py +27 -0
- qwak_sdk/commands/models/delete/__init__.py +0 -0
- qwak_sdk/commands/models/delete/_logic.py +5 -0
- qwak_sdk/commands/models/delete/ui.py +16 -0
- qwak_sdk/commands/models/deployments/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/advance_deployment_options_handler.py +31 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/base_deploy_executor.py +64 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py +241 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment.py +405 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +98 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_response_handler.py +154 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +21 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/get_latest_successful_build.py +31 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/variations.py +79 -0
- qwak_sdk/commands/models/deployments/deploy/batch/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/advanced_deployment_mapper.py +14 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/batch/ui.py +104 -0
- qwak_sdk/commands/models/deployments/deploy/deploy_commands_group.py +19 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/advanced_deployment_mapper.py +20 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py +105 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/ui.py +179 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/_logic/serving_strategy_mapper.py +38 -0
- qwak_sdk/commands/models/deployments/deploy/streaming/ui.py +196 -0
- qwak_sdk/commands/models/deployments/undeploy/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/undeploy/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/deployments/undeploy/_logic/request_undeploy.py +176 -0
- qwak_sdk/commands/models/deployments/undeploy/_logic/variations.py +74 -0
- qwak_sdk/commands/models/deployments/undeploy/ui.py +78 -0
- qwak_sdk/commands/models/executions/__init__.py +0 -0
- qwak_sdk/commands/models/executions/cancel/__init__.py +0 -0
- qwak_sdk/commands/models/executions/cancel/_logic.py +9 -0
- qwak_sdk/commands/models/executions/cancel/ui.py +27 -0
- qwak_sdk/commands/models/executions/execution_commands_group.py +24 -0
- qwak_sdk/commands/models/executions/report/__init__.py +0 -0
- qwak_sdk/commands/models/executions/report/_logic.py +14 -0
- qwak_sdk/commands/models/executions/report/ui.py +43 -0
- qwak_sdk/commands/models/executions/start/__init__.py +0 -0
- qwak_sdk/commands/models/executions/start/_logic.py +16 -0
- qwak_sdk/commands/models/executions/start/ui.py +176 -0
- qwak_sdk/commands/models/executions/status/__init__.py +0 -0
- qwak_sdk/commands/models/executions/status/_logic.py +13 -0
- qwak_sdk/commands/models/executions/status/ui.py +27 -0
- qwak_sdk/commands/models/init/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/initialize_model_structure.py +40 -0
- qwak_sdk/commands/models/init/_logic/template/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/model.py +95 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/test_churn.py +32 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
- qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/model.py +108 -0
- qwak_sdk/commands/models/init/_logic/template/general/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/general/cookiecutter.json +6 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/conda.yml +8 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/model.py +66 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/test_qwak_model.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/model.py +98 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +24 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/cookiecutter.json +3 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/model.py +98 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/pyproject.toml +18 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
- qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +25 -0
- qwak_sdk/commands/models/init/ui.py +61 -0
- qwak_sdk/commands/models/list/__init__.py +0 -0
- qwak_sdk/commands/models/list/_logic.py +5 -0
- qwak_sdk/commands/models/list/ui.py +31 -0
- qwak_sdk/commands/models/models_command_group.py +36 -0
- qwak_sdk/commands/models/runtime/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/feedback/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/feedback/_logic.py +81 -0
- qwak_sdk/commands/models/runtime/feedback/ui.py +45 -0
- qwak_sdk/commands/models/runtime/logs/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/logs/ui.py +63 -0
- qwak_sdk/commands/models/runtime/runtime_commands_group.py +21 -0
- qwak_sdk/commands/models/runtime/traffic_update/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/execute_runtime_update_traffic.py +54 -0
- qwak_sdk/commands/models/runtime/traffic_update/_logic/variations.py +84 -0
- qwak_sdk/commands/models/runtime/traffic_update/ui.py +37 -0
- qwak_sdk/commands/models/runtime/update/__init__.py +0 -0
- qwak_sdk/commands/models/runtime/update/_logic.py +9 -0
- qwak_sdk/commands/models/runtime/update/ui.py +15 -0
- qwak_sdk/commands/projects/__init__.py +0 -0
- qwak_sdk/commands/projects/create/__init__.py +0 -0
- qwak_sdk/commands/projects/create/_logic.py +6 -0
- qwak_sdk/commands/projects/create/ui.py +21 -0
- qwak_sdk/commands/projects/delete/__init__.py +0 -0
- qwak_sdk/commands/projects/delete/_logic.py +6 -0
- qwak_sdk/commands/projects/delete/ui.py +15 -0
- qwak_sdk/commands/projects/list/__init__.py +0 -0
- qwak_sdk/commands/projects/list/_logic.py +6 -0
- qwak_sdk/commands/projects/list/ui.py +36 -0
- qwak_sdk/commands/projects/projects_command_group.py +19 -0
- qwak_sdk/commands/secrets/__init__.py +0 -0
- qwak_sdk/commands/secrets/delete/__init__.py +0 -0
- qwak_sdk/commands/secrets/delete/_logic.py +5 -0
- qwak_sdk/commands/secrets/delete/ui.py +21 -0
- qwak_sdk/commands/secrets/get/__init__.py +0 -0
- qwak_sdk/commands/secrets/get/_logic.py +5 -0
- qwak_sdk/commands/secrets/get/ui.py +17 -0
- qwak_sdk/commands/secrets/secrets_commands_group.py +19 -0
- qwak_sdk/commands/secrets/set/__init__.py +0 -0
- qwak_sdk/commands/secrets/set/_logic.py +5 -0
- qwak_sdk/commands/secrets/set/ui.py +16 -0
- qwak_sdk/commands/ui_tools.py +18 -0
- qwak_sdk/common/__init__.py +0 -0
- qwak_sdk/common/run_config/__init__.py +22 -0
- qwak_sdk/common/run_config/base.py +101 -0
- qwak_sdk/common/run_config/utils.py +249 -0
- qwak_sdk/exceptions/__init__.py +11 -0
- qwak_sdk/exceptions/qwak_command_exception.py +2 -0
- qwak_sdk/exceptions/qwak_deploy_new_build_failed.py +5 -0
- qwak_sdk/exceptions/qwak_general_build_exception.py +13 -0
- qwak_sdk/exceptions/qwak_remote_build_failed.py +5 -0
- qwak_sdk/exceptions/qwak_resource_not_found.py +2 -0
- qwak_sdk/exceptions/qwak_suggestion_exception.py +27 -0
- qwak_sdk/inner/__init__.py +0 -0
- qwak_sdk/inner/file_registry.py +97 -0
- qwak_sdk/inner/tools/__init__.py +0 -0
- qwak_sdk/inner/tools/cli_tools.py +159 -0
- qwak_sdk/inner/tools/config_handler.py +18 -0
- qwak_sdk/inner/tools/logger/__init__.py +3 -0
- qwak_sdk/inner/tools/logger/logger.py +269 -0
- qwak_sdk/inner/tools/logger/logging.yml +79 -0
- qwak_sdk/inner/tools/tracking.py +47 -0
- qwak_sdk/main.py +9 -0
- qwak_sdk/tools/__init__.py +0 -0
- qwak_sdk/tools/colors.py +13 -0
- qwak_sdk/tools/files.py +9 -0
- qwak_sdk/tools/log_handling.py +146 -0
- qwak_sdk/tools/utils.py +46 -0
- qwak_sdk-0.2.21rc0.dist-info/METADATA +42 -0
- qwak_sdk-0.2.21rc0.dist-info/RECORD +302 -0
- {qwak_sdk-0.1.0.dist-info → qwak_sdk-0.2.21rc0.dist-info}/WHEEL +1 -2
- qwak_sdk-0.2.21rc0.dist-info/entry_points.txt +3 -0
- qwak_sdk-0.1.0.dist-info/METADATA +0 -19
- qwak_sdk-0.1.0.dist-info/RECORD +0 -5
- qwak_sdk-0.1.0.dist-info/top_level.txt +0 -1
- {qwak-sdk → qwak_sdk/commands}/__init__.py +0 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import fnmatch
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
import shutil
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Iterable, List, Optional, Tuple
|
|
9
|
+
|
|
10
|
+
import requests
|
|
11
|
+
from qwak.exceptions import QwakException
|
|
12
|
+
|
|
13
|
+
from qwak_sdk.commands.models.build._logic.constant.temp_dir import TEMP_LOCAL_MODEL_DIR
|
|
14
|
+
from qwak_sdk.commands.models.build._logic.constant.upload_tag import (
|
|
15
|
+
BUILD_CONFIG_TAG,
|
|
16
|
+
MODEL_CODE_TAG,
|
|
17
|
+
QWAK_SDK_VERSION_TAG,
|
|
18
|
+
SKINNY_MODEL_CODE_TAG,
|
|
19
|
+
)
|
|
20
|
+
from qwak_sdk.commands.models.build._logic.interface.step_inteface import Step
|
|
21
|
+
from qwak_sdk.commands.models.build._logic.util.step_decorator import (
|
|
22
|
+
build_failure_handler,
|
|
23
|
+
)
|
|
24
|
+
from qwak_sdk.exceptions import QwakGeneralBuildException
|
|
25
|
+
from qwak_sdk.tools.files import copytree
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from qwak_sdk.commands.models.build._logic import Notifier
|
|
29
|
+
|
|
30
|
+
from qwak_sdk import __version__ as qwak_sdk_version
|
|
31
|
+
|
|
32
|
+
_MAX_FILE_SIZE_BYTES = 10000000
|
|
33
|
+
_IGNORED_PATTERNS = [r"\..*", r"__pycache__"]
|
|
34
|
+
_LOG_PREFIX = "Saving Qwak Model"
|
|
35
|
+
QWAK_IGNORE_FILE_NAME = ".qwakignore"
|
|
36
|
+
|
|
37
|
+
# Hidden directories setting
|
|
38
|
+
HIDDEN_FILES_PREFIX = "."
|
|
39
|
+
HIDDEN_DIRS_TO_INCLUDE = [".dvc"]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class UploadStep(Step):
|
|
43
|
+
def description(self) -> str:
|
|
44
|
+
return _LOG_PREFIX
|
|
45
|
+
|
|
46
|
+
@build_failure_handler()
|
|
47
|
+
def execute(self) -> None:
|
|
48
|
+
files_tag_iterator = self.create_files_to_upload()
|
|
49
|
+
files_total_size = sum(
|
|
50
|
+
file.stat().st_size for (file, tag) in files_tag_iterator
|
|
51
|
+
)
|
|
52
|
+
upload_so_far = 0
|
|
53
|
+
for file, tag in files_tag_iterator:
|
|
54
|
+
if file.exists():
|
|
55
|
+
pre_signed_url = self.upload_file(
|
|
56
|
+
file=file,
|
|
57
|
+
tag=tag,
|
|
58
|
+
all_files_size_to_upload=files_total_size,
|
|
59
|
+
read_so_far=upload_so_far,
|
|
60
|
+
)
|
|
61
|
+
upload_so_far += file.stat().st_size
|
|
62
|
+
|
|
63
|
+
if tag == MODEL_CODE_TAG:
|
|
64
|
+
self.context.model_code_remote_url = str(pre_signed_url).split("?")[
|
|
65
|
+
0
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
def create_files_to_upload(self) -> Tuple[List[Tuple[Path, Any]], int]:
|
|
69
|
+
ignored_patterns = (
|
|
70
|
+
load_patterns_from_ignore_file(
|
|
71
|
+
notifier=self.notifier,
|
|
72
|
+
ignore_file_path=self.context.host_temp_local_build_dir
|
|
73
|
+
/ TEMP_LOCAL_MODEL_DIR
|
|
74
|
+
/ self.config.build_properties.model_uri.main_dir
|
|
75
|
+
/ QWAK_IGNORE_FILE_NAME,
|
|
76
|
+
)
|
|
77
|
+
+ _IGNORED_PATTERNS
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# copy 'main' and 'tests' directories
|
|
81
|
+
dirs_to_include = [self.config.build_properties.model_uri.main_dir, "tests"]
|
|
82
|
+
deps_folders = (
|
|
83
|
+
self.config.build_properties.model_uri.dependency_required_folders
|
|
84
|
+
)
|
|
85
|
+
if deps_folders:
|
|
86
|
+
self.notifier.debug(
|
|
87
|
+
f"Adding dependency folders to model code: {deps_folders}"
|
|
88
|
+
)
|
|
89
|
+
dirs_to_include += deps_folders
|
|
90
|
+
|
|
91
|
+
self.notifier.debug("Zipping skinny model code")
|
|
92
|
+
skinny_size_zip_file = zip_model(
|
|
93
|
+
build_dir=self.context.host_temp_local_build_dir,
|
|
94
|
+
dependency_file=self.context.model_relative_dependency_file,
|
|
95
|
+
dirs_to_include=dirs_to_include,
|
|
96
|
+
zip_name="skinny_size_model_code",
|
|
97
|
+
ignored_patterns=ignored_patterns,
|
|
98
|
+
max_bytes=_MAX_FILE_SIZE_BYTES,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Full size model
|
|
102
|
+
self.notifier.debug("Zipping full model code")
|
|
103
|
+
full_size_zip_file = zip_model(
|
|
104
|
+
build_dir=self.context.host_temp_local_build_dir,
|
|
105
|
+
dependency_file=self.context.model_relative_dependency_file,
|
|
106
|
+
dirs_to_include=dirs_to_include,
|
|
107
|
+
zip_name="full_size_model_code",
|
|
108
|
+
ignored_patterns=ignored_patterns,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Dump config file for upload
|
|
112
|
+
config_file_temp = self.context.host_temp_local_build_dir / "build.conf"
|
|
113
|
+
config_file_temp.write_text(self.config.to_yaml())
|
|
114
|
+
|
|
115
|
+
# Dump qwak-sdk version for upload
|
|
116
|
+
qwak_sdk_version_temp = self.context.host_temp_local_build_dir / "VERSION"
|
|
117
|
+
qwak_sdk_version_temp.write_text(qwak_sdk_version)
|
|
118
|
+
|
|
119
|
+
files_tag_iterator = [
|
|
120
|
+
(full_size_zip_file, MODEL_CODE_TAG),
|
|
121
|
+
(skinny_size_zip_file, SKINNY_MODEL_CODE_TAG),
|
|
122
|
+
(qwak_sdk_version_temp, QWAK_SDK_VERSION_TAG),
|
|
123
|
+
(config_file_temp, BUILD_CONFIG_TAG),
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
return files_tag_iterator
|
|
127
|
+
|
|
128
|
+
def upload_file(
|
|
129
|
+
self, file: Path, tag: str, all_files_size_to_upload: int, read_so_far: int
|
|
130
|
+
):
|
|
131
|
+
self.notifier.debug(f"Upload file {file}")
|
|
132
|
+
|
|
133
|
+
pre_signed_url = self.get_pre_signed_upload_url(tag=tag)
|
|
134
|
+
self.upload_file_to_s3(
|
|
135
|
+
upload_url=pre_signed_url,
|
|
136
|
+
file=file,
|
|
137
|
+
all_files_size_to_upload=all_files_size_to_upload,
|
|
138
|
+
read_so_far=read_so_far,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
self.notifier.debug(f"Upload file {file} completed")
|
|
142
|
+
|
|
143
|
+
return pre_signed_url
|
|
144
|
+
|
|
145
|
+
def get_pre_signed_upload_url(self, tag: str) -> str:
|
|
146
|
+
try:
|
|
147
|
+
self.notifier.debug(f"Getting pre-signed url for S3 upload - tag {tag}")
|
|
148
|
+
|
|
149
|
+
pre_signed_url = (
|
|
150
|
+
self.context.client_builds_orchestrator.get_build_versioning_upload_url(
|
|
151
|
+
build_id=self.context.build_id,
|
|
152
|
+
model_id=self.context.model_id,
|
|
153
|
+
tag=tag,
|
|
154
|
+
).upload_url
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
self.notifier.debug("Pre-signed url generated successfully")
|
|
158
|
+
|
|
159
|
+
return pre_signed_url
|
|
160
|
+
except QwakException as e:
|
|
161
|
+
raise QwakGeneralBuildException(
|
|
162
|
+
message="Unable to get pre-signed url for uploading model",
|
|
163
|
+
src_exception=e,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def upload_file_to_s3(
|
|
167
|
+
self,
|
|
168
|
+
upload_url: str,
|
|
169
|
+
file: Path,
|
|
170
|
+
all_files_size_to_upload: int,
|
|
171
|
+
read_so_far: int,
|
|
172
|
+
):
|
|
173
|
+
try:
|
|
174
|
+
self.notifier.debug(f"Upload file {file} to Qwak storage")
|
|
175
|
+
|
|
176
|
+
http_response = requests.put( # nosec B113
|
|
177
|
+
url=upload_url,
|
|
178
|
+
data=UploadInChunks(
|
|
179
|
+
file=file,
|
|
180
|
+
notifier=self.notifier,
|
|
181
|
+
chunk_size_bytes=10,
|
|
182
|
+
all_files_size_to_upload=all_files_size_to_upload,
|
|
183
|
+
read_so_far=read_so_far,
|
|
184
|
+
),
|
|
185
|
+
headers={"content-type": "text/plain"},
|
|
186
|
+
)
|
|
187
|
+
if http_response.status_code != 200:
|
|
188
|
+
raise QwakException(
|
|
189
|
+
f"Status: [{http_response.status_code}], "
|
|
190
|
+
f"reason: [{http_response.reason}]"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
self.notifier.debug(f"File {file} uploaded to Qwak storage successfully")
|
|
194
|
+
except Exception as e:
|
|
195
|
+
raise QwakGeneralBuildException(
|
|
196
|
+
message="Fail uploading model to S3 storage.",
|
|
197
|
+
src_exception=e,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def load_patterns_from_ignore_file(notifier: Notifier, ignore_file_path: Path):
|
|
202
|
+
if Path(ignore_file_path).is_file():
|
|
203
|
+
notifier.info("Found a Qwak ignore file - will ignore listed patterns")
|
|
204
|
+
|
|
205
|
+
with open(ignore_file_path, "r") as igonre_file:
|
|
206
|
+
patterns_to_ignore = [
|
|
207
|
+
pattern.strip() for pattern in igonre_file.readlines()
|
|
208
|
+
]
|
|
209
|
+
notifier.debug(
|
|
210
|
+
f"Patterns from Qwak igonre file detected - {str(patterns_to_ignore)}"
|
|
211
|
+
)
|
|
212
|
+
return patterns_to_ignore
|
|
213
|
+
|
|
214
|
+
notifier.debug("no Qwak ignore file was found, skipping")
|
|
215
|
+
return []
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _replace_large_files_with_too_large_file_message(
|
|
219
|
+
filtered_model: Path, max_bytes: Optional[int]
|
|
220
|
+
):
|
|
221
|
+
def does_exceed_size(file: Path):
|
|
222
|
+
file_size = file.lstat().st_size
|
|
223
|
+
return file_size > max_bytes, file.lstat().st_size
|
|
224
|
+
|
|
225
|
+
if max_bytes is None:
|
|
226
|
+
return
|
|
227
|
+
|
|
228
|
+
for root, dirs, files in os.walk(filtered_model):
|
|
229
|
+
for file in files:
|
|
230
|
+
file_path = Path(os.path.join(root, file))
|
|
231
|
+
replace_content, file_size = does_exceed_size(file_path)
|
|
232
|
+
if replace_content:
|
|
233
|
+
Path(file_path).write_text(
|
|
234
|
+
f"File is too big to display. Size: {file_size} bytes"
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def zip_model(
|
|
239
|
+
build_dir: Path,
|
|
240
|
+
dependency_file: Path,
|
|
241
|
+
dirs_to_include: list[str],
|
|
242
|
+
zip_name: str,
|
|
243
|
+
ignored_patterns: Iterable[str],
|
|
244
|
+
max_bytes: Optional[int] = None,
|
|
245
|
+
):
|
|
246
|
+
try:
|
|
247
|
+
filtered_model = build_dir / zip_name
|
|
248
|
+
ignored_patterns = get_files_to_ignore(
|
|
249
|
+
directory=build_dir / TEMP_LOCAL_MODEL_DIR, patterns=ignored_patterns
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
for included_dir in dirs_to_include:
|
|
253
|
+
dir_to_copy = build_dir / TEMP_LOCAL_MODEL_DIR / included_dir
|
|
254
|
+
if dir_to_copy.is_dir():
|
|
255
|
+
copytree(
|
|
256
|
+
src=build_dir / TEMP_LOCAL_MODEL_DIR / included_dir,
|
|
257
|
+
dst=filtered_model / included_dir,
|
|
258
|
+
ignore=shutil.ignore_patterns(*ignored_patterns),
|
|
259
|
+
dirs_exist_ok=True,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
deps_file = build_dir / TEMP_LOCAL_MODEL_DIR / dependency_file
|
|
263
|
+
|
|
264
|
+
shutil.copy(deps_file, filtered_model / dependency_file)
|
|
265
|
+
|
|
266
|
+
_replace_large_files_with_too_large_file_message(filtered_model, max_bytes)
|
|
267
|
+
|
|
268
|
+
zip_path = Path(
|
|
269
|
+
shutil.make_archive(
|
|
270
|
+
base_name=str(filtered_model),
|
|
271
|
+
format="zip",
|
|
272
|
+
root_dir=filtered_model,
|
|
273
|
+
)
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
shutil.rmtree(filtered_model)
|
|
277
|
+
return zip_path
|
|
278
|
+
|
|
279
|
+
except Exception as e:
|
|
280
|
+
raise QwakGeneralBuildException(
|
|
281
|
+
message="Unable to zip model before upload",
|
|
282
|
+
src_exception=e,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def get_files_to_ignore(directory: Path, patterns: Iterable[str] = ()):
|
|
287
|
+
def ignore_hidden(file: Path, exclusions: List[str]):
|
|
288
|
+
name = os.path.basename(os.path.abspath(file))
|
|
289
|
+
is_hidden = name.startswith(HIDDEN_FILES_PREFIX) and (
|
|
290
|
+
name != QWAK_IGNORE_FILE_NAME and name not in exclusions
|
|
291
|
+
)
|
|
292
|
+
return is_hidden
|
|
293
|
+
|
|
294
|
+
def is_ignore_by_pattern(file: Path):
|
|
295
|
+
return (
|
|
296
|
+
len(
|
|
297
|
+
[
|
|
298
|
+
pattern
|
|
299
|
+
for pattern in patterns
|
|
300
|
+
if re.search(fnmatch.translate(pattern), str(file))
|
|
301
|
+
]
|
|
302
|
+
)
|
|
303
|
+
!= 0
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
return [
|
|
307
|
+
file.name
|
|
308
|
+
for file in Path(directory).rglob("*")
|
|
309
|
+
if is_ignore_by_pattern(file)
|
|
310
|
+
or ignore_hidden(file, exclusions=HIDDEN_DIRS_TO_INCLUDE)
|
|
311
|
+
]
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class UploadInChunks(object):
|
|
315
|
+
def __init__(
|
|
316
|
+
self,
|
|
317
|
+
file: Path,
|
|
318
|
+
notifier: Notifier,
|
|
319
|
+
all_files_size_to_upload: int,
|
|
320
|
+
read_so_far: int = 0,
|
|
321
|
+
chunk_size_bytes: int = 1 << 13,
|
|
322
|
+
):
|
|
323
|
+
self._file = file
|
|
324
|
+
self._chunk_size = chunk_size_bytes
|
|
325
|
+
self._total_size = self._file.stat().st_size
|
|
326
|
+
self._read_so_far = read_so_far
|
|
327
|
+
self._notifier = notifier
|
|
328
|
+
self._all_files_size_to_upload = (
|
|
329
|
+
all_files_size_to_upload # Used for calculating percentage for both files
|
|
330
|
+
)
|
|
331
|
+
self._last_percent_update = 0
|
|
332
|
+
|
|
333
|
+
def __iter__(self):
|
|
334
|
+
with self._file.open("rb") as file:
|
|
335
|
+
while True:
|
|
336
|
+
data = file.read(self._chunk_size)
|
|
337
|
+
if not data:
|
|
338
|
+
break
|
|
339
|
+
self._read_so_far += len(data)
|
|
340
|
+
percent = self._read_so_far * 1e2 / self._all_files_size_to_upload
|
|
341
|
+
msg = "{percent:3.0f}%".format(percent=percent)
|
|
342
|
+
if int(percent / 10) > self._last_percent_update:
|
|
343
|
+
self._notifier.info(msg) # Updating only after 10 percent change
|
|
344
|
+
self._last_percent_update = int(percent / 10)
|
|
345
|
+
self._notifier.spinner_text(line=msg)
|
|
346
|
+
yield data
|
|
347
|
+
|
|
348
|
+
def __len__(self):
|
|
349
|
+
return self._total_size
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from _qwak_proto.qwak.build.v1.build_api_pb2 import GetBuildResponse
|
|
6
|
+
from _qwak_proto.qwak.build.v1.build_pb2 import BuildStatus
|
|
7
|
+
|
|
8
|
+
from qwak_sdk.commands.models.build._logic.client_logs.messages import (
|
|
9
|
+
FAILED_REMOTE_BUILD_SUGGESTION,
|
|
10
|
+
)
|
|
11
|
+
from qwak_sdk.commands.models.build._logic.interface.step_inteface import Step
|
|
12
|
+
from qwak_sdk.exceptions.qwak_remote_build_failed import QwakRemoteBuildFailedException
|
|
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.notifier.info("Waiting for build to finish")
|
|
30
|
+
status = self.wait_for_finite_build_status()
|
|
31
|
+
if status != BuildStatus.SUCCESSFUL:
|
|
32
|
+
raise QwakRemoteBuildFailedException(
|
|
33
|
+
message=self.REMOTE_BUILD_FAILURE_EXCEPTION_FORMAT.format(
|
|
34
|
+
status=BuildStatus.Name(status)
|
|
35
|
+
),
|
|
36
|
+
suggestion=FAILED_REMOTE_BUILD_SUGGESTION.format(
|
|
37
|
+
build_id=self.context.build_id,
|
|
38
|
+
model_id=self.context.model_id,
|
|
39
|
+
project_uuid=self.context.project_uuid,
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
self.notifier.info("Your build finished successfully")
|
|
43
|
+
|
|
44
|
+
def wait_for_finite_build_status(self) -> BuildStatus:
|
|
45
|
+
self.notifier.spinner_text(line="Waiting for build to finish")
|
|
46
|
+
while True:
|
|
47
|
+
result: GetBuildResponse = (
|
|
48
|
+
self.context.client_builds_orchestrator.get_build(self.context.build_id)
|
|
49
|
+
)
|
|
50
|
+
status: BuildStatus = result.build.build_status
|
|
51
|
+
if status in self.FINITE_BUILD_STATUSES:
|
|
52
|
+
return status
|
|
53
|
+
self.notifier.debug(f"Build status is currently {BuildStatus.Name(status)}")
|
|
54
|
+
time.sleep(self.SLEEP_BETWEEN_STATUS_CHECK)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
|
|
5
|
+
from qwak_sdk.commands.models.build._logic.client_logs.messages import (
|
|
6
|
+
FAILED_DEPLOY_BUILD_SUGGESTION,
|
|
7
|
+
)
|
|
8
|
+
from qwak_sdk.commands.models.build._logic.interface.step_inteface import Step
|
|
9
|
+
from qwak_sdk.commands.models.deployments.deploy.realtime.ui import deploy_realtime
|
|
10
|
+
from qwak_sdk.exceptions.qwak_deploy_new_build_failed import (
|
|
11
|
+
QwakDeployNewBuildFailedException,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DeployBuildStep(Step):
|
|
16
|
+
SMALL_DEPLOYMENT: Dict[str, Any] = {
|
|
17
|
+
"pods": 1,
|
|
18
|
+
"cpus": 2,
|
|
19
|
+
"memory": 2048,
|
|
20
|
+
}
|
|
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.notifier.info(f"Deploying build {self.context.build_id}")
|
|
28
|
+
try:
|
|
29
|
+
deploy_config = {
|
|
30
|
+
"build_id": self.context.build_id,
|
|
31
|
+
"model_id": self.context.model_id,
|
|
32
|
+
}
|
|
33
|
+
deploy_config.update(self.SMALL_DEPLOYMENT)
|
|
34
|
+
deploy_realtime(from_file=None, out_conf=False, sync=False, **deploy_config)
|
|
35
|
+
self.notifier.info(f"Finished deploying build {self.context.build_id}")
|
|
36
|
+
except Exception as e:
|
|
37
|
+
raise QwakDeployNewBuildFailedException(
|
|
38
|
+
message=self.DEPLOY_FAILURE_EXCEPTION_MESSAGE.format(e=e),
|
|
39
|
+
suggestion=FAILED_DEPLOY_BUILD_SUGGESTION.format(
|
|
40
|
+
build_id=self.context.build_id,
|
|
41
|
+
model_id=self.context.model_id,
|
|
42
|
+
project_uuid=self.context.project_uuid,
|
|
43
|
+
),
|
|
44
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from qwak.exceptions import QwakException
|
|
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 QwakException(
|
|
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 QwakException("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
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from qwak.exceptions import QuietError
|
|
7
|
+
|
|
8
|
+
from qwak_sdk.commands.models.build._logic.interface.step_inteface import Step
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from qwak_sdk.commands.models.build import Notifier
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def build_failure_handler(should_fail_build: bool = True):
|
|
15
|
+
def _exception_handler(func):
|
|
16
|
+
@wraps(func)
|
|
17
|
+
def inner_function(*args, **kwargs):
|
|
18
|
+
try:
|
|
19
|
+
func(*args, **kwargs)
|
|
20
|
+
except BaseException as e:
|
|
21
|
+
if should_fail_build and not isinstance(e, QuietError):
|
|
22
|
+
notifier: Notifier = args[0].notifier
|
|
23
|
+
notifier.error(
|
|
24
|
+
"Build failed with Exception. See the stack trace above."
|
|
25
|
+
)
|
|
26
|
+
cleaning_up_after_build(args[0])
|
|
27
|
+
raise e
|
|
28
|
+
|
|
29
|
+
return inner_function
|
|
30
|
+
|
|
31
|
+
return _exception_handler
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def cleaning_up_after_build(step: Step):
|
|
35
|
+
if os.getenv("QWAK_DEBUG") != "true":
|
|
36
|
+
step.notifier.debug("Removing Qwak temp artifacts directory")
|
|
37
|
+
shutil.rmtree(step.context.host_temp_local_build_dir, ignore_errors=True)
|