qwak-sdk 0.5.102__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.
- qwak_sdk/__init__.py +9 -0
- qwak_sdk/cli.py +79 -0
- qwak_sdk/commands/__init__.py +0 -0
- qwak_sdk/commands/_logic/__init__.py +0 -0
- qwak_sdk/commands/_logic/tools.py +6 -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/alerts/__init__.py +0 -0
- qwak_sdk/commands/alerts/alerts_commnad_group.py +18 -0
- qwak_sdk/commands/alerts/delete/__init__.py +0 -0
- qwak_sdk/commands/alerts/delete/_logic.py +5 -0
- qwak_sdk/commands/alerts/delete/ui.py +10 -0
- qwak_sdk/commands/alerts/list/__init__.py +0 -0
- qwak_sdk/commands/alerts/list/_logic.py +23 -0
- qwak_sdk/commands/alerts/list/ui.py +17 -0
- qwak_sdk/commands/alerts/register/__init__.py +0 -0
- qwak_sdk/commands/alerts/register/_logic.py +72 -0
- qwak_sdk/commands/alerts/register/ui.py +30 -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 +15 -0
- qwak_sdk/commands/audience/_logic/config/parser.py +30 -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 +59 -0
- qwak_sdk/commands/audience/_logic/config/v1/config_v1.py +23 -0
- qwak_sdk/commands/audience/_logic/config/v1/route_config.py +15 -0
- qwak_sdk/commands/audience/_logic/config/v1/spec.py +9 -0
- qwak_sdk/commands/audience/audience_api_dump.py +86 -0
- qwak_sdk/commands/audience/audience_commands_group.py +30 -0
- qwak_sdk/commands/audience/create/__init__.py +0 -0
- qwak_sdk/commands/audience/create/logic.py +41 -0
- qwak_sdk/commands/audience/create/ui.py +21 -0
- qwak_sdk/commands/audience/delete/__init__.py +0 -0
- qwak_sdk/commands/audience/delete/logic.py +13 -0
- qwak_sdk/commands/audience/delete/ui.py +17 -0
- qwak_sdk/commands/audience/get/__init__.py +0 -0
- qwak_sdk/commands/audience/get/logic.py +14 -0
- qwak_sdk/commands/audience/get/ui.py +25 -0
- qwak_sdk/commands/audience/list/__init__.py +0 -0
- qwak_sdk/commands/audience/list/logic.py +16 -0
- qwak_sdk/commands/audience/list/ui.py +26 -0
- qwak_sdk/commands/audience/update/__init__.py +0 -0
- qwak_sdk/commands/audience/update/logic.py +37 -0
- qwak_sdk/commands/audience/update/ui.py +26 -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 +152 -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 +36 -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/backfill/__init__.py +0 -0
- qwak_sdk/commands/feature_store/backfill/_logic.py +140 -0
- qwak_sdk/commands/feature_store/backfill/streaming/__init__.py +0 -0
- qwak_sdk/commands/feature_store/backfill/streaming/_logic.py +50 -0
- qwak_sdk/commands/feature_store/backfill/streaming/ui.py +67 -0
- qwak_sdk/commands/feature_store/backfill/ui.py +146 -0
- qwak_sdk/commands/feature_store/delete/__init__.py +0 -0
- qwak_sdk/commands/feature_store/delete/_logic.py +104 -0
- qwak_sdk/commands/feature_store/delete/ui.py +40 -0
- qwak_sdk/commands/feature_store/execution/__init__.py +0 -0
- qwak_sdk/commands/feature_store/execution/ui.py +19 -0
- qwak_sdk/commands/feature_store/feature_store_command_group.py +29 -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 +367 -0
- qwak_sdk/commands/feature_store/register/ui.py +111 -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 +39 -0
- qwak_sdk/commands/models/__init__.py +0 -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 +42 -0
- qwak_sdk/commands/models/build/_logic/client_logs/__init__.py +0 -0
- qwak_sdk/commands/models/build/_logic/client_logs/cli_phase_run_handler.py +123 -0
- qwak_sdk/commands/models/build/_logic/client_logs/cli_trigger_build_logger.py +19 -0
- qwak_sdk/commands/models/build/_logic/client_logs/logger.py +88 -0
- qwak_sdk/commands/models/build/_logic/client_logs/messages.py +36 -0
- qwak_sdk/commands/models/build/_logic/client_logs/spinner.py +14 -0
- qwak_sdk/commands/models/build/_logic/client_logs/trigger_build_logger.py +54 -0
- qwak_sdk/commands/models/build/_logic/client_logs/utils.py +12 -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 +20 -0
- qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/get_sdk_version_step.py +14 -0
- qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/__init__.py +16 -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 +55 -0
- qwak_sdk/commands/models/build/_logic/phase/c_deploy/deploy_build.py +61 -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 +60 -0
- qwak_sdk/commands/models/build/_logic/util/text.py +9 -0
- qwak_sdk/commands/models/build/_logic/wait_until_finished.py +27 -0
- qwak_sdk/commands/models/build/ui.py +337 -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 +39 -0
- qwak_sdk/commands/models/create/__init__.py +0 -0
- qwak_sdk/commands/models/create/_logic.py +36 -0
- qwak_sdk/commands/models/create/ui.py +43 -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 +25 -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 +68 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py +261 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment.py +405 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +114 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_response_handler.py +156 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +96 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/get_latest_successful_build.py +28 -0
- qwak_sdk/commands/models/deployments/deploy/_logic/local_deployment.py +193 -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 +15 -0
- qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +24 -0
- qwak_sdk/commands/models/deployments/deploy/batch/ui.py +126 -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 +21 -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 +75 -0
- qwak_sdk/commands/models/deployments/deploy/realtime/ui.py +209 -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 +213 -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 +249 -0
- qwak_sdk/commands/models/deployments/undeploy/ui.py +72 -0
- qwak_sdk/commands/models/describe/__init__.py +0 -0
- qwak_sdk/commands/models/describe/_logic.py +169 -0
- qwak_sdk/commands/models/describe/ui.py +35 -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 +81 -0
- qwak_sdk/commands/models/executions/start/ui.py +208 -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 +11 -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 +11 -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 +20 -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 +40 -0
- qwak_sdk/commands/models/list_models/__init__.py +0 -0
- qwak_sdk/commands/models/list_models/_logic.py +5 -0
- qwak_sdk/commands/models/list_models/ui.py +60 -0
- qwak_sdk/commands/models/metadata/__init__.py +0 -0
- qwak_sdk/commands/models/metadata/_logic.py +5 -0
- qwak_sdk/commands/models/metadata/ui.py +60 -0
- qwak_sdk/commands/models/models_command_group.py +44 -0
- qwak_sdk/commands/models/runtime/__init__.py +0 -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 +17 -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 +9 -0
- qwak_sdk/commands/projects/create/ui.py +68 -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 +24 -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 +45 -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/commands/workspaces/__init__.py +0 -0
- qwak_sdk/commands/workspaces/_logic/__init__.py +0 -0
- qwak_sdk/commands/workspaces/_logic/tools.py +44 -0
- qwak_sdk/commands/workspaces/_logic/workspace_validations.py +41 -0
- qwak_sdk/commands/workspaces/config/__init__.py +0 -0
- qwak_sdk/commands/workspaces/config/workspace_config.py +35 -0
- qwak_sdk/commands/workspaces/create/__init__.py +0 -0
- qwak_sdk/commands/workspaces/create/_logic.py +54 -0
- qwak_sdk/commands/workspaces/create/ui.py +48 -0
- qwak_sdk/commands/workspaces/delete/__init__.py +0 -0
- qwak_sdk/commands/workspaces/delete/_logic.py +30 -0
- qwak_sdk/commands/workspaces/delete/ui.py +23 -0
- qwak_sdk/commands/workspaces/start/__init__.py +0 -0
- qwak_sdk/commands/workspaces/start/_logic.py +30 -0
- qwak_sdk/commands/workspaces/start/ui.py +23 -0
- qwak_sdk/commands/workspaces/stop/__init__.py +0 -0
- qwak_sdk/commands/workspaces/stop/_logic.py +30 -0
- qwak_sdk/commands/workspaces/stop/ui.py +23 -0
- qwak_sdk/commands/workspaces/update/__init__.py +0 -0
- qwak_sdk/commands/workspaces/update/_logic.py +82 -0
- qwak_sdk/commands/workspaces/update/ui.py +57 -0
- qwak_sdk/commands/workspaces/workspaces_commands_group.py +23 -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_resource_not_found.py +2 -0
- qwak_sdk/inner/__init__.py +0 -0
- qwak_sdk/inner/file_registry.py +98 -0
- qwak_sdk/inner/tools/__init__.py +0 -0
- qwak_sdk/inner/tools/cli_tools.py +220 -0
- qwak_sdk/inner/tools/config_handler.py +27 -0
- qwak_sdk/inner/tools/dataclasses_utils.py +21 -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 +63 -0
- qwak_sdk/tools/log_handling.py +159 -0
- qwak_sdk/tools/utils.py +42 -0
- qwak_sdk-0.5.102.dist-info/METADATA +51 -0
- qwak_sdk-0.5.102.dist-info/RECORD +328 -0
- qwak_sdk-0.5.102.dist-info/WHEEL +4 -0
- qwak_sdk-0.5.102.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
from _qwak_proto.qwak.audience.v1.audience_pb2 import (
|
|
4
|
+
Audience,
|
|
5
|
+
AudienceEntry,
|
|
6
|
+
BinaryOperatorType,
|
|
7
|
+
UnaryOperatorType,
|
|
8
|
+
)
|
|
9
|
+
from google.protobuf.json_format import MessageToJson
|
|
10
|
+
from tabulate import tabulate
|
|
11
|
+
|
|
12
|
+
from qwak_sdk.tools.colors import Color
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def audience_to_json(audience: Audience):
|
|
16
|
+
return MessageToJson(audience)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def audience_to_pretty_string(audience_id: str, audience: Audience):
|
|
20
|
+
header = f"{Color.UNDERLINE + Color.BOLD}Audience {audience_id}{Color.END}"
|
|
21
|
+
details_header = f"{Color.UNDERLINE}Details{Color.END}"
|
|
22
|
+
details_table = tabulate(
|
|
23
|
+
tabular_data=[[audience.name, audience.description]],
|
|
24
|
+
headers=["name", "description"],
|
|
25
|
+
tablefmt="pretty",
|
|
26
|
+
)
|
|
27
|
+
conditions_header = f"{Color.UNDERLINE}Conditions{Color.END}"
|
|
28
|
+
conditions_binary_header = f"{Color.CYAN}Binary condition{Color.END}"
|
|
29
|
+
conditions_binary_table = tabulate(
|
|
30
|
+
tabular_data=[
|
|
31
|
+
[
|
|
32
|
+
condition.key,
|
|
33
|
+
BinaryOperatorType.DESCRIPTOR.values_by_number[
|
|
34
|
+
condition.binary_condition.operator
|
|
35
|
+
].name,
|
|
36
|
+
condition.binary_condition.first_operand,
|
|
37
|
+
condition.binary_condition.second_operand,
|
|
38
|
+
]
|
|
39
|
+
for condition in audience.conditions
|
|
40
|
+
if condition.binary_condition.operator
|
|
41
|
+
],
|
|
42
|
+
headers=["Key", "Operator", "First operand", "Second operand"],
|
|
43
|
+
tablefmt="pretty",
|
|
44
|
+
)
|
|
45
|
+
conditions_unary_header = f"{Color.CYAN}Unary condition{Color.END}"
|
|
46
|
+
conditions_unary_table = tabulate(
|
|
47
|
+
tabular_data=[
|
|
48
|
+
[
|
|
49
|
+
condition.key,
|
|
50
|
+
UnaryOperatorType.DESCRIPTOR.values_by_number[
|
|
51
|
+
condition.unary_condition.operator
|
|
52
|
+
].name,
|
|
53
|
+
condition.unary_condition.operand,
|
|
54
|
+
]
|
|
55
|
+
for condition in audience.conditions
|
|
56
|
+
if condition.unary_condition.operator
|
|
57
|
+
],
|
|
58
|
+
headers=["Key", "Operator", "Operand"],
|
|
59
|
+
tablefmt="pretty",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return f"""
|
|
63
|
+
{header}
|
|
64
|
+
{details_header}
|
|
65
|
+
{details_table}
|
|
66
|
+
|
|
67
|
+
{conditions_header}
|
|
68
|
+
{conditions_unary_header}
|
|
69
|
+
{conditions_unary_table}
|
|
70
|
+
|
|
71
|
+
{conditions_binary_header}
|
|
72
|
+
{conditions_binary_table}
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def audience_entries_to_pretty_string(audience_entries: List[AudienceEntry]) -> str:
|
|
77
|
+
header = f"{Color.BOLD + Color.UNDERLINE}Audiences{Color.END}"
|
|
78
|
+
table = tabulate(
|
|
79
|
+
tabular_data=[[entry.id, entry.audience.name] for entry in audience_entries],
|
|
80
|
+
headers=["Audience ID", "Audience Name"],
|
|
81
|
+
tablefmt="pretty",
|
|
82
|
+
)
|
|
83
|
+
return f"""
|
|
84
|
+
{header}
|
|
85
|
+
{table}
|
|
86
|
+
"""
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from qwak_sdk.commands.audience.create.ui import create_audience_command
|
|
6
|
+
from qwak_sdk.commands.audience.delete.ui import delete_audience_command
|
|
7
|
+
from qwak_sdk.commands.audience.get.ui import get_audience_command
|
|
8
|
+
from qwak_sdk.commands.audience.list.ui import list_audience_command
|
|
9
|
+
from qwak_sdk.commands.audience.update.ui import update_audience_command
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
DELIMITER = "----------------------------------------"
|
|
13
|
+
|
|
14
|
+
AUTOMATION = "automation"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.group(
|
|
18
|
+
name="audiences",
|
|
19
|
+
help="Manage audiences",
|
|
20
|
+
)
|
|
21
|
+
def audience_commands_group():
|
|
22
|
+
# Click commands group injection
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
audience_commands_group.add_command(create_audience_command)
|
|
27
|
+
audience_commands_group.add_command(get_audience_command)
|
|
28
|
+
audience_commands_group.add_command(list_audience_command)
|
|
29
|
+
audience_commands_group.add_command(delete_audience_command)
|
|
30
|
+
audience_commands_group.add_command(update_audience_command)
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import grpc
|
|
5
|
+
from qwak.clients.audience import AudienceClient
|
|
6
|
+
|
|
7
|
+
from qwak_sdk.commands.audience._logic.config.config_base import ConfigBase
|
|
8
|
+
from qwak_sdk.commands.audience._logic.config.parser import parse_audience_from_yaml
|
|
9
|
+
from qwak_sdk.commands.audience._logic.config.v1.config_v1 import ConfigV1
|
|
10
|
+
from qwak_sdk.exceptions import QwakCommandException
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def create_audience(
|
|
14
|
+
name: str = "",
|
|
15
|
+
description: str = "",
|
|
16
|
+
file: Optional[Path] = None,
|
|
17
|
+
) -> str:
|
|
18
|
+
config = parse_audience_from_yaml(file)
|
|
19
|
+
config = merge_kw_yaml(config=config, name=name, description=description)
|
|
20
|
+
audience_api = config.to_audiences_api()[0]
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
audience_id = AudienceClient().create_audience(audience=audience_api)
|
|
24
|
+
except grpc.RpcError as e:
|
|
25
|
+
raise QwakCommandException(e.args[0].details)
|
|
26
|
+
|
|
27
|
+
return audience_id
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def merge_kw_yaml(
|
|
31
|
+
config: ConfigBase,
|
|
32
|
+
name: str = "",
|
|
33
|
+
description: str = "",
|
|
34
|
+
) -> ConfigBase:
|
|
35
|
+
if isinstance(config, ConfigV1):
|
|
36
|
+
if name:
|
|
37
|
+
config.spec.audiences[0].name = name
|
|
38
|
+
if description:
|
|
39
|
+
config.spec.audiences[0].description = description
|
|
40
|
+
|
|
41
|
+
return config
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from qwak_sdk.commands.audience.create.logic import create_audience
|
|
6
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
7
|
+
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command("create", cls=QwakCommand)
|
|
11
|
+
@click.option("--name", type=str)
|
|
12
|
+
@click.option("--description", type=str)
|
|
13
|
+
@click.option("-f", "--file", type=click.Path(exists=True))
|
|
14
|
+
def create_audience_command(name: str, description: str, file: Path, **kwargs):
|
|
15
|
+
click.echo("Creating audience")
|
|
16
|
+
try:
|
|
17
|
+
audience_id = create_audience(name=name, description=description, file=file)
|
|
18
|
+
click.echo(f"Audience ID {audience_id} created successfully")
|
|
19
|
+
except (QwakCommandException, QwakResourceNotFound) as e:
|
|
20
|
+
click.echo(f"Failed to create audience, Error: {e}")
|
|
21
|
+
exit(1)
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import grpc
|
|
2
|
+
from qwak.clients.audience import AudienceClient
|
|
3
|
+
|
|
4
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def delete_audience(audience_id: str) -> None:
|
|
8
|
+
try:
|
|
9
|
+
AudienceClient().delete_audience(audience_id=audience_id)
|
|
10
|
+
except grpc.RpcError as e:
|
|
11
|
+
if e.args[0].code == grpc.StatusCode.NOT_FOUND:
|
|
12
|
+
raise QwakResourceNotFound(e.args[0].details)
|
|
13
|
+
raise QwakCommandException(e.args[0].details)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from qwak_sdk.commands.audience.delete.logic import delete_audience
|
|
4
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
5
|
+
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command("delete", cls=QwakCommand)
|
|
9
|
+
@click.option("--audience-id", type=str)
|
|
10
|
+
def delete_audience_command(audience_id: str, **kwargs):
|
|
11
|
+
click.echo(f"Deleting audience ID {audience_id}")
|
|
12
|
+
try:
|
|
13
|
+
delete_audience(audience_id)
|
|
14
|
+
click.echo(f"Audience ID {audience_id} deleted successfully")
|
|
15
|
+
except (QwakCommandException, QwakResourceNotFound) as e:
|
|
16
|
+
click.echo(f"Failed to delete audience, Error: {e}")
|
|
17
|
+
exit(1)
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import grpc
|
|
2
|
+
from _qwak_proto.qwak.audience.v1.audience_pb2 import Audience
|
|
3
|
+
from qwak.clients.audience import AudienceClient
|
|
4
|
+
|
|
5
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_audience(audience_id: str) -> Audience:
|
|
9
|
+
try:
|
|
10
|
+
return AudienceClient().get_audience(audience_id=audience_id)
|
|
11
|
+
except grpc.RpcError as e:
|
|
12
|
+
if e.args[0].code == grpc.StatusCode.NOT_FOUND:
|
|
13
|
+
raise QwakResourceNotFound(e.args[0].details)
|
|
14
|
+
raise QwakCommandException(e.args[0].details)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from qwak_sdk.commands.audience.audience_api_dump import (
|
|
4
|
+
audience_to_json,
|
|
5
|
+
audience_to_pretty_string,
|
|
6
|
+
)
|
|
7
|
+
from qwak_sdk.commands.audience.get.logic import get_audience
|
|
8
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
9
|
+
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.command("get", cls=QwakCommand)
|
|
13
|
+
@click.option("--audience-id", type=str)
|
|
14
|
+
@click.option("--json-format", is_flag=True, type=bool)
|
|
15
|
+
def get_audience_command(audience_id: str, json_format: bool, **kwargs):
|
|
16
|
+
click.echo(f"Getting audience {audience_id}")
|
|
17
|
+
try:
|
|
18
|
+
audience = get_audience(audience_id)
|
|
19
|
+
if json_format:
|
|
20
|
+
click.echo(audience_to_json(audience))
|
|
21
|
+
else:
|
|
22
|
+
click.echo(audience_to_pretty_string(audience_id, audience))
|
|
23
|
+
except (QwakCommandException, QwakResourceNotFound) as e:
|
|
24
|
+
click.echo(f"Failed to get audience, Error: {e}")
|
|
25
|
+
exit(1)
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import grpc
|
|
4
|
+
from _qwak_proto.qwak.audience.v1.audience_pb2 import AudienceEntry
|
|
5
|
+
from qwak.clients.audience import AudienceClient
|
|
6
|
+
|
|
7
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def list_audience() -> List[AudienceEntry]:
|
|
11
|
+
try:
|
|
12
|
+
return AudienceClient().list_audience()
|
|
13
|
+
except grpc.RpcError as e:
|
|
14
|
+
if e.args[0].code == grpc.StatusCode.NOT_FOUND:
|
|
15
|
+
raise QwakResourceNotFound(e.args[0].details)
|
|
16
|
+
raise QwakCommandException(e.args[0].details)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from qwak_sdk.commands._logic.tools import list_of_messages_to_json_str
|
|
4
|
+
from qwak_sdk.commands.audience.audience_api_dump import (
|
|
5
|
+
audience_entries_to_pretty_string,
|
|
6
|
+
)
|
|
7
|
+
from qwak_sdk.commands.audience.list.logic import list_audience
|
|
8
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
9
|
+
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.command("list", cls=QwakCommand)
|
|
13
|
+
@click.option("--json-format", is_flag=True, type=bool)
|
|
14
|
+
def list_audience_command(json_format: bool, **kwargs):
|
|
15
|
+
try:
|
|
16
|
+
audience_entries = list_audience()
|
|
17
|
+
if json_format:
|
|
18
|
+
click.echo(list_of_messages_to_json_str(audience_entries))
|
|
19
|
+
else:
|
|
20
|
+
click.echo("Getting audiences")
|
|
21
|
+
click.echo(
|
|
22
|
+
audience_entries_to_pretty_string(audience_entries=audience_entries)
|
|
23
|
+
)
|
|
24
|
+
except (QwakCommandException, QwakResourceNotFound) as e:
|
|
25
|
+
click.echo(f"Failed to list audiences, Error: {e}")
|
|
26
|
+
exit(1)
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import grpc
|
|
5
|
+
from qwak.clients.audience import AudienceClient
|
|
6
|
+
|
|
7
|
+
from qwak_sdk.commands.audience._logic.config.config_base import ConfigBase
|
|
8
|
+
from qwak_sdk.commands.audience._logic.config.parser import parse_audience_from_yaml
|
|
9
|
+
from qwak_sdk.commands.audience._logic.config.v1.config_v1 import ConfigV1
|
|
10
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def update_audience(
|
|
14
|
+
audience_id: str, name: str = "", description: str = "", file: Optional[Path] = None
|
|
15
|
+
) -> None:
|
|
16
|
+
config = parse_audience_from_yaml(file)
|
|
17
|
+
config = merge_kw_yaml(config=config, name=name, description=description)
|
|
18
|
+
audience_api = config.to_audiences_api()[0]
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
AudienceClient().update_audience(audience_id=audience_id, audience=audience_api)
|
|
22
|
+
except grpc.RpcError as e:
|
|
23
|
+
if e.args[0].code == grpc.StatusCode.NOT_FOUND:
|
|
24
|
+
raise QwakResourceNotFound(e.args[0].details)
|
|
25
|
+
raise QwakCommandException(e.args[0].details)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def merge_kw_yaml(
|
|
29
|
+
config: ConfigBase, name: str = "", description: str = ""
|
|
30
|
+
) -> ConfigBase:
|
|
31
|
+
if isinstance(config, ConfigV1):
|
|
32
|
+
if name:
|
|
33
|
+
config.spec.audiences[0].name = name
|
|
34
|
+
if description:
|
|
35
|
+
config.spec.audiences[0].description = description
|
|
36
|
+
|
|
37
|
+
return config
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from qwak_sdk.commands.audience.update.logic import update_audience
|
|
6
|
+
from qwak_sdk.exceptions import QwakCommandException, QwakResourceNotFound
|
|
7
|
+
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command("update", cls=QwakCommand)
|
|
11
|
+
@click.option("--audience-id", type=str)
|
|
12
|
+
@click.option("--name", type=str)
|
|
13
|
+
@click.option("--description", type=str)
|
|
14
|
+
@click.option("-f", "--file", type=click.Path(exists=True))
|
|
15
|
+
def update_audience_command(
|
|
16
|
+
audience_id: str, name: str, description: str, file: Path, **kwargs
|
|
17
|
+
):
|
|
18
|
+
click.echo(f"Updating audience ID {audience_id}")
|
|
19
|
+
try:
|
|
20
|
+
update_audience(
|
|
21
|
+
audience_id=audience_id, name=name, description=description, file=file
|
|
22
|
+
)
|
|
23
|
+
click.echo(f"Audience ID {audience_id} updated successfully")
|
|
24
|
+
except (QwakCommandException, QwakResourceNotFound) as e:
|
|
25
|
+
click.echo(f"Failed to update audience, Error: {e}")
|
|
26
|
+
exit(1)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
from _qwak_proto.qwak.auto_scaling.v1.auto_scaling_pb2 import (
|
|
6
|
+
AGGREGATION_TYPE_AVERAGE,
|
|
7
|
+
AGGREGATION_TYPE_MAX,
|
|
8
|
+
AGGREGATION_TYPE_MIN,
|
|
9
|
+
AGGREGATION_TYPE_P50,
|
|
10
|
+
AGGREGATION_TYPE_P90,
|
|
11
|
+
AGGREGATION_TYPE_P95,
|
|
12
|
+
AGGREGATION_TYPE_P99,
|
|
13
|
+
AGGREGATION_TYPE_SUM,
|
|
14
|
+
METRIC_TYPE_CPU,
|
|
15
|
+
METRIC_TYPE_ERROR_RATE,
|
|
16
|
+
METRIC_TYPE_GPU,
|
|
17
|
+
METRIC_TYPE_LATENCY,
|
|
18
|
+
METRIC_TYPE_MEMORY,
|
|
19
|
+
METRIC_TYPE_THROUGHPUT,
|
|
20
|
+
AutoScalingConfig,
|
|
21
|
+
PrometheusTrigger,
|
|
22
|
+
QuerySpec,
|
|
23
|
+
Trigger,
|
|
24
|
+
Triggers,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
from qwak_sdk.exceptions import QwakCommandException
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MetricType(Enum):
|
|
31
|
+
cpu = METRIC_TYPE_CPU
|
|
32
|
+
gpu = METRIC_TYPE_GPU
|
|
33
|
+
latency = METRIC_TYPE_LATENCY
|
|
34
|
+
memory = METRIC_TYPE_MEMORY
|
|
35
|
+
throughput = METRIC_TYPE_THROUGHPUT
|
|
36
|
+
error_rate = METRIC_TYPE_ERROR_RATE
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def get_metric_type(cls, metric_type: str) -> "MetricType":
|
|
40
|
+
"""
|
|
41
|
+
Converts a string representation of a metric type to its corresponding `MetricType` enum.
|
|
42
|
+
The method performs a case-insensitive lookup. If the provided metric type does not exist
|
|
43
|
+
in the `MetricType` enum, a `QwakCommandException` is raised.
|
|
44
|
+
|
|
45
|
+
:param metric_type: The name of the metric type to retrieve.
|
|
46
|
+
:return: The corresponding `MetricType` enum.
|
|
47
|
+
:raises: QwakCommandException if the provided `metric_type` does not match any member
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
return cls[metric_type.lower()]
|
|
52
|
+
except KeyError as exception:
|
|
53
|
+
raise QwakCommandException(
|
|
54
|
+
f"The metric type {metric_type} doesn't exist"
|
|
55
|
+
) from exception
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class AggregationType(Enum):
|
|
59
|
+
avg = AGGREGATION_TYPE_AVERAGE
|
|
60
|
+
max = AGGREGATION_TYPE_MAX
|
|
61
|
+
min = AGGREGATION_TYPE_MIN
|
|
62
|
+
sum = AGGREGATION_TYPE_SUM
|
|
63
|
+
p50 = AGGREGATION_TYPE_P50
|
|
64
|
+
p90 = AGGREGATION_TYPE_P90
|
|
65
|
+
p95 = AGGREGATION_TYPE_P95
|
|
66
|
+
p99 = AGGREGATION_TYPE_P99
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_aggregation_type(cls, aggregation_type: str) -> "AggregationType":
|
|
70
|
+
"""
|
|
71
|
+
Converts a string representation of an aggregation type to its corresponding `AggregationType` enum.
|
|
72
|
+
The method performs a case-insensitive lookup. If the provided aggregation type does not exist
|
|
73
|
+
in the `AggregationType` enum, a `QwakCommandException` is raised.
|
|
74
|
+
|
|
75
|
+
:param aggregation_type: The name of the aggregation type to retrieve
|
|
76
|
+
:return: The corresponding `AggregationType` enum.
|
|
77
|
+
:raises: QwakCommandException if the provided `aggregation_type` does not match
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
return cls[aggregation_type.lower()]
|
|
81
|
+
except KeyError as exception:
|
|
82
|
+
raise QwakCommandException(
|
|
83
|
+
f"The aggregation type {aggregation_type} doesn't exist"
|
|
84
|
+
) from exception
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class AutoScaling:
|
|
89
|
+
@dataclass
|
|
90
|
+
class Triggers:
|
|
91
|
+
@dataclass
|
|
92
|
+
class PrometheusTrigger:
|
|
93
|
+
@dataclass
|
|
94
|
+
class QuerySpec:
|
|
95
|
+
metric_type: str = field(default=None)
|
|
96
|
+
aggregation_type: str = field(default=None)
|
|
97
|
+
time_period: int = field(default=None)
|
|
98
|
+
error_code: str = field(default=None)
|
|
99
|
+
|
|
100
|
+
query_spec: QuerySpec = field(default=QuerySpec)
|
|
101
|
+
threshold: int = field(default=None)
|
|
102
|
+
|
|
103
|
+
prometheus_trigger: List[PrometheusTrigger] = field(default_factory=list)
|
|
104
|
+
|
|
105
|
+
min_replica_count: int = field(default=None)
|
|
106
|
+
max_replica_count: int = field(default=None)
|
|
107
|
+
polling_interval: int = field(default=None)
|
|
108
|
+
cool_down_period: int = field(default=None)
|
|
109
|
+
triggers: Triggers = field(default_factory=Triggers)
|
|
110
|
+
|
|
111
|
+
def to_autoscaling_api(self) -> AutoScalingConfig:
|
|
112
|
+
triggers = Triggers()
|
|
113
|
+
for trigger in self.triggers.prometheus_trigger:
|
|
114
|
+
metric_type: MetricType = MetricType.get_metric_type(
|
|
115
|
+
trigger.query_spec.metric_type
|
|
116
|
+
)
|
|
117
|
+
aggregation_type: AggregationType = AggregationType.get_aggregation_type(
|
|
118
|
+
trigger.query_spec.aggregation_type
|
|
119
|
+
)
|
|
120
|
+
triggers.triggers.append(
|
|
121
|
+
Trigger(
|
|
122
|
+
prometheus_trigger=PrometheusTrigger(
|
|
123
|
+
query_spec=QuerySpec(
|
|
124
|
+
metric_type=metric_type.value,
|
|
125
|
+
aggregation_type=aggregation_type.value,
|
|
126
|
+
time_period=trigger.query_spec.time_period,
|
|
127
|
+
error_code=trigger.query_spec.error_code,
|
|
128
|
+
),
|
|
129
|
+
threshold=trigger.threshold,
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
return AutoScalingConfig(
|
|
134
|
+
min_replica_count=self.min_replica_count,
|
|
135
|
+
max_replica_count=self.max_replica_count,
|
|
136
|
+
polling_interval=self.polling_interval,
|
|
137
|
+
cool_down_period=self.cool_down_period,
|
|
138
|
+
triggers=triggers,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@dataclass
|
|
143
|
+
class Spec:
|
|
144
|
+
model_id: str = field(default="")
|
|
145
|
+
variation_name: str = field(default="")
|
|
146
|
+
auto_scaling: AutoScaling = field(default=AutoScaling)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@dataclass
|
|
150
|
+
class Config:
|
|
151
|
+
spec: Spec = field(default=Spec)
|
|
152
|
+
api_version: str = field(default="v1")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional, Union
|
|
3
|
+
|
|
4
|
+
import yaml
|
|
5
|
+
|
|
6
|
+
from qwak_sdk.commands.auto_scalling._logic.config import Config
|
|
7
|
+
from qwak_sdk.inner.tools.dataclasses_utils import create_dataclass_instance
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_autoscaling_from_yaml(file_path: Optional[Union[Path, str]] = None) -> Config:
|
|
11
|
+
if file_path:
|
|
12
|
+
file_obj = Path(file_path)
|
|
13
|
+
if file_obj.exists():
|
|
14
|
+
autoscaling_dict = yaml.safe_load(file_obj.open("r"))
|
|
15
|
+
return create_dataclass_instance(Config, autoscaling_dict)
|
|
16
|
+
else:
|
|
17
|
+
raise FileNotFoundError(
|
|
18
|
+
f"autoscaling file {file_obj} definition isn't found"
|
|
19
|
+
)
|
|
20
|
+
else:
|
|
21
|
+
return Config()
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
import grpc
|
|
4
|
+
from qwak.clients.autoscaling import AutoScalingClient
|
|
5
|
+
|
|
6
|
+
from qwak_sdk.commands.auto_scalling._logic.config import Config
|
|
7
|
+
from qwak_sdk.commands.auto_scalling._logic.config.parser import (
|
|
8
|
+
parse_autoscaling_from_yaml,
|
|
9
|
+
)
|
|
10
|
+
from qwak_sdk.exceptions import QwakCommandException
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def attach_autoscaling(model_id: str, variation_name: str, file: str) -> Dict[str, str]:
|
|
14
|
+
try:
|
|
15
|
+
config = parse_autoscaling_from_yaml(file)
|
|
16
|
+
config = merge_kw_yaml(
|
|
17
|
+
config=config, model_id=model_id, variation_name=variation_name
|
|
18
|
+
)
|
|
19
|
+
response = AutoScalingClient().attach_autoscaling(
|
|
20
|
+
model_id=config.spec.model_id,
|
|
21
|
+
variation_name=config.spec.variation_name,
|
|
22
|
+
auto_scaling_config=config.spec.auto_scaling.to_autoscaling_api(),
|
|
23
|
+
)
|
|
24
|
+
return {
|
|
25
|
+
"autoscaling_id": response.auto_scaling_id,
|
|
26
|
+
"model_id": config.spec.model_id,
|
|
27
|
+
"variation_name": config.spec.variation_name,
|
|
28
|
+
}
|
|
29
|
+
except grpc.RpcError as e:
|
|
30
|
+
raise QwakCommandException(e.args[0].details)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def merge_kw_yaml(
|
|
34
|
+
config: Config,
|
|
35
|
+
model_id: str = "",
|
|
36
|
+
variation_name: str = "",
|
|
37
|
+
) -> Config:
|
|
38
|
+
if model_id:
|
|
39
|
+
config.spec.model_id = model_id
|
|
40
|
+
if variation_name:
|
|
41
|
+
config.spec.variation_name = variation_name
|
|
42
|
+
|
|
43
|
+
return config
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from qwak_sdk.commands.auto_scalling.attach._logic import attach_autoscaling
|
|
4
|
+
from qwak_sdk.exceptions import QwakCommandException
|
|
5
|
+
from qwak_sdk.inner.tools.cli_tools import QwakCommand
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command("attach", cls=QwakCommand)
|
|
9
|
+
@click.option("-m", "--model-id", required=False, help="Model named ID")
|
|
10
|
+
@click.option("-v", "--variation-name", required=False, help="Model variation name")
|
|
11
|
+
@click.option("-f", "--file", required=True, type=click.Path(exists=True))
|
|
12
|
+
def attach(model_id: str, variation_name: str, file: str, **kwargs):
|
|
13
|
+
click.echo("Attaching autoscaling configuration")
|
|
14
|
+
try:
|
|
15
|
+
response = attach_autoscaling(model_id, variation_name, file)
|
|
16
|
+
click.echo(
|
|
17
|
+
f"Successfully configured autoscaling. model: {response['model_id']}, variation: {response['variation_name']}"
|
|
18
|
+
)
|
|
19
|
+
except QwakCommandException as e:
|
|
20
|
+
click.echo(f"Failed to attach autoscaling, Error: {e}")
|
|
21
|
+
exit(1)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from qwak_sdk.commands.auto_scalling.attach.ui import attach
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@click.group(
|
|
7
|
+
name="autoscaling",
|
|
8
|
+
help="Manage autoscaling",
|
|
9
|
+
)
|
|
10
|
+
def autoscaling_commands_group():
|
|
11
|
+
# Click commands group injection
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
autoscaling_commands_group.add_command(attach)
|
|
File without changes
|