thestage 0.6.8__tar.gz → 0.7.0__tar.gz

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 (225) hide show
  1. {thestage-0.6.8 → thestage-0.7.0}/PKG-INFO +1 -1
  2. {thestage-0.6.8 → thestage-0.7.0}/pyproject.toml +1 -1
  3. {thestage-0.6.8 → thestage-0.7.0}/thestage/__init__.py +1 -1
  4. {thestage-0.6.8 → thestage-0.7.0}/thestage/cli_command.py +3 -0
  5. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/business/container_service.py +121 -1
  6. thestage-0.7.0/thestage/docker_container/business/mapper/image_mapper.py +16 -0
  7. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/communication/docker_command.py +178 -9
  8. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/communication/docker_container_api_client.py +42 -2
  9. thestage-0.7.0/thestage/docker_container/communication/image_command.py +40 -0
  10. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/container_response.py +7 -0
  11. thestage-0.7.0/thestage/docker_container/dto/docker_container_create_request.py +28 -0
  12. thestage-0.7.0/thestage/docker_container/dto/docker_container_create_response.py +11 -0
  13. thestage-0.7.0/thestage/docker_container/dto/docker_image_list_request.py +11 -0
  14. thestage-0.7.0/thestage/docker_container/dto/docker_image_list_response.py +13 -0
  15. thestage-0.7.0/thestage/docker_container/dto/image_entity.py +14 -0
  16. {thestage-0.6.8 → thestage-0.7.0}/thestage/helpers/error_handler.py +1 -1
  17. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/business/inference_model_service.py +6 -6
  18. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/business/inference_simulator_service.py +3 -3
  19. {thestage-0.6.8 → thestage-0.7.0}/thestage/main.py +7 -0
  20. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/business/project_service.py +3 -3
  21. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/business/task_service.py +5 -2
  22. {thestage-0.6.8 → thestage-0.7.0}/LICENSE.txt +0 -0
  23. {thestage-0.6.8 → thestage-0.7.0}/README.md +0 -0
  24. {thestage-0.6.8 → thestage-0.7.0}/thestage/.env +0 -0
  25. {thestage-0.6.8 → thestage-0.7.0}/thestage/__main__.py +0 -0
  26. {thestage-0.6.8 → thestage-0.7.0}/thestage/cli_command_helper.py +0 -0
  27. {thestage-0.6.8 → thestage-0.7.0}/thestage/color_scheme/__init__.py +0 -0
  28. {thestage-0.6.8 → thestage-0.7.0}/thestage/color_scheme/color_scheme.py +0 -0
  29. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/__init__.py +0 -0
  30. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/business/__init__.py +0 -0
  31. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/business/app_config_service.py +0 -0
  32. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/business/config_provider.py +0 -0
  33. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/business/config_storage.py +0 -0
  34. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/business/validation_service.py +0 -0
  35. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/communication/__init__.py +0 -0
  36. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/communication/config_command.py +0 -0
  37. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/dto/__init__.py +0 -0
  38. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/dto/config_entity.py +0 -0
  39. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/dto/remote_server_config.py +0 -0
  40. {thestage-0.6.8 → thestage-0.7.0}/thestage/config/env_base.py +0 -0
  41. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/__init__.py +0 -0
  42. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/business/__init__.py +0 -0
  43. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/business/connect_service.py +0 -0
  44. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/business/remote_server_service.py +0 -0
  45. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/communication/__init__.py +0 -0
  46. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/communication/connect_api_client.py +0 -0
  47. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/__init__.py +0 -0
  48. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/add_ssh_key_to_user_request.py +0 -0
  49. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/add_ssh_key_to_user_response.py +0 -0
  50. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/add_ssh_public_key_to_instance_request.py +0 -0
  51. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/add_ssh_public_key_to_instance_response.py +0 -0
  52. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/connect_resolve_response.py +0 -0
  53. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/is_user_has_public_ssh_key_request.py +0 -0
  54. {thestage-0.6.8 → thestage-0.7.0}/thestage/connect/dto/is_user_has_public_ssh_key_response.py +0 -0
  55. {thestage-0.6.8 → thestage-0.7.0}/thestage/controllers/__init__.py +0 -0
  56. {thestage-0.6.8 → thestage-0.7.0}/thestage/controllers/base_controller.py +0 -0
  57. {thestage-0.6.8 → thestage-0.7.0}/thestage/controllers/utils_controller.py +0 -0
  58. {thestage-0.6.8 → thestage-0.7.0}/thestage/debug_main.dist.py +0 -0
  59. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/__init__.py +0 -0
  60. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/business/__init__.py +0 -0
  61. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/business/mapper/__init__.py +0 -0
  62. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/business/mapper/container_mapper.py +0 -0
  63. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/communication/__init__.py +0 -0
  64. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/__init__.py +0 -0
  65. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/container_action_request.py +0 -0
  66. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/container_entity.py +0 -0
  67. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/docker_container_list_request.py +0 -0
  68. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/docker_container_list_response.py +0 -0
  69. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/docker_container_mapping.py +0 -0
  70. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/enum/__init__.py +0 -0
  71. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/enum/container_pending_action.py +0 -0
  72. {thestage-0.6.8 → thestage-0.7.0}/thestage/docker_container/dto/enum/container_status.py +0 -0
  73. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/__init__.py +0 -0
  74. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/auth_exception.py +0 -0
  75. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/base_exception.py +0 -0
  76. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/business_logic_exception.py +0 -0
  77. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/config_exception.py +0 -0
  78. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/file_system_exception.py +0 -0
  79. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/git_access_exception.py +0 -0
  80. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/log_polling_exception.py +0 -0
  81. {thestage-0.6.8 → thestage-0.7.0}/thestage/exceptions/remote_server_exception.py +0 -0
  82. {thestage-0.6.8 → thestage-0.7.0}/thestage/git/__init__.py +0 -0
  83. {thestage-0.6.8 → thestage-0.7.0}/thestage/git/business/ProgressPrinter.py +0 -0
  84. {thestage-0.6.8 → thestage-0.7.0}/thestage/git/business/__init__.py +0 -0
  85. {thestage-0.6.8 → thestage-0.7.0}/thestage/git/communication/__init__.py +0 -0
  86. {thestage-0.6.8 → thestage-0.7.0}/thestage/git/communication/git_client.py +0 -0
  87. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/__init__.py +0 -0
  88. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/enums/__init__.py +0 -0
  89. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/enums/order_direction_type.py +0 -0
  90. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/enums/shell_type.py +0 -0
  91. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/enums/tail_output_type.py +0 -0
  92. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/enums/yes_no_response.py +0 -0
  93. {thestage-0.6.8 → thestage-0.7.0}/thestage/global_dto/file_item.py +0 -0
  94. {thestage-0.6.8 → thestage-0.7.0}/thestage/helpers/__init__.py +0 -0
  95. {thestage-0.6.8 → thestage-0.7.0}/thestage/helpers/exception_hook.py +0 -0
  96. {thestage-0.6.8 → thestage-0.7.0}/thestage/helpers/logger/__init__.py +0 -0
  97. {thestage-0.6.8 → thestage-0.7.0}/thestage/helpers/logger/app_logger.py +0 -0
  98. {thestage-0.6.8 → thestage-0.7.0}/thestage/helpers/ssh_util.py +0 -0
  99. {thestage-0.6.8 → thestage-0.7.0}/thestage/i18n/en_GB/messages.po +0 -0
  100. {thestage-0.6.8 → thestage-0.7.0}/thestage/i18n/translation.py +0 -0
  101. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/__init__.py +0 -0
  102. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/business/__init__.py +0 -0
  103. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/business/mapper/__init__.py +0 -0
  104. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/business/mapper/inference_model_mapper.py +0 -0
  105. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/communication/__init__.py +0 -0
  106. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/communication/inference_model_api_client.py +0 -0
  107. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/communication/inference_model_command.py +0 -0
  108. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/__init__.py +0 -0
  109. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/deploy_inference_model_to_instance_request.py +0 -0
  110. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/deploy_inference_model_to_instance_response.py +0 -0
  111. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/deploy_inference_model_to_sagemaker_request.py +0 -0
  112. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/deploy_inference_model_to_sagemaker_response.py +0 -0
  113. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/enum/__init__.py +0 -0
  114. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/enum/inference_model_status.py +0 -0
  115. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/inference_model.py +0 -0
  116. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/inference_model_entity.py +0 -0
  117. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/inference_simulator_model_list_for_project_request.py +0 -0
  118. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/inference_simulator_model_list_for_project_response.py +0 -0
  119. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/inference_simulator_model_response.py +0 -0
  120. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/push_inference_simulator_model_request.py +0 -0
  121. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_model/dto/push_inference_simulator_model_response.py +0 -0
  122. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/__init__.py +0 -0
  123. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/business/__init__.py +0 -0
  124. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/business/mapper/__init__.py +0 -0
  125. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/business/mapper/inference_simulator_mapper.py +0 -0
  126. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/communication/__init__.py +0 -0
  127. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/communication/inference_simulator_api_client.py +0 -0
  128. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/communication/inference_simulator_command.py +0 -0
  129. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/__init__.py +0 -0
  130. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/enum/__init__.py +0 -0
  131. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/enum/inference_simulator_status.py +0 -0
  132. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/get_inference_simulator_request.py +0 -0
  133. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/get_inference_simulator_response.py +0 -0
  134. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/inference_simulator.py +0 -0
  135. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/inference_simulator_entity.py +0 -0
  136. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/inference_simulator_list_request.py +0 -0
  137. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/inference_simulator_list_response.py +0 -0
  138. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/inference_simulator_response.py +0 -0
  139. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/start_inference_simulator_request.py +0 -0
  140. {thestage-0.6.8 → thestage-0.7.0}/thestage/inference_simulator/dto/start_inference_simulator_response.py +0 -0
  141. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/__init__.py +0 -0
  142. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/business/__init__.py +0 -0
  143. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/business/instance_service.py +0 -0
  144. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/business/mapper/__init__.py +0 -0
  145. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/business/mapper/rented_instance_mapper.py +0 -0
  146. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/business/mapper/selfhosted_instance_mapper.py +0 -0
  147. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/communication/__init__.py +0 -0
  148. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/communication/instance_api_client.py +0 -0
  149. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/communication/instance_command.py +0 -0
  150. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/__init__.py +0 -0
  151. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/enum/__init__.py +0 -0
  152. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/enum/cpu_type.py +0 -0
  153. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/enum/gpu_name.py +0 -0
  154. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/enum/instance_rented_status.py +0 -0
  155. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/enum/provider_name.py +0 -0
  156. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/enum/selfhosted_status.py +0 -0
  157. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/instance_detected_gpus.py +0 -0
  158. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/instance_rented_response.py +0 -0
  159. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/rented_instance.py +0 -0
  160. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/self_hosted_instance.py +0 -0
  161. {thestage-0.6.8 → thestage-0.7.0}/thestage/instance/dto/selfhosted_instance_response.py +0 -0
  162. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/__init__.py +0 -0
  163. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/business/__init__.py +0 -0
  164. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/business/logging_service.py +0 -0
  165. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/byte_print_style.py +0 -0
  166. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/communication/__init__.py +0 -0
  167. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/communication/logging_api_client.py +0 -0
  168. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/__init__.py +0 -0
  169. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/docker_container_log_stream_request.py +0 -0
  170. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/log_message.py +0 -0
  171. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/log_polling_request.py +0 -0
  172. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/log_polling_response.py +0 -0
  173. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/log_type.py +0 -0
  174. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/task_log_stream_request.py +0 -0
  175. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/user_logs_query_request.py +0 -0
  176. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/dto/user_logs_query_response.py +0 -0
  177. {thestage-0.6.8 → thestage-0.7.0}/thestage/logging/logging_constants.py +0 -0
  178. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/__init__.py +0 -0
  179. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/business/__init__.py +0 -0
  180. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/communication/__init__.py +0 -0
  181. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/communication/project_api_client.py +0 -0
  182. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/communication/project_command.py +0 -0
  183. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/dto/__init__.py +0 -0
  184. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/dto/get_deploy_ssh_key_request.py +0 -0
  185. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/dto/get_deploy_ssh_key_response.py +0 -0
  186. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/dto/project_config.py +0 -0
  187. {thestage-0.6.8 → thestage-0.7.0}/thestage/project/dto/project_response.py +0 -0
  188. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/.env +0 -0
  189. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/__init__.py +0 -0
  190. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/abstract_mapper.py +0 -0
  191. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/abstract_service.py +0 -0
  192. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/__init__.py +0 -0
  193. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/__init__.py +0 -0
  194. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/core/api_client_core.py +0 -0
  195. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/core/http_client_exception.py +0 -0
  196. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/__init__.py +0 -0
  197. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/base_response.py +0 -0
  198. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/entity_filter_request.py +0 -0
  199. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/frontend_status.py +0 -0
  200. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/installed_service.py +0 -0
  201. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/paginated_entity_list.py +0 -0
  202. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/pagination_data.py +0 -0
  203. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +0 -0
  204. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/clients/thestage_api/dtos/validate_token_response.py +0 -0
  205. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/filesystem_service.py +0 -0
  206. {thestage-0.6.8 → thestage-0.7.0}/thestage/services/service_factory.py +0 -0
  207. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/__init__.py +0 -0
  208. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/business/__init__.py +0 -0
  209. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/business/mapper/__init__.py +0 -0
  210. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/business/mapper/task_mapper.py +0 -0
  211. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/communication/__init__.py +0 -0
  212. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/communication/task_api_client.py +0 -0
  213. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/communication/task_command.py +0 -0
  214. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/__init__.py +0 -0
  215. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/enum/__init__.py +0 -0
  216. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/enum/task_execution_status.py +0 -0
  217. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/enum/task_status.py +0 -0
  218. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/list_for_project_request.py +0 -0
  219. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/list_for_project_response.py +0 -0
  220. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/run_task_request.py +0 -0
  221. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/run_task_response.py +0 -0
  222. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/status_localized_map_response.py +0 -0
  223. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/task.py +0 -0
  224. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/task_entity.py +0 -0
  225. {thestage-0.6.8 → thestage-0.7.0}/thestage/task/dto/view_response.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thestage
3
- Version: 0.6.8
3
+ Version: 0.7.0
4
4
  Summary:
5
5
  License-File: LICENSE.txt
6
6
  Author: TheStage AI team
@@ -1,7 +1,7 @@
1
1
  [tool.poetry]
2
2
  name = "thestage"
3
3
 
4
- version = "0.6.8"
4
+ version = "0.7.0"
5
5
 
6
6
  description = ""
7
7
  authors = ["TheStage AI team <hello@thestage.ai>"]
@@ -1,3 +1,3 @@
1
1
  from . import *
2
2
  __app_name__ = "thestage"
3
- __version__ = "0.6.8"
3
+ __version__ = "0.7.0"
@@ -27,10 +27,13 @@ class CliCommand(str, Enum):
27
27
  CONTAINER_CONNECT = "CONTAINER_CONNECT"
28
28
  CONTAINER_UPLOAD = "CONTAINER_UPLOAD"
29
29
  CONTAINER_DOWNLOAD = "CONTAINER_DOWNLOAD"
30
+ CONTAINER_CREATE = "CONTAINER_CREATE"
30
31
  CONTAINER_START = "CONTAINER_START"
31
32
  CONTAINER_STOP = "CONTAINER_STOP"
33
+ CONTAINER_DELETE = "CONTAINER_DELETE"
32
34
  CONTAINER_RESTART = "CONTAINER_RESTART"
33
35
  CONTAINER_LOGS = "CONTAINER_LOGS"
36
+ CONTAINER_IMAGE_LS = "CONTAINER_IMAGE_LS"
34
37
  INSTANCE_RENTED_LS = "INSTANCE_RENTED_LS"
35
38
  INSTANCE_RENTED_CONNECT = "INSTANCE_RENTED_CONNECT"
36
39
  INSTANCE_SELF_HOSTED_LS = "INSTANCE_SELF_HOSTED_LS"
@@ -7,19 +7,24 @@ import typer
7
7
 
8
8
  from thestage.color_scheme.color_scheme import ColorScheme
9
9
  from thestage.connect.communication.connect_api_client import ConnectApiClient
10
+ from thestage.docker_container.business.mapper.image_mapper import ImageMapper
10
11
  from thestage.docker_container.communication.docker_container_api_client import DockerContainerApiClient
11
12
  from thestage.docker_container.dto.container_entity import DockerContainerEntity
12
13
  from thestage.docker_container.dto.container_action_request import DockerContainerActionRequest
14
+ from thestage.docker_container.dto.docker_container_create_request import DockerContainerCreateRequest, \
15
+ DockerContainerMappings
13
16
  from thestage.docker_container.dto.enum.container_pending_action import DockerContainerAction
14
17
  from thestage.docker_container.dto.enum.container_status import DockerContainerStatus
18
+ from thestage.docker_container.dto.image_entity import DockerImageEntity
15
19
  from thestage.global_dto.enums.shell_type import ShellType
20
+ from thestage.project.dto.project_config import ProjectConfig
16
21
  from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
17
22
  from thestage.docker_container.business.mapper.container_mapper import ContainerMapper
18
23
  from thestage.services.filesystem_service import FileSystemService
19
24
  from thestage.connect.business.remote_server_service import RemoteServerService
20
25
  from thestage.i18n.translation import __
21
26
  from thestage.services.abstract_service import AbstractService
22
- from thestage.docker_container.dto.container_response import DockerContainerDto
27
+ from thestage.docker_container.dto.container_response import DockerContainerDto, DockerImageDto
23
28
  from thestage.helpers.error_handler import error_handler
24
29
  from thestage.config.business.config_provider import ConfigProvider
25
30
 
@@ -118,6 +123,7 @@ class ContainerService(AbstractService):
118
123
 
119
124
  return list
120
125
 
126
+
121
127
  # TODO delete this proxy method
122
128
  @error_handler()
123
129
  def get_container(
@@ -456,3 +462,117 @@ class ContainerService(AbstractService):
456
462
 
457
463
  if result.is_success:
458
464
  typer.echo(f'Docker container action scheduled: {action.value}')
465
+
466
+ @error_handler()
467
+ def create_docker_container(
468
+ self,
469
+ project_public_id: Optional[str],
470
+ project_slug: Optional[str],
471
+ container_slug: str,
472
+ rented_instance_public_id: Optional[str],
473
+ rented_instance_slug: Optional[str],
474
+ self_hosted_instance_public_id: Optional[str],
475
+ self_hosted_instance_slug: Optional[str],
476
+ image_name: str,
477
+ cpu_number: Optional[int],
478
+ gpu_number: Optional[int],
479
+ volume_mappings: Optional[Dict[str, str]],
480
+ ):
481
+ if not project_public_id and not project_slug:
482
+ project_config: ProjectConfig = self.__config_provider.read_project_config()
483
+ if not project_config:
484
+ typer.echo("Provide the project unique ID or name, or run this command from within an initialized project directory")
485
+ raise typer.Exit(1)
486
+ project_public_id = project_config.public_id
487
+
488
+ docker_images_paginated = self.get_image_list()
489
+ if not docker_images_paginated or not docker_images_paginated.entities:
490
+ typer.echo("No Docker images available")
491
+ raise typer.Exit(1)
492
+
493
+ selected_image = None
494
+ selection_pool = docker_images_paginated.entities
495
+
496
+ if image_name is not None:
497
+ matches = [img for img in selection_pool if img.image == image_name]
498
+
499
+ if len(matches) == 1:
500
+ selected_image = matches[0]
501
+ elif len(matches) > 1:
502
+ typer.echo(f"Multiple tags found for repository '{image_name}':")
503
+ selection_pool = matches
504
+ else:
505
+ typer.echo(f"Image '{image_name}' not found. Select from available images:")
506
+
507
+ if selected_image is None:
508
+ for idx, img in enumerate(selection_pool, start=1):
509
+ typer.echo(f"{idx}) {img.image}:{img.tag}")
510
+
511
+ choice_str = typer.prompt("Choose which image to use")
512
+
513
+ try:
514
+ choice_index = int(choice_str)
515
+ except ValueError:
516
+ typer.echo("Error: Invalid input. Enter a number.")
517
+ raise typer.Exit(1)
518
+
519
+ if not (1 <= choice_index <= len(selection_pool)):
520
+ typer.echo("Error: Choice out of range.")
521
+ raise typer.Exit(1)
522
+
523
+ selected_image = selection_pool[choice_index - 1]
524
+
525
+ request_params = DockerContainerCreateRequest(
526
+ instance_rented_public_id=rented_instance_public_id,
527
+ instance_rented_slug=rented_instance_slug,
528
+ selfhosted_instance_public_id=self_hosted_instance_public_id,
529
+ selfhosted_instance_slug=self_hosted_instance_slug,
530
+ project_public_id=project_public_id,
531
+ project_slug=project_slug,
532
+ container_slug=container_slug,
533
+ docker_image_id=selected_image.id,
534
+ assigned_cpus=cpu_number,
535
+ is_unlimited_cpus=cpu_number is None,
536
+ assigned_gpus=gpu_number,
537
+ is_unlimited_gpus=gpu_number is None,
538
+ mappings=DockerContainerMappings(directory_mappings=volume_mappings)
539
+ )
540
+
541
+ result = self.__docker_container_api_client.create_container(
542
+ request_params
543
+ )
544
+ if result.is_success:
545
+ typer.echo(f'Docker container creation scheduled.')
546
+
547
+ @error_handler()
548
+ def print_docker_image_list(
549
+ self,
550
+ row: int,
551
+ page: int,
552
+ ):
553
+ typer.echo("Listing available Docker images:")
554
+
555
+ self.print(
556
+ func_get_data=self.get_image_list,
557
+ func_special_params={},
558
+ mapper=ImageMapper(),
559
+ headers=list(map(lambda x: x.alias, DockerImageEntity.model_fields.values())),
560
+ row=row,
561
+ page=page,
562
+ max_col_width=[50, 20],
563
+ show_index="never",
564
+ )
565
+
566
+ @error_handler()
567
+ def get_image_list(
568
+ self,
569
+ row: int = 5,
570
+ page: int = 1,
571
+ ) -> PaginatedEntityList[DockerImageDto]:
572
+
573
+ list = self.__docker_container_api_client.get_docker_image_list(
574
+ page=page,
575
+ limit=row,
576
+ )
577
+
578
+ return list
@@ -0,0 +1,16 @@
1
+ from typing import Optional
2
+
3
+ from thestage.docker_container.dto.container_response import DockerImageDto
4
+ from thestage.docker_container.dto.image_entity import DockerImageEntity
5
+ from thestage.services.abstract_mapper import AbstractMapper
6
+
7
+
8
+ class ImageMapper(AbstractMapper):
9
+ def build_entity(self, item: DockerImageDto) -> Optional[DockerImageEntity]:
10
+ if not item:
11
+ return None
12
+
13
+ return DockerImageEntity(
14
+ image=item.image or '',
15
+ tag=item.tag or '',
16
+ )
@@ -15,7 +15,6 @@ from thestage.logging.business.logging_service import LoggingService
15
15
 
16
16
  app = typer.Typer(no_args_is_help=True, help=__("Manage containers"))
17
17
 
18
-
19
18
  @app.command(name='ls', help=__("List containers"), **get_command_metadata(CliCommand.CONTAINER_LS))
20
19
  def list_containers(
21
20
  row: int = typer.Option(
@@ -289,7 +288,7 @@ def start_container(
289
288
  check_command_permission(command_name)
290
289
 
291
290
  if sum(v is not None for v in [container_public_id, container_slug]) != 1:
292
- typer.echo("Please provide a single identifier for container - ID or name.")
291
+ typer.echo("Provide a single identifier for container - ID or name.")
293
292
  raise typer.Exit(1)
294
293
 
295
294
  service_factory = validate_config_and_get_service_factory()
@@ -301,7 +300,140 @@ def start_container(
301
300
  action=DockerContainerAction.START
302
301
  )
303
302
 
304
- app_logger.info(f'Container start completed')
303
+ app_logger.info(f'Container is starting')
304
+ raise typer.Exit(0)
305
+
306
+
307
+ @app.command(name="create", no_args_is_help=True, help=__("Create container"), **get_command_metadata(CliCommand.CONTAINER_CREATE))
308
+ def create_container(
309
+ project_public_id: Optional[str] = typer.Option(
310
+ None,
311
+ '--project-id',
312
+ '-pid',
313
+ help=__("Project ID. By default, project info is taken from the current directory"),
314
+ is_eager=False,
315
+ ),
316
+ project_slug: Optional[str] = typer.Option(
317
+ None,
318
+ '--project-name',
319
+ '-pn',
320
+ help=__("Project name. By default, project info is taken from the current directory"),
321
+ is_eager=False,
322
+ ),
323
+ working_directory: Optional[str] = typer.Option(
324
+ None,
325
+ "--working-directory",
326
+ "-wd",
327
+ help=__("Full path to working directory"),
328
+ show_default=False,
329
+ is_eager=False,
330
+ ),
331
+ container_slug: Optional[str] = typer.Option(
332
+ None,
333
+ '--container-name',
334
+ '-cn',
335
+ help=__("Container name"),
336
+ is_eager=False,
337
+ ),
338
+ rented_instance_public_id: Optional[str] = typer.Option(
339
+ None,
340
+ '--rented-instance-id',
341
+ '-rid',
342
+ help=__("Rented instance ID on which container will run"),
343
+ is_eager=False,
344
+ ),
345
+ rented_instance_slug: Optional[str] = typer.Option(
346
+ None,
347
+ '--rented-instance-name',
348
+ '-rn',
349
+ help=__("Rented instance name on which container will run"),
350
+ is_eager=False,
351
+ ),
352
+ self_hosted_instance_public_id: Optional[str] = typer.Option(
353
+ None,
354
+ '--self-hosted-instance-id',
355
+ '-sid',
356
+ help=__("Self-hosted instance ID on which container will run"),
357
+ is_eager=False,
358
+ ),
359
+ self_hosted_instance_slug: Optional[str] = typer.Option(
360
+ None,
361
+ '--self-hosted-instance-name',
362
+ '-sn',
363
+ help=__("Self-hosted instance name on which container will run"),
364
+ is_eager=False,
365
+ ),
366
+ image_name: Optional[str] = typer.Option(
367
+ None,
368
+ '--image',
369
+ '-i',
370
+ help=__("Docker image name. If not provided, you will be prompted to select from available images"),
371
+ is_eager=False,
372
+ ),
373
+ gpu_number: Optional[int] = typer.Option(
374
+ None,
375
+ '--gpu-number',
376
+ '-gpun',
377
+ help=__("Number of assigned GPUs for container. No GPU limit by default"),
378
+ is_eager=False,
379
+ ),
380
+ cpu_number: Optional[int] = typer.Option(
381
+ None,
382
+ '--cpu-number',
383
+ '-cpun',
384
+ help=__("Number of assigned CPUs for container. No CPU limit by default"),
385
+ is_eager=False,
386
+ ),
387
+ volume_mounts: Optional[List[str]] = typer.Option(
388
+ None,
389
+ '--volume',
390
+ '-v',
391
+ help=__("Volume mounts. Can be used multiple times. Format: /host_dir:/container_dir"),
392
+ is_eager=False,
393
+ ),
394
+ ):
395
+ command_name = CliCommand.CONTAINER_CREATE
396
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
397
+ check_command_permission(command_name)
398
+
399
+ if sum(v is not None for v in [project_public_id, project_slug]) > 1:
400
+ typer.echo("Provide a single identifier for project - ID or name.")
401
+ raise typer.Exit(1)
402
+
403
+ if sum(v is not None for v in [rented_instance_public_id, rented_instance_slug, self_hosted_instance_public_id, self_hosted_instance_slug]) != 1:
404
+ typer.echo("Provide exactly one identifier (ID or Name) for either a rented or self-hosted instance.")
405
+ raise typer.Exit(1)
406
+
407
+ if not container_slug:
408
+ container_slug = typer.prompt("Enter container name")
409
+
410
+ volume_mappings_dict = {}
411
+ if volume_mounts:
412
+ for mount in volume_mounts:
413
+ if ":" not in mount:
414
+ typer.echo(f"Invalid volume format: {mount}. Expected host:container")
415
+ raise typer.Exit(1)
416
+ host_path, container_path = mount.split(":", 1)
417
+ volume_mappings_dict[host_path] = container_path
418
+
419
+ service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
420
+ container_service: ContainerService = service_factory.get_container_service()
421
+
422
+ container_service.create_docker_container(
423
+ project_public_id=project_public_id,
424
+ project_slug=project_slug,
425
+ container_slug=container_slug,
426
+ rented_instance_public_id=rented_instance_public_id,
427
+ rented_instance_slug=rented_instance_slug,
428
+ self_hosted_instance_public_id=self_hosted_instance_public_id,
429
+ self_hosted_instance_slug=self_hosted_instance_slug,
430
+ image_name=image_name,
431
+ cpu_number=cpu_number,
432
+ gpu_number=gpu_number,
433
+ volume_mappings=volume_mappings_dict
434
+ )
435
+
436
+ app_logger.info(f'Container is creating')
305
437
  raise typer.Exit(0)
306
438
 
307
439
 
@@ -327,7 +459,7 @@ def stop_container(
327
459
  check_command_permission(command_name)
328
460
 
329
461
  if sum(v is not None for v in [container_public_id, container_slug]) != 1:
330
- typer.echo("Please provide a single identifier for container - ID or name.")
462
+ typer.echo("Provide a single identifier for container - ID or name.")
331
463
  raise typer.Exit(1)
332
464
 
333
465
  service_factory = validate_config_and_get_service_factory()
@@ -339,10 +471,47 @@ def stop_container(
339
471
  action=DockerContainerAction.STOP
340
472
  )
341
473
 
342
- app_logger.info(f'Container stop completed')
474
+ app_logger.info(f'Container is stopping')
343
475
  raise typer.Exit(0)
344
476
 
345
477
 
478
+ @app.command(name="delete", no_args_is_help=True, help=__("Delete container"), **get_command_metadata(CliCommand.CONTAINER_DELETE))
479
+ def delete_container(
480
+ container_public_id: str = typer.Option(
481
+ None,
482
+ '--container-id',
483
+ '-cid',
484
+ help=__("Container ID"),
485
+ is_eager=False,
486
+ ),
487
+ container_slug: str = typer.Option(
488
+ None,
489
+ '--container-name',
490
+ '-cn',
491
+ help=__("Container name"),
492
+ is_eager=False,
493
+ ),
494
+ ):
495
+ command_name = CliCommand.CONTAINER_DELETE
496
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
497
+ check_command_permission(command_name)
498
+
499
+ if sum(v is not None for v in [container_public_id, container_slug]) != 1:
500
+ typer.echo("Provide a single identifier for container - ID or name.")
501
+ raise typer.Exit(1)
502
+
503
+ service_factory = validate_config_and_get_service_factory()
504
+ container_service: ContainerService = service_factory.get_container_service()
505
+
506
+ container_service.request_docker_container_action(
507
+ container_public_id=container_public_id,
508
+ container_slug=container_slug,
509
+ action=DockerContainerAction.DELETE
510
+ )
511
+
512
+ app_logger.info(f'Container is deleting')
513
+ raise typer.Exit(0)
514
+
346
515
  @app.command(name="restart", no_args_is_help=True, help=__("Restart container"), **get_command_metadata(CliCommand.CONTAINER_RESTART))
347
516
  def restart_container(
348
517
  container_public_id: str = typer.Option(
@@ -365,7 +534,7 @@ def restart_container(
365
534
  check_command_permission(command_name)
366
535
 
367
536
  if sum(v is not None for v in [container_public_id, container_slug]) != 1:
368
- typer.echo("Please provide a single identifier for container - ID or name.")
537
+ typer.echo("Provide a single identifier for container - ID or name.")
369
538
  raise typer.Exit(1)
370
539
 
371
540
  service_factory = validate_config_and_get_service_factory()
@@ -377,7 +546,7 @@ def restart_container(
377
546
  action=DockerContainerAction.RESTART
378
547
  )
379
548
 
380
- app_logger.info(f'Container restart completed')
549
+ app_logger.info(f'Container is restarting')
381
550
  raise typer.Exit(0)
382
551
 
383
552
 
@@ -410,7 +579,7 @@ def container_logs(
410
579
  check_command_permission(command_name)
411
580
 
412
581
  if sum(v is not None for v in [container_public_id, container_slug]) != 1:
413
- typer.echo("Please provide a single identifier for container - ID or name.")
582
+ typer.echo("Provide a single identifier for container - ID or name.")
414
583
  raise typer.Exit(1)
415
584
 
416
585
  service_factory = validate_config_and_get_service_factory()
@@ -425,4 +594,4 @@ def container_logs(
425
594
  logging_service.print_last_container_logs(container_public_id=container_public_id, container_slug=container_slug, logs_number=logs_number)
426
595
 
427
596
  app_logger.info(f'Container log streaming completed')
428
- raise typer.Exit(0)
597
+ raise typer.Exit(0)
@@ -1,6 +1,10 @@
1
1
  from typing import Optional, List, Dict
2
2
 
3
3
  from thestage.config.business.config_provider import ConfigProvider
4
+ from thestage.docker_container.dto.docker_container_create_request import DockerContainerCreateRequest
5
+ from thestage.docker_container.dto.docker_container_create_response import DockerContainerCreateResult
6
+ from thestage.docker_container.dto.docker_image_list_request import DockerImageListRequest
7
+ from thestage.docker_container.dto.docker_image_list_response import DockerImageListResponse
4
8
  from thestage.global_dto.enums.order_direction_type import OrderDirectionType
5
9
  from thestage.services.clients.thestage_api.core.api_client_core import TheStageApiClientCore
6
10
  from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
@@ -11,7 +15,7 @@ from thestage.docker_container.dto.container_action_request import DockerContain
11
15
  from thestage.docker_container.dto.container_response import (
12
16
  DockerContainerDto,
13
17
  DockerContainerViewResponse,
14
- ContainerBusinessStatusMapperResponse
18
+ ContainerBusinessStatusMapperResponse, DockerImageDto
15
19
  )
16
20
  from thestage.docker_container.dto.docker_container_list_request import DockerContainerListRequest
17
21
  from thestage.docker_container.dto.docker_container_list_response import DockerContainerListResponse
@@ -50,9 +54,32 @@ class DockerContainerApiClient(TheStageApiClientCore):
50
54
  )
51
55
 
52
56
  result = DockerContainerListResponse.model_validate(response) if response else None
53
- # return result.paginatedList.entities, result.paginatedList.pagination_data.total_pages if result and result.is_success else None
54
57
  return result.paginatedList if result and result.is_success else None
55
58
 
59
+
60
+ def get_docker_image_list(
61
+ self,
62
+ page: int = 1,
63
+ limit: int = 10,
64
+ ) -> PaginatedEntityList[DockerImageDto]:
65
+ request = DockerImageListRequest(
66
+ entityFilterRequest=EntityFilterRequest(
67
+ orderByField="createdAt",
68
+ orderByDirection=OrderDirectionType.DESC,
69
+ page=page,
70
+ limit=limit,
71
+ ),
72
+ )
73
+ response = self._request(
74
+ method='POST',
75
+ url='/user-api/v1/docker-image/list',
76
+ data=request.model_dump(),
77
+ token=self.__config_provider.get_config().main.thestage_auth_token
78
+ )
79
+ result = DockerImageListResponse.model_validate(response) if response else None
80
+ return result.paginatedList if result and result.is_success else None
81
+
82
+
56
83
  def get_container(
57
84
  self,
58
85
  container_slug: Optional[str] = None,
@@ -72,6 +99,18 @@ class DockerContainerApiClient(TheStageApiClientCore):
72
99
 
73
100
  return DockerContainerViewResponse.model_validate(response).docker_container if response else None
74
101
 
102
+
103
+ def create_container(self, request_param: DockerContainerCreateRequest) -> Optional[DockerContainerCreateResult]:
104
+ response = self._request(
105
+ method='POST',
106
+ url='/user-api/v1/docker-container/create',
107
+ data=request_param.model_dump(by_alias=True),
108
+ token=self.__config_provider.get_config().main.thestage_auth_token
109
+ )
110
+
111
+ return DockerContainerCreateResult.model_validate(response) if response else None
112
+
113
+
75
114
  def container_action(
76
115
  self,
77
116
  request_param: DockerContainerActionRequest,
@@ -87,6 +126,7 @@ class DockerContainerApiClient(TheStageApiClientCore):
87
126
  result = TheStageBaseResponse.model_validate(response) if response else None
88
127
  return result
89
128
 
129
+
90
130
  def get_container_business_status_map(self) -> Optional[Dict[str, str]]:
91
131
  response = self._request(
92
132
  method='POST',
@@ -0,0 +1,40 @@
1
+ import typer
2
+
3
+ from thestage.cli_command import CliCommand
4
+ from thestage.cli_command_helper import get_command_metadata, check_command_permission
5
+ from thestage.controllers.utils_controller import validate_config_and_get_service_factory
6
+ from thestage.docker_container.business.container_service import ContainerService
7
+ from thestage.i18n.translation import __
8
+
9
+ app = typer.Typer(no_args_is_help=True, help=__("Manage Docker images"))
10
+
11
+ @app.command(name='ls', help=__("List available docker images"), **get_command_metadata(CliCommand.CONTAINER_LS))
12
+ def list_available_images(
13
+ row: int = typer.Option(
14
+ 5,
15
+ '--row',
16
+ '-r',
17
+ help=__("Set number of rows displayed per page"),
18
+ is_eager=False,
19
+ ),
20
+ page: int = typer.Option(
21
+ 1,
22
+ '--page',
23
+ '-p',
24
+ help=__("Set starting page for displaying output"),
25
+ is_eager=False,
26
+ ),
27
+ ):
28
+ command_name = CliCommand.CONTAINER_IMAGE_LS
29
+ check_command_permission(command_name)
30
+
31
+ service_factory = validate_config_and_get_service_factory()
32
+ container_service: ContainerService = service_factory.get_container_service()
33
+
34
+ container_service.print_docker_image_list(
35
+ row=row,
36
+ page=page,
37
+ )
38
+
39
+ typer.echo(__("Images listing complete"))
40
+ raise typer.Exit(0)
@@ -45,3 +45,10 @@ class ContainerBusinessStatusMapperResponse(TheStageBasePaginatedResponse):
45
45
  model_config = ConfigDict(use_enum_values=True)
46
46
 
47
47
  docker_container_status_map: Dict[str, str] = Field(default={}, alias='dockerContainerStatusMap')
48
+
49
+ class DockerImageDto(BaseModel):
50
+ model_config = ConfigDict(use_enum_values=True)
51
+
52
+ id: Optional[int] = Field(None, alias='id')
53
+ image: Optional[str] = Field(None, alias='image')
54
+ tag: Optional[str] = Field(None, alias='tag')
@@ -0,0 +1,28 @@
1
+ from typing import Optional, Dict
2
+
3
+ from pydantic import BaseModel, Field, ConfigDict
4
+
5
+
6
+ class DockerContainerMappings(BaseModel):
7
+ model_config = ConfigDict(populate_by_name=True)
8
+
9
+ directory_mappings: Dict[str, str] = Field(default_factory=dict, alias='directoryMappings')
10
+ port_mappings: Dict[str, str] = Field(default_factory=dict, alias='portMappings')
11
+
12
+
13
+ class DockerContainerCreateRequest(BaseModel):
14
+ model_config = ConfigDict(populate_by_name=True)
15
+
16
+ instance_rented_public_id: Optional[str] = Field(None, alias='instanceRentedPublicId')
17
+ instance_rented_slug: Optional[str] = Field(None, alias='instanceRentedSlug')
18
+ selfhosted_instance_public_id: Optional[str] = Field(None, alias='selfhostedInstancePublicId')
19
+ selfhosted_instance_slug: Optional[str] = Field(None, alias='selfhostedInstanceSlug')
20
+ project_public_id: Optional[str] = Field(..., alias='projectPublicId')
21
+ project_slug: Optional[str] = Field(..., alias='projectSlug')
22
+ container_slug: str = Field(..., alias='containerSlug')
23
+ docker_image_id: int = Field(..., alias='dockerImageId')
24
+ assigned_cpus: Optional[int] = Field(None, alias='assignedCpus')
25
+ is_unlimited_cpus: bool = Field(False, alias='isUnlimitedCpus')
26
+ assigned_gpus: Optional[int] = Field(None, alias='assignedGpus')
27
+ is_unlimited_gpus: bool = Field(False, alias='isUnlimitedGpus')
28
+ mappings: DockerContainerMappings = Field(default_factory=DockerContainerMappings, alias='mappings')
@@ -0,0 +1,11 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field, ConfigDict
4
+
5
+ from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
6
+
7
+
8
+ class DockerContainerCreateResult(TheStageBaseResponse):
9
+ model_config = ConfigDict(populate_by_name=True)
10
+
11
+ docker_container_public_id: Optional[str] = Field(None, alias='dockerContainerPublicId')
@@ -0,0 +1,11 @@
1
+ from typing import Optional, List
2
+
3
+ from pydantic import Field, ConfigDict, BaseModel
4
+
5
+ from thestage.services.clients.thestage_api.dtos.entity_filter_request import EntityFilterRequest
6
+
7
+
8
+ class DockerImageListRequest(BaseModel):
9
+ model_config = ConfigDict(use_enum_values=True)
10
+
11
+ entityFilterRequest: EntityFilterRequest = Field(None, alias='entityFilterRequest')
@@ -0,0 +1,13 @@
1
+ from typing import List, Optional
2
+
3
+ from pydantic import Field, ConfigDict
4
+
5
+ from thestage.docker_container.dto.container_response import DockerImageDto
6
+ from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
7
+ from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
8
+
9
+
10
+ class DockerImageListResponse(TheStageBaseResponse):
11
+ model_config = ConfigDict(use_enum_values=True)
12
+
13
+ paginatedList: PaginatedEntityList[DockerImageDto] = Field(None, alias='paginatedList')
@@ -0,0 +1,14 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict, Field
4
+
5
+
6
+ class DockerImageEntity(BaseModel):
7
+
8
+ model_config = ConfigDict(
9
+ populate_by_name=True,
10
+ use_enum_values=True,
11
+ )
12
+
13
+ image: Optional[str] = Field(None, alias='IMAGE')
14
+ tag: Optional[str] = Field(None, alias='TAG')