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.
Files changed (328) hide show
  1. qwak_sdk/__init__.py +9 -0
  2. qwak_sdk/cli.py +79 -0
  3. qwak_sdk/commands/__init__.py +0 -0
  4. qwak_sdk/commands/_logic/__init__.py +0 -0
  5. qwak_sdk/commands/_logic/tools.py +6 -0
  6. qwak_sdk/commands/admin/__init__.py +0 -0
  7. qwak_sdk/commands/admin/admin_commands_group.py +17 -0
  8. qwak_sdk/commands/admin/apikeys/__init__.py +0 -0
  9. qwak_sdk/commands/admin/apikeys/api_keys_commands_group.py +17 -0
  10. qwak_sdk/commands/admin/apikeys/generate/__init__.py +0 -0
  11. qwak_sdk/commands/admin/apikeys/generate/_logic.py +21 -0
  12. qwak_sdk/commands/admin/apikeys/generate/ui.py +45 -0
  13. qwak_sdk/commands/admin/apikeys/revoke/__init__.py +0 -0
  14. qwak_sdk/commands/admin/apikeys/revoke/_logic.py +22 -0
  15. qwak_sdk/commands/admin/apikeys/revoke/ui.py +31 -0
  16. qwak_sdk/commands/alerts/__init__.py +0 -0
  17. qwak_sdk/commands/alerts/alerts_commnad_group.py +18 -0
  18. qwak_sdk/commands/alerts/delete/__init__.py +0 -0
  19. qwak_sdk/commands/alerts/delete/_logic.py +5 -0
  20. qwak_sdk/commands/alerts/delete/ui.py +10 -0
  21. qwak_sdk/commands/alerts/list/__init__.py +0 -0
  22. qwak_sdk/commands/alerts/list/_logic.py +23 -0
  23. qwak_sdk/commands/alerts/list/ui.py +17 -0
  24. qwak_sdk/commands/alerts/register/__init__.py +0 -0
  25. qwak_sdk/commands/alerts/register/_logic.py +72 -0
  26. qwak_sdk/commands/alerts/register/ui.py +30 -0
  27. qwak_sdk/commands/audience/__init__.py +0 -0
  28. qwak_sdk/commands/audience/_logic/__init__.py +0 -0
  29. qwak_sdk/commands/audience/_logic/config/__init__.py +0 -0
  30. qwak_sdk/commands/audience/_logic/config/config_base.py +15 -0
  31. qwak_sdk/commands/audience/_logic/config/parser.py +30 -0
  32. qwak_sdk/commands/audience/_logic/config/v1/__init__.py +0 -0
  33. qwak_sdk/commands/audience/_logic/config/v1/audience_config.py +26 -0
  34. qwak_sdk/commands/audience/_logic/config/v1/conditions_config.py +59 -0
  35. qwak_sdk/commands/audience/_logic/config/v1/config_v1.py +23 -0
  36. qwak_sdk/commands/audience/_logic/config/v1/route_config.py +15 -0
  37. qwak_sdk/commands/audience/_logic/config/v1/spec.py +9 -0
  38. qwak_sdk/commands/audience/audience_api_dump.py +86 -0
  39. qwak_sdk/commands/audience/audience_commands_group.py +30 -0
  40. qwak_sdk/commands/audience/create/__init__.py +0 -0
  41. qwak_sdk/commands/audience/create/logic.py +41 -0
  42. qwak_sdk/commands/audience/create/ui.py +21 -0
  43. qwak_sdk/commands/audience/delete/__init__.py +0 -0
  44. qwak_sdk/commands/audience/delete/logic.py +13 -0
  45. qwak_sdk/commands/audience/delete/ui.py +17 -0
  46. qwak_sdk/commands/audience/get/__init__.py +0 -0
  47. qwak_sdk/commands/audience/get/logic.py +14 -0
  48. qwak_sdk/commands/audience/get/ui.py +25 -0
  49. qwak_sdk/commands/audience/list/__init__.py +0 -0
  50. qwak_sdk/commands/audience/list/logic.py +16 -0
  51. qwak_sdk/commands/audience/list/ui.py +26 -0
  52. qwak_sdk/commands/audience/update/__init__.py +0 -0
  53. qwak_sdk/commands/audience/update/logic.py +37 -0
  54. qwak_sdk/commands/audience/update/ui.py +26 -0
  55. qwak_sdk/commands/auto_scalling/__init__.py +0 -0
  56. qwak_sdk/commands/auto_scalling/_logic/__init__.py +0 -0
  57. qwak_sdk/commands/auto_scalling/_logic/config/__init__.py +3 -0
  58. qwak_sdk/commands/auto_scalling/_logic/config/config.py +152 -0
  59. qwak_sdk/commands/auto_scalling/_logic/config/parser.py +21 -0
  60. qwak_sdk/commands/auto_scalling/attach/__init__.py +0 -0
  61. qwak_sdk/commands/auto_scalling/attach/_logic.py +43 -0
  62. qwak_sdk/commands/auto_scalling/attach/ui.py +21 -0
  63. qwak_sdk/commands/auto_scalling/autoscaling_commands_group.py +15 -0
  64. qwak_sdk/commands/automations/__init__.py +0 -0
  65. qwak_sdk/commands/automations/automations_commands_group.py +30 -0
  66. qwak_sdk/commands/automations/delete/__init__.py +0 -0
  67. qwak_sdk/commands/automations/delete/_logic.py +6 -0
  68. qwak_sdk/commands/automations/delete/ui.py +23 -0
  69. qwak_sdk/commands/automations/executions/__init__.py +0 -0
  70. qwak_sdk/commands/automations/executions/executions_commands_group.py +14 -0
  71. qwak_sdk/commands/automations/executions/list/__init__.py +0 -0
  72. qwak_sdk/commands/automations/executions/list/_logic.py +8 -0
  73. qwak_sdk/commands/automations/executions/list/ui.py +25 -0
  74. qwak_sdk/commands/automations/list/__init__.py +0 -0
  75. qwak_sdk/commands/automations/list/_logic.py +36 -0
  76. qwak_sdk/commands/automations/list/ui.py +21 -0
  77. qwak_sdk/commands/automations/register/__init__.py +0 -0
  78. qwak_sdk/commands/automations/register/_logic.py +43 -0
  79. qwak_sdk/commands/automations/register/ui.py +44 -0
  80. qwak_sdk/commands/feature_store/__init__.py +0 -0
  81. qwak_sdk/commands/feature_store/backfill/__init__.py +0 -0
  82. qwak_sdk/commands/feature_store/backfill/_logic.py +140 -0
  83. qwak_sdk/commands/feature_store/backfill/streaming/__init__.py +0 -0
  84. qwak_sdk/commands/feature_store/backfill/streaming/_logic.py +50 -0
  85. qwak_sdk/commands/feature_store/backfill/streaming/ui.py +67 -0
  86. qwak_sdk/commands/feature_store/backfill/ui.py +146 -0
  87. qwak_sdk/commands/feature_store/delete/__init__.py +0 -0
  88. qwak_sdk/commands/feature_store/delete/_logic.py +104 -0
  89. qwak_sdk/commands/feature_store/delete/ui.py +40 -0
  90. qwak_sdk/commands/feature_store/execution/__init__.py +0 -0
  91. qwak_sdk/commands/feature_store/execution/ui.py +19 -0
  92. qwak_sdk/commands/feature_store/feature_store_command_group.py +29 -0
  93. qwak_sdk/commands/feature_store/list/__init__.py +0 -0
  94. qwak_sdk/commands/feature_store/list/ui.py +140 -0
  95. qwak_sdk/commands/feature_store/pause/__init__.py +0 -0
  96. qwak_sdk/commands/feature_store/pause/ui.py +18 -0
  97. qwak_sdk/commands/feature_store/register/__init__.py +0 -0
  98. qwak_sdk/commands/feature_store/register/_logic.py +367 -0
  99. qwak_sdk/commands/feature_store/register/ui.py +111 -0
  100. qwak_sdk/commands/feature_store/resume/__init__.py +0 -0
  101. qwak_sdk/commands/feature_store/resume/ui.py +18 -0
  102. qwak_sdk/commands/feature_store/trigger/__init__.py +0 -0
  103. qwak_sdk/commands/feature_store/trigger/ui.py +39 -0
  104. qwak_sdk/commands/models/__init__.py +0 -0
  105. qwak_sdk/commands/models/build/__init__.py +0 -0
  106. qwak_sdk/commands/models/build/_logic/__init__.py +0 -0
  107. qwak_sdk/commands/models/build/_logic/build_steps.py +42 -0
  108. qwak_sdk/commands/models/build/_logic/client_logs/__init__.py +0 -0
  109. qwak_sdk/commands/models/build/_logic/client_logs/cli_phase_run_handler.py +123 -0
  110. qwak_sdk/commands/models/build/_logic/client_logs/cli_trigger_build_logger.py +19 -0
  111. qwak_sdk/commands/models/build/_logic/client_logs/logger.py +88 -0
  112. qwak_sdk/commands/models/build/_logic/client_logs/messages.py +36 -0
  113. qwak_sdk/commands/models/build/_logic/client_logs/spinner.py +14 -0
  114. qwak_sdk/commands/models/build/_logic/client_logs/trigger_build_logger.py +54 -0
  115. qwak_sdk/commands/models/build/_logic/client_logs/utils.py +12 -0
  116. qwak_sdk/commands/models/build/_logic/phase/__init__.py +0 -0
  117. qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/__init__.py +20 -0
  118. qwak_sdk/commands/models/build/_logic/phase/a_fetch_model_code/get_sdk_version_step.py +14 -0
  119. qwak_sdk/commands/models/build/_logic/phase/b_remote_register_qwak_build/__init__.py +16 -0
  120. qwak_sdk/commands/models/build/_logic/phase/c_deploy/__init__.py +6 -0
  121. qwak_sdk/commands/models/build/_logic/phase/c_deploy/build_polling_status.py +55 -0
  122. qwak_sdk/commands/models/build/_logic/phase/c_deploy/deploy_build.py +61 -0
  123. qwak_sdk/commands/models/build/_logic/util/__init__.py +0 -0
  124. qwak_sdk/commands/models/build/_logic/util/protobuf_factory.py +45 -0
  125. qwak_sdk/commands/models/build/_logic/util/step_decorator.py +60 -0
  126. qwak_sdk/commands/models/build/_logic/util/text.py +9 -0
  127. qwak_sdk/commands/models/build/_logic/wait_until_finished.py +27 -0
  128. qwak_sdk/commands/models/build/ui.py +337 -0
  129. qwak_sdk/commands/models/builds/__init__.py +0 -0
  130. qwak_sdk/commands/models/builds/builds_commands_group.py +16 -0
  131. qwak_sdk/commands/models/builds/cancel/__init__.py +0 -0
  132. qwak_sdk/commands/models/builds/cancel/_logic.py +5 -0
  133. qwak_sdk/commands/models/builds/cancel/ui.py +15 -0
  134. qwak_sdk/commands/models/builds/logs/__init__.py +0 -0
  135. qwak_sdk/commands/models/builds/logs/ui.py +35 -0
  136. qwak_sdk/commands/models/builds/status/__init__.py +0 -0
  137. qwak_sdk/commands/models/builds/status/_logic.py +6 -0
  138. qwak_sdk/commands/models/builds/status/ui.py +39 -0
  139. qwak_sdk/commands/models/create/__init__.py +0 -0
  140. qwak_sdk/commands/models/create/_logic.py +36 -0
  141. qwak_sdk/commands/models/create/ui.py +43 -0
  142. qwak_sdk/commands/models/delete/__init__.py +0 -0
  143. qwak_sdk/commands/models/delete/_logic.py +5 -0
  144. qwak_sdk/commands/models/delete/ui.py +25 -0
  145. qwak_sdk/commands/models/deployments/__init__.py +0 -0
  146. qwak_sdk/commands/models/deployments/deploy/__init__.py +0 -0
  147. qwak_sdk/commands/models/deployments/deploy/_logic/__init__.py +0 -0
  148. qwak_sdk/commands/models/deployments/deploy/_logic/advance_deployment_options_handler.py +31 -0
  149. qwak_sdk/commands/models/deployments/deploy/_logic/base_deploy_executor.py +68 -0
  150. qwak_sdk/commands/models/deployments/deploy/_logic/deploy_config.py +261 -0
  151. qwak_sdk/commands/models/deployments/deploy/_logic/deployment.py +405 -0
  152. qwak_sdk/commands/models/deployments/deploy/_logic/deployment_message_helpers.py +114 -0
  153. qwak_sdk/commands/models/deployments/deploy/_logic/deployment_response_handler.py +156 -0
  154. qwak_sdk/commands/models/deployments/deploy/_logic/deployment_size_mapper.py +96 -0
  155. qwak_sdk/commands/models/deployments/deploy/_logic/get_latest_successful_build.py +28 -0
  156. qwak_sdk/commands/models/deployments/deploy/_logic/local_deployment.py +193 -0
  157. qwak_sdk/commands/models/deployments/deploy/batch/__init__.py +0 -0
  158. qwak_sdk/commands/models/deployments/deploy/batch/_logic/__init__.py +0 -0
  159. qwak_sdk/commands/models/deployments/deploy/batch/_logic/advanced_deployment_mapper.py +15 -0
  160. qwak_sdk/commands/models/deployments/deploy/batch/_logic/deploy_executor.py +24 -0
  161. qwak_sdk/commands/models/deployments/deploy/batch/ui.py +126 -0
  162. qwak_sdk/commands/models/deployments/deploy/deploy_commands_group.py +19 -0
  163. qwak_sdk/commands/models/deployments/deploy/realtime/__init__.py +0 -0
  164. qwak_sdk/commands/models/deployments/deploy/realtime/_logic/__init__.py +0 -0
  165. qwak_sdk/commands/models/deployments/deploy/realtime/_logic/advanced_deployment_mapper.py +21 -0
  166. qwak_sdk/commands/models/deployments/deploy/realtime/_logic/deploy_executor.py +24 -0
  167. qwak_sdk/commands/models/deployments/deploy/realtime/_logic/serving_strategy_mapper.py +75 -0
  168. qwak_sdk/commands/models/deployments/deploy/realtime/ui.py +209 -0
  169. qwak_sdk/commands/models/deployments/deploy/streaming/__init__.py +0 -0
  170. qwak_sdk/commands/models/deployments/deploy/streaming/_logic/__init__.py +0 -0
  171. qwak_sdk/commands/models/deployments/deploy/streaming/_logic/deploy_executor.py +24 -0
  172. qwak_sdk/commands/models/deployments/deploy/streaming/_logic/serving_strategy_mapper.py +38 -0
  173. qwak_sdk/commands/models/deployments/deploy/streaming/ui.py +213 -0
  174. qwak_sdk/commands/models/deployments/undeploy/__init__.py +0 -0
  175. qwak_sdk/commands/models/deployments/undeploy/_logic/__init__.py +0 -0
  176. qwak_sdk/commands/models/deployments/undeploy/_logic/request_undeploy.py +249 -0
  177. qwak_sdk/commands/models/deployments/undeploy/ui.py +72 -0
  178. qwak_sdk/commands/models/describe/__init__.py +0 -0
  179. qwak_sdk/commands/models/describe/_logic.py +169 -0
  180. qwak_sdk/commands/models/describe/ui.py +35 -0
  181. qwak_sdk/commands/models/executions/__init__.py +0 -0
  182. qwak_sdk/commands/models/executions/cancel/__init__.py +0 -0
  183. qwak_sdk/commands/models/executions/cancel/_logic.py +9 -0
  184. qwak_sdk/commands/models/executions/cancel/ui.py +27 -0
  185. qwak_sdk/commands/models/executions/execution_commands_group.py +24 -0
  186. qwak_sdk/commands/models/executions/report/__init__.py +0 -0
  187. qwak_sdk/commands/models/executions/report/_logic.py +14 -0
  188. qwak_sdk/commands/models/executions/report/ui.py +43 -0
  189. qwak_sdk/commands/models/executions/start/__init__.py +0 -0
  190. qwak_sdk/commands/models/executions/start/_logic.py +81 -0
  191. qwak_sdk/commands/models/executions/start/ui.py +208 -0
  192. qwak_sdk/commands/models/executions/status/__init__.py +0 -0
  193. qwak_sdk/commands/models/executions/status/_logic.py +13 -0
  194. qwak_sdk/commands/models/executions/status/ui.py +27 -0
  195. qwak_sdk/commands/models/init/__init__.py +0 -0
  196. qwak_sdk/commands/models/init/_logic/__init__.py +0 -0
  197. qwak_sdk/commands/models/init/_logic/initialize_model_structure.py +40 -0
  198. qwak_sdk/commands/models/init/_logic/template/__init__.py +0 -0
  199. qwak_sdk/commands/models/init/_logic/template/churn/__init__.py +0 -0
  200. qwak_sdk/commands/models/init/_logic/template/churn/cookiecutter.json +3 -0
  201. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/__init__.py +0 -0
  202. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  203. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/conda.yml +10 -0
  204. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
  205. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/main/model.py +95 -0
  206. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
  207. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
  208. qwak_sdk/commands/models/init/_logic/template/churn/{{cookiecutter.model_directory}}/tests/it/test_churn.py +32 -0
  209. qwak_sdk/commands/models/init/_logic/template/credit_risk/__init__.py +0 -0
  210. qwak_sdk/commands/models/init/_logic/template/credit_risk/cookiecutter.json +3 -0
  211. qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/__init__.py +0 -0
  212. qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  213. qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/conda.yml +11 -0
  214. qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/data.csv +1001 -0
  215. qwak_sdk/commands/models/init/_logic/template/credit_risk/{{cookiecutter.model_directory}}/main/model.py +108 -0
  216. qwak_sdk/commands/models/init/_logic/template/general/__init__.py +0 -0
  217. qwak_sdk/commands/models/init/_logic/template/general/cookiecutter.json +6 -0
  218. qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/__init__.py +0 -0
  219. qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/__init__.py +5 -0
  220. qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/conda.yml +8 -0
  221. qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.main_directory}}/model.py +66 -0
  222. qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/__init__.py +0 -0
  223. qwak_sdk/commands/models/init/_logic/template/general/{{cookiecutter.model_directory}}/{{cookiecutter.test_directory}}/test_qwak_model.py +5 -0
  224. qwak_sdk/commands/models/init/_logic/template/titanic/__init__.py +0 -0
  225. qwak_sdk/commands/models/init/_logic/template/titanic/cookiecutter.json +3 -0
  226. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/__init__.py +0 -0
  227. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  228. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/conda.yml +11 -0
  229. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/main/model.py +98 -0
  230. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
  231. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
  232. qwak_sdk/commands/models/init/_logic/template/titanic/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +24 -0
  233. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/__init__.py +0 -0
  234. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/cookiecutter.json +3 -0
  235. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/__init__.py +0 -0
  236. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/__init__.py +5 -0
  237. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/model.py +98 -0
  238. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/main/pyproject.toml +20 -0
  239. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/__init__.py +0 -0
  240. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/__init__.py +0 -0
  241. qwak_sdk/commands/models/init/_logic/template/titanic_poetry/{{cookiecutter.model_directory}}/tests/it/test_titanic.py +25 -0
  242. qwak_sdk/commands/models/init/ui.py +61 -0
  243. qwak_sdk/commands/models/list/__init__.py +0 -0
  244. qwak_sdk/commands/models/list/_logic.py +5 -0
  245. qwak_sdk/commands/models/list/ui.py +40 -0
  246. qwak_sdk/commands/models/list_models/__init__.py +0 -0
  247. qwak_sdk/commands/models/list_models/_logic.py +5 -0
  248. qwak_sdk/commands/models/list_models/ui.py +60 -0
  249. qwak_sdk/commands/models/metadata/__init__.py +0 -0
  250. qwak_sdk/commands/models/metadata/_logic.py +5 -0
  251. qwak_sdk/commands/models/metadata/ui.py +60 -0
  252. qwak_sdk/commands/models/models_command_group.py +44 -0
  253. qwak_sdk/commands/models/runtime/__init__.py +0 -0
  254. qwak_sdk/commands/models/runtime/logs/__init__.py +0 -0
  255. qwak_sdk/commands/models/runtime/logs/ui.py +63 -0
  256. qwak_sdk/commands/models/runtime/runtime_commands_group.py +17 -0
  257. qwak_sdk/commands/models/runtime/update/__init__.py +0 -0
  258. qwak_sdk/commands/models/runtime/update/_logic.py +9 -0
  259. qwak_sdk/commands/models/runtime/update/ui.py +15 -0
  260. qwak_sdk/commands/projects/__init__.py +0 -0
  261. qwak_sdk/commands/projects/create/__init__.py +0 -0
  262. qwak_sdk/commands/projects/create/_logic.py +9 -0
  263. qwak_sdk/commands/projects/create/ui.py +68 -0
  264. qwak_sdk/commands/projects/delete/__init__.py +0 -0
  265. qwak_sdk/commands/projects/delete/_logic.py +6 -0
  266. qwak_sdk/commands/projects/delete/ui.py +24 -0
  267. qwak_sdk/commands/projects/list/__init__.py +0 -0
  268. qwak_sdk/commands/projects/list/_logic.py +6 -0
  269. qwak_sdk/commands/projects/list/ui.py +45 -0
  270. qwak_sdk/commands/projects/projects_command_group.py +19 -0
  271. qwak_sdk/commands/secrets/__init__.py +0 -0
  272. qwak_sdk/commands/secrets/delete/__init__.py +0 -0
  273. qwak_sdk/commands/secrets/delete/_logic.py +5 -0
  274. qwak_sdk/commands/secrets/delete/ui.py +21 -0
  275. qwak_sdk/commands/secrets/get/__init__.py +0 -0
  276. qwak_sdk/commands/secrets/get/_logic.py +5 -0
  277. qwak_sdk/commands/secrets/get/ui.py +17 -0
  278. qwak_sdk/commands/secrets/secrets_commands_group.py +19 -0
  279. qwak_sdk/commands/secrets/set/__init__.py +0 -0
  280. qwak_sdk/commands/secrets/set/_logic.py +5 -0
  281. qwak_sdk/commands/secrets/set/ui.py +16 -0
  282. qwak_sdk/commands/ui_tools.py +18 -0
  283. qwak_sdk/commands/workspaces/__init__.py +0 -0
  284. qwak_sdk/commands/workspaces/_logic/__init__.py +0 -0
  285. qwak_sdk/commands/workspaces/_logic/tools.py +44 -0
  286. qwak_sdk/commands/workspaces/_logic/workspace_validations.py +41 -0
  287. qwak_sdk/commands/workspaces/config/__init__.py +0 -0
  288. qwak_sdk/commands/workspaces/config/workspace_config.py +35 -0
  289. qwak_sdk/commands/workspaces/create/__init__.py +0 -0
  290. qwak_sdk/commands/workspaces/create/_logic.py +54 -0
  291. qwak_sdk/commands/workspaces/create/ui.py +48 -0
  292. qwak_sdk/commands/workspaces/delete/__init__.py +0 -0
  293. qwak_sdk/commands/workspaces/delete/_logic.py +30 -0
  294. qwak_sdk/commands/workspaces/delete/ui.py +23 -0
  295. qwak_sdk/commands/workspaces/start/__init__.py +0 -0
  296. qwak_sdk/commands/workspaces/start/_logic.py +30 -0
  297. qwak_sdk/commands/workspaces/start/ui.py +23 -0
  298. qwak_sdk/commands/workspaces/stop/__init__.py +0 -0
  299. qwak_sdk/commands/workspaces/stop/_logic.py +30 -0
  300. qwak_sdk/commands/workspaces/stop/ui.py +23 -0
  301. qwak_sdk/commands/workspaces/update/__init__.py +0 -0
  302. qwak_sdk/commands/workspaces/update/_logic.py +82 -0
  303. qwak_sdk/commands/workspaces/update/ui.py +57 -0
  304. qwak_sdk/commands/workspaces/workspaces_commands_group.py +23 -0
  305. qwak_sdk/exceptions/__init__.py +11 -0
  306. qwak_sdk/exceptions/qwak_command_exception.py +2 -0
  307. qwak_sdk/exceptions/qwak_deploy_new_build_failed.py +5 -0
  308. qwak_sdk/exceptions/qwak_resource_not_found.py +2 -0
  309. qwak_sdk/inner/__init__.py +0 -0
  310. qwak_sdk/inner/file_registry.py +98 -0
  311. qwak_sdk/inner/tools/__init__.py +0 -0
  312. qwak_sdk/inner/tools/cli_tools.py +220 -0
  313. qwak_sdk/inner/tools/config_handler.py +27 -0
  314. qwak_sdk/inner/tools/dataclasses_utils.py +21 -0
  315. qwak_sdk/inner/tools/logger/__init__.py +3 -0
  316. qwak_sdk/inner/tools/logger/logger.py +269 -0
  317. qwak_sdk/inner/tools/logger/logging.yml +79 -0
  318. qwak_sdk/inner/tools/tracking.py +47 -0
  319. qwak_sdk/main.py +9 -0
  320. qwak_sdk/tools/__init__.py +0 -0
  321. qwak_sdk/tools/colors.py +13 -0
  322. qwak_sdk/tools/files.py +63 -0
  323. qwak_sdk/tools/log_handling.py +159 -0
  324. qwak_sdk/tools/utils.py +42 -0
  325. qwak_sdk-0.5.102.dist-info/METADATA +51 -0
  326. qwak_sdk-0.5.102.dist-info/RECORD +328 -0
  327. qwak_sdk-0.5.102.dist-info/WHEEL +4 -0
  328. qwak_sdk-0.5.102.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,123 @@
1
+ from contextlib import contextmanager
2
+ from logging import Logger
3
+ from pathlib import Path
4
+
5
+ from qwak.inner.build_logic.interface.build_phase import BuildPhase
6
+ from qwak.inner.build_logic.interface.phase_run_handler import PhaseRunHandler
7
+ from qwak.inner.build_logic.phases.phases_pipeline import PhasesPipeline
8
+ from yaspin import yaspin
9
+
10
+ from qwak_sdk.tools.colors import Color
11
+ from .cli_trigger_build_logger import CliTriggerBuildLogger
12
+ from .messages import (
13
+ FAILED_CONTACT_QWAK_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_QWAK_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 qwak.inner.build_logic.build_loggers.trigger_build_logger import TriggerBuildLogger
4
+ from qwak.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 qwak.inner.build_config.build_config_v1 import BuildConfigV1
11
+ from qwak.inner.build_logic.constants.host_resource import HOST_QWAK_HIDDEN_FOLDER
12
+
13
+ from qwak_sdk import __version__ as qwak_sdk_version
14
+ from qwak_sdk.inner.tools.logger import setup_qwak_logger
15
+ from qwak_sdk.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_qwak_logger,
23
+ non_qwak_logger_enabled,
24
+ set_file_handler_log_file,
25
+ set_handler_verbosity,
26
+ )
27
+
28
+ BUILDS_LOGS = HOST_QWAK_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_qwak_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_qwak_logger(fallback_logger_name=fallback_logger_name)
68
+
69
+ if not non_qwak_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
+ qwak 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_QWAK_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 qwak.inner.build_logic.interface.build_logger_interface import BuildLogger
5
+ from qwak.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)
@@ -0,0 +1,20 @@
1
+ from typing import List
2
+
3
+ from qwak.inner.build_logic.interface.step_inteface import Step
4
+ from qwak.inner.build_logic.phases.phase_010_fetch_model.fetch_model_step import FetchModelStep
5
+ from qwak.inner.build_logic.phases.phase_010_fetch_model.post_fetch_validation_step import PostFetchValidationStep
6
+ from qwak.inner.build_logic.phases.phase_010_fetch_model.pre_fetch_validation_step import PreFetchValidationStep
7
+
8
+ from qwak_sdk.commands.models.build._logic.phase.a_fetch_model_code.get_sdk_version_step import SdkVersionStep
9
+ from qwak_sdk.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,14 @@
1
+ from qwak.inner.build_logic.interface.step_inteface import Step
2
+
3
+ from qwak_sdk import __version__ as qwak_sdk_version
4
+
5
+
6
+ class SdkVersionStep(Step):
7
+ def description(self) -> str:
8
+ return "Getting SDK Version"
9
+
10
+ def execute(self) -> None:
11
+ self.build_logger.debug(
12
+ "Getting sdk version"
13
+ )
14
+ self.context.qwak_sdk_version = qwak_sdk_version
@@ -0,0 +1,16 @@
1
+ from qwak.inner.build_logic.phases.phase_020_remote_register_qwak_build.cleanup_step import CleanupStep
2
+ from qwak.inner.build_logic.phases.phase_020_remote_register_qwak_build.start_remote_build_step import \
3
+ StartRemoteBuildStep
4
+ from qwak.inner.build_logic.phases.phase_020_remote_register_qwak_build.upload_step import UploadStep
5
+
6
+ from ...util.step_decorator import add_decorator_to_steps
7
+
8
+
9
+ def get_remote_register_qwak_build_steps():
10
+ phase_steps = [
11
+ UploadStep(),
12
+ StartRemoteBuildStep(),
13
+ CleanupStep(),
14
+ ]
15
+
16
+ return add_decorator_to_steps(phase_steps)
@@ -0,0 +1,6 @@
1
+ from .build_polling_status import BuildPollingStatusStep
2
+ from .deploy_build import DeployBuildStep
3
+
4
+
5
+ def get_deploy_steps():
6
+ return [BuildPollingStatusStep(), DeployBuildStep()]
@@ -0,0 +1,55 @@
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.inner.build_logic.interface.step_inteface import Step
12
+ from qwak.exceptions 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.build_logger.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
+ 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 _qwak_proto.qwak.instance_template.instance_template_pb2 import (
6
+ InstanceTemplateSpec,
7
+ InstanceType,
8
+ )
9
+
10
+ from qwak_sdk.commands.models.build._logic.client_logs.messages import (
11
+ FAILED_DEPLOY_BUILD_SUGGESTION,
12
+ )
13
+ from qwak.inner.build_logic.interface.step_inteface import Step
14
+ from qwak_sdk.commands.models.deployments.deploy.realtime.ui import deploy_realtime
15
+ from qwak_sdk.exceptions.qwak_deploy_new_build_failed import (
16
+ QwakDeployNewBuildFailedException,
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 QwakDeployNewBuildFailedException(
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 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,60 @@
1
+ import os
2
+ import shutil
3
+ from functools import wraps
4
+ from typing import List
5
+
6
+ from qwak.exceptions import QuietError
7
+ from qwak.inner.build_logic.interface.build_logger_interface import BuildLogger
8
+ from qwak.inner.build_logic.interface.step_inteface import Step
9
+
10
+
11
+ def step_exception_handler_decorator(step: Step):
12
+ execute_func = step.execute
13
+
14
+ @wraps(execute_func)
15
+ def inner_function(*args, **kwargs):
16
+ try:
17
+ execute_func(*args, **kwargs)
18
+ except BaseException as e:
19
+ if not isinstance(e, QuietError):
20
+ build_logger: BuildLogger = step.build_logger
21
+ build_logger.error(
22
+ "Build failed with Exception. See the stack trace above."
23
+ )
24
+ cleaning_up_after_build(step)
25
+ raise e
26
+
27
+ return inner_function
28
+
29
+
30
+ def build_failure_handler():
31
+ def _exception_handler(func):
32
+ @wraps(func)
33
+ def inner_function(*args, **kwargs):
34
+ try:
35
+ func(*args, **kwargs)
36
+ except BaseException as e:
37
+ if not isinstance(e, QuietError):
38
+ build_logger: BuildLogger = args[0].build_logger
39
+ build_logger.error(
40
+ "Build failed with Exception. See the stack trace above."
41
+ )
42
+ cleaning_up_after_build(args[0])
43
+ raise e
44
+ return inner_function
45
+
46
+ return _exception_handler
47
+
48
+
49
+ def cleaning_up_after_build(step: Step):
50
+ if os.getenv("QWAK_DEBUG") != "true":
51
+ step.build_logger.debug("Removing Qwak temp artifacts directory")
52
+ shutil.rmtree(step.context.host_temp_local_build_dir, ignore_errors=True)
53
+
54
+
55
+ def add_decorator_to_steps(phase_steps: List[Step]):
56
+ for step in phase_steps:
57
+ if not hasattr(step.execute, '__wrapped__'):
58
+ step_exception_handler_decorator(step)
59
+
60
+ return phase_steps
@@ -0,0 +1,9 @@
1
+ from re import sub
2
+
3
+
4
+ def snake_case(s):
5
+ return "_".join(
6
+ sub(
7
+ "([A-Z][a-z]+)", r" \1", sub("([A-Z]+)", r" \1", s.replace("-", " "))
8
+ ).split()
9
+ ).lower()
@@ -0,0 +1,27 @@
1
+ from logging import Logger
2
+ import time
3
+ from typing import List
4
+ from _qwak_proto.qwak.build.v1.build_pb2 import BuildStatus
5
+ from qwak.clients.build_orchestrator import BuildOrchestratorClient
6
+
7
+
8
+ def __get_current_status(build_id) -> BuildStatus:
9
+ return BuildOrchestratorClient().get_build(build_id).build.build_status
10
+
11
+
12
+ def __end_state_statuses() -> List[BuildStatus.ValueType]:
13
+ return [BuildStatus.FAILED, BuildStatus.SUCCESSFUL, BuildStatus.REMOTE_BUILD_CANCELLED, BuildStatus.REMOTE_BUILD_TIMED_OUT, BuildStatus.FAILED_INITIATING_BUILD]
14
+
15
+
16
+ def wait_until_finished(build_id, log: Logger, pool_interval_seconds=10) -> None:
17
+ status = __get_current_status(build_id)
18
+ log.info(f"Waiting for build {build_id} to finish. Aborting this process will not stop the build!")
19
+ log.debug(f"Current status of build {build_id}: {BuildStatus.DESCRIPTOR.values_by_number[status].name}")
20
+ while status not in __end_state_statuses():
21
+ time.sleep(pool_interval_seconds)
22
+ status = __get_current_status(build_id)
23
+ log.debug(f"Current status of build {build_id}: {BuildStatus.DESCRIPTOR.values_by_number[status].name}")
24
+
25
+
26
+ def is_final_status_successful(build_id) -> bool:
27
+ return __get_current_status(build_id) == BuildStatus.SUCCESSFUL