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,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,3 @@
1
+ from .config import Config
2
+
3
+ __all__ = ["Config"]
@@ -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