thestage 0.5.46__py3-none-any.whl → 0.5.49__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 (179) hide show
  1. thestage/.env +5 -0
  2. thestage/__init__.py +3 -3
  3. thestage/__main__.py +9 -9
  4. thestage/cli_command.py +56 -0
  5. thestage/cli_command_helper.py +51 -0
  6. thestage/color_scheme/color_scheme.py +7 -7
  7. thestage/config/__init__.py +18 -18
  8. thestage/config/config_storage.py +5 -0
  9. thestage/config/env_base.py +7 -7
  10. thestage/controllers/__init__.py +0 -0
  11. thestage/controllers/base_controller.py +67 -63
  12. thestage/controllers/config_controller.py +137 -145
  13. thestage/controllers/container_controller.py +389 -425
  14. thestage/controllers/instance_controller.py +183 -200
  15. thestage/controllers/project_controller.py +802 -872
  16. thestage/controllers/utils_controller.py +32 -28
  17. thestage/debug_main.dist.py +28 -28
  18. thestage/entities/__init__.py +0 -0
  19. thestage/entities/container.py +17 -22
  20. thestage/entities/enums/__init__.py +0 -0
  21. thestage/entities/enums/order_direction_type.py +6 -6
  22. thestage/entities/enums/shell_type.py +7 -7
  23. thestage/entities/enums/tail_output_type.py +6 -6
  24. thestage/entities/enums/yes_no_response.py +7 -7
  25. thestage/entities/file_item.py +27 -27
  26. thestage/entities/project_inference_simulator.py +18 -18
  27. thestage/entities/project_inference_simulator_model.py +16 -16
  28. thestage/entities/project_task.py +19 -19
  29. thestage/entities/rented_instance.py +19 -24
  30. thestage/entities/self_hosted_instance.py +18 -20
  31. thestage/exceptions/__init__.py +0 -0
  32. thestage/exceptions/auth_exception.py +6 -6
  33. thestage/exceptions/base_exception.py +13 -13
  34. thestage/exceptions/business_logic_exception.py +6 -6
  35. thestage/exceptions/config_exception.py +6 -6
  36. thestage/exceptions/file_system_exception.py +6 -6
  37. thestage/exceptions/git_access_exception.py +17 -17
  38. thestage/exceptions/remote_server_exception.py +24 -24
  39. thestage/git/ProgressPrinter.py +22 -22
  40. thestage/helpers/__init__.py +0 -0
  41. thestage/helpers/error_handler.py +115 -115
  42. thestage/helpers/exception_hook.py +14 -0
  43. thestage/helpers/logger/__init__.py +0 -0
  44. thestage/helpers/logger/app_logger.py +50 -51
  45. thestage/helpers/ssh_util.py +38 -38
  46. thestage/i18n/en_GB/messages.po +947 -947
  47. thestage/i18n/translation.py +9 -9
  48. thestage/main.py +36 -24
  49. thestage/services/.env +6 -6
  50. thestage/services/__init__.py +0 -0
  51. thestage/services/abstract_mapper.py +9 -9
  52. thestage/services/abstract_service.py +87 -127
  53. thestage/services/app_config_service.py +52 -51
  54. thestage/services/clients/__init__.py +0 -0
  55. thestage/services/clients/git/__init__.py +0 -0
  56. thestage/services/clients/git/git_client.py +433 -331
  57. thestage/services/clients/thestage_api/__init__.py +0 -0
  58. thestage/services/clients/thestage_api/api_client.py +718 -734
  59. thestage/services/clients/thestage_api/core/api_client_core.py +108 -25
  60. thestage/services/clients/thestage_api/core/http_client_exception.py +12 -12
  61. thestage/services/clients/thestage_api/dtos/__init__.py +0 -0
  62. thestage/services/clients/thestage_api/dtos/base_response.py +13 -13
  63. thestage/services/clients/thestage_api/dtos/cloud_provider_region.py +19 -19
  64. thestage/services/clients/thestage_api/dtos/container_param_request.py +11 -11
  65. thestage/services/clients/thestage_api/dtos/container_response.py +67 -67
  66. thestage/services/clients/thestage_api/dtos/docker_container_assigned_device.py +10 -10
  67. thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_request.py +13 -13
  68. thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_response.py +13 -13
  69. thestage/services/clients/thestage_api/dtos/docker_container_mapping.py +10 -10
  70. thestage/services/clients/thestage_api/dtos/entity_filter_request.py +14 -14
  71. thestage/services/clients/thestage_api/dtos/enums/__init__.py +0 -0
  72. thestage/services/clients/thestage_api/dtos/enums/container_pending_action.py +10 -10
  73. thestage/services/clients/thestage_api/dtos/enums/container_status.py +17 -17
  74. thestage/services/clients/thestage_api/dtos/enums/cpu_type.py +8 -8
  75. thestage/services/clients/thestage_api/dtos/enums/currency_type.py +10 -10
  76. thestage/services/clients/thestage_api/dtos/enums/daemon_status.py +9 -9
  77. thestage/services/clients/thestage_api/dtos/enums/disk_type.py +7 -7
  78. thestage/services/clients/thestage_api/dtos/enums/drive_type.py +7 -7
  79. thestage/services/clients/thestage_api/dtos/enums/gpu_name.py +8 -8
  80. thestage/services/clients/thestage_api/dtos/enums/inference_model_status.py +9 -9
  81. thestage/services/clients/thestage_api/dtos/enums/inference_simulator_status.py +15 -15
  82. thestage/services/clients/thestage_api/dtos/enums/instance_rented_status.py +17 -17
  83. thestage/services/clients/thestage_api/dtos/enums/instance_type.py +7 -7
  84. thestage/services/clients/thestage_api/dtos/enums/location_region.py +11 -11
  85. thestage/services/clients/thestage_api/dtos/enums/power_status.py +10 -10
  86. thestage/services/clients/thestage_api/dtos/enums/provider_name.py +11 -11
  87. thestage/services/clients/thestage_api/dtos/enums/selfhosted_status.py +10 -10
  88. thestage/services/clients/thestage_api/dtos/enums/task_execution_status.py +12 -12
  89. thestage/services/clients/thestage_api/dtos/enums/task_status.py +12 -12
  90. thestage/services/clients/thestage_api/dtos/frontend_status.py +10 -10
  91. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +13 -13
  92. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +13 -13
  93. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_request.py +12 -12
  94. thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_response.py +12 -12
  95. thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +10 -10
  96. thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py +13 -13
  97. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_request.py +14 -14
  98. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_response.py +12 -12
  99. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_request.py +12 -12
  100. thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_response.py +13 -13
  101. thestage/services/clients/thestage_api/dtos/inference_simulator_model_response.py +11 -11
  102. thestage/services/clients/thestage_api/dtos/inference_simulator_response.py +11 -11
  103. thestage/services/clients/thestage_api/dtos/installed_service.py +17 -17
  104. thestage/services/clients/thestage_api/dtos/instance_detected_gpus.py +20 -20
  105. thestage/services/clients/thestage_api/dtos/instance_rented_response.py +71 -71
  106. thestage/services/clients/thestage_api/dtos/logging_controller/docker_container_log_stream_request.py +7 -7
  107. thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_request.py +13 -13
  108. thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_response.py +14 -14
  109. thestage/services/clients/thestage_api/dtos/logging_controller/task_log_stream_request.py +7 -7
  110. thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_request.py +21 -21
  111. thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_response.py +14 -14
  112. thestage/services/clients/thestage_api/dtos/paginated_entity_list.py +11 -11
  113. thestage/services/clients/thestage_api/dtos/pagination_data.py +10 -10
  114. thestage/services/clients/thestage_api/dtos/price_definition.py +14 -14
  115. thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py +7 -7
  116. thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_response.py +10 -10
  117. thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py +8 -8
  118. thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py +6 -6
  119. thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_request.py +15 -15
  120. thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +10 -10
  121. thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py +13 -14
  122. thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py +10 -10
  123. thestage/services/clients/thestage_api/dtos/project_response.py +32 -32
  124. thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +56 -56
  125. thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +13 -13
  126. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_request.py +8 -8
  127. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_response.py +11 -11
  128. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_request.py +8 -8
  129. thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_response.py +11 -11
  130. thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_request.py +7 -7
  131. thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_response.py +12 -12
  132. thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py +10 -10
  133. thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py +12 -12
  134. thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py +9 -9
  135. thestage/services/clients/thestage_api/dtos/task_controller/task_view_response.py +12 -12
  136. thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py +12 -12
  137. thestage/services/clients/thestage_api/dtos/validate_token_response.py +11 -0
  138. thestage/services/config_provider/__init__.py +0 -0
  139. thestage/services/config_provider/config_provider.py +237 -209
  140. thestage/services/connect/connect_service.py +196 -207
  141. thestage/services/connect/dto/remote_server_config.py +9 -9
  142. thestage/services/container/__init__.py +0 -0
  143. thestage/services/container/container_service.py +374 -391
  144. thestage/services/container/mapper/__init__.py +0 -0
  145. thestage/services/container/mapper/container_mapper.py +30 -30
  146. thestage/services/core_files/config_entity.py +26 -20
  147. thestage/services/filesystem_service.py +133 -133
  148. thestage/services/instance/__init__.py +0 -0
  149. thestage/services/instance/instance_service.py +303 -317
  150. thestage/services/instance/mapper/__init__.py +0 -0
  151. thestage/services/instance/mapper/instance_mapper.py +24 -24
  152. thestage/services/instance/mapper/selfhosted_mapper.py +33 -33
  153. thestage/services/logging/byte_print_style.py +5 -5
  154. thestage/services/logging/dto/log_message.py +15 -15
  155. thestage/services/logging/dto/log_type.py +6 -6
  156. thestage/services/logging/exception/log_polling_exception.py +6 -6
  157. thestage/services/logging/logging_constants.py +3 -3
  158. thestage/services/logging/logging_service.py +367 -395
  159. thestage/services/project/__init__.py +0 -0
  160. thestage/services/project/dto/inference_simulator_dto.py +22 -22
  161. thestage/services/project/dto/inference_simulator_model_dto.py +20 -20
  162. thestage/services/project/dto/project_config.py +14 -14
  163. thestage/services/project/mapper/__init__.py +0 -0
  164. thestage/services/project/mapper/project_inference_simulator_mapper.py +21 -21
  165. thestage/services/project/mapper/project_inference_simulator_model_mapper.py +21 -21
  166. thestage/services/project/mapper/project_task_mapper.py +22 -22
  167. thestage/services/project/project_service.py +1260 -1280
  168. thestage/services/remote_server_service.py +609 -610
  169. thestage/services/service_factory.py +97 -103
  170. thestage/services/task/dto/task_dto.py +40 -40
  171. thestage/services/validation_service.py +61 -56
  172. {thestage-0.5.46.dist-info → thestage-0.5.49.dist-info}/LICENSE.txt +12 -12
  173. {thestage-0.5.46.dist-info → thestage-0.5.49.dist-info}/METADATA +3 -4
  174. thestage-0.5.49.dist-info/RECORD +176 -0
  175. {thestage-0.5.46.dist-info → thestage-0.5.49.dist-info}/WHEEL +1 -1
  176. thestage/exceptions/http_error_exception.py +0 -12
  177. thestage/services/clients/thestage_api/core/api_client_abstract.py +0 -91
  178. thestage-0.5.46.dist-info/RECORD +0 -172
  179. {thestage-0.5.46.dist-info → thestage-0.5.49.dist-info}/entry_points.txt +0 -0
thestage/.env ADDED
@@ -0,0 +1,5 @@
1
+ THESTAGE_CONFIG_DIR=.thestage
2
+ THESTAGE_CONFIG_FILE=config.json
3
+ THESTAGE_API_URL=https://backend-staging.thestage.ai
4
+ THESTAGE_API_URL=https://backend.thestage.ai
5
+ LOG_FILE=thestage.log
thestage/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- from . import *
2
- __app_name__ = "thestage"
3
- __version__ = "0.5.46"
1
+ from . import *
2
+ __app_name__ = "thestage"
3
+ __version__ = "0.5.49"
thestage/__main__.py CHANGED
@@ -1,9 +1,9 @@
1
- import thestage.main as main
2
-
3
-
4
- def start():
5
- main.main()
6
-
7
-
8
- if __name__ == "__main__":
9
- start()
1
+ import thestage.main as main
2
+
3
+
4
+ def start():
5
+ main.main()
6
+
7
+
8
+ if __name__ == "__main__":
9
+ start()
@@ -0,0 +1,56 @@
1
+ from enum import Enum
2
+
3
+ class CliCommand(str, Enum):
4
+ VERSION = "VERSION"
5
+ CONNECT = "CONNECT"
6
+ PROJECT_CLONE = "PROJECT_CLONE"
7
+ PROJECT_INIT = "PROJECT_INIT"
8
+ PROJECT_RUN = "PROJECT_RUN"
9
+ PROJECT_CHECKOUT = "PROJECT_CHECKOUT"
10
+ PROJECT_PULL = "PROJECT_PULL"
11
+ PROJECT_RESET = "PROJECT_RESET"
12
+ PROJECT_INFERENCE_SIMULATOR_RUN = "PROJECT_INFERENCE_SIMULATOR_RUN"
13
+ PROJECT_INFERENCE_SIMULATOR_SAVE_METADATA = "PROJECT_INFERENCE_SIMULATOR_SAVE_METADATA"
14
+ PROJECT_INFERENCE_SIMULATOR_PUSH = "PROJECT_INFERENCE_SIMULATOR_PUSH"
15
+ PROJECT_INFERENCE_SIMULATOR_LS = "PROJECT_INFERENCE_SIMULATOR_LS"
16
+ PROJECT_INFERENCE_SIMULATOR_LOGS = "PROJECT_INFERENCE_SIMULATOR_LOGS"
17
+ PROJECT_MODEL_LS = "PROJECT_MODEL_LS"
18
+ PROJECT_MODEL_DEPLOY_INSTANCE = "PROJECT_MODEL_DEPLOY_INSTANCE"
19
+ PROJECT_MODEL_DEPLOY_SAGEMAKER = "PROJECT_MODEL_DEPLOY_SAGEMAKER"
20
+ PROJECT_TASK_CANCEL = "PROJECT_TASK_CANCEL"
21
+ PROJECT_TASK_LS = "PROJECT_TASK_LS"
22
+ PROJECT_TASK_LOGS = "PROJECT_TASK_LOGS"
23
+ PROJECT_CONFIG_SET_DEFAULT_CONTAINER = "PROJECT_CONFIG_SET_DEFAULT_CONTAINER"
24
+ PROJECT_CONFIG_GET = "PROJECT_CONFIG_GET"
25
+ CONTAINER_LS = "CONTAINER_LS"
26
+ CONTAINER_INFO = "CONTAINER_INFO"
27
+ CONTAINER_CONNECT = "CONTAINER_CONNECT"
28
+ CONTAINER_UPLOAD = "CONTAINER_UPLOAD"
29
+ CONTAINER_DOWNLOAD = "CONTAINER_DOWNLOAD"
30
+ CONTAINER_START = "CONTAINER_START"
31
+ CONTAINER_STOP = "CONTAINER_STOP"
32
+ CONTAINER_RESTART = "CONTAINER_RESTART"
33
+ CONTAINER_LOGS = "CONTAINER_LOGS"
34
+ INSTANCE_RENTED_LS = "INSTANCE_RENTED_LS"
35
+ INSTANCE_RENTED_CONNECT = "INSTANCE_RENTED_CONNECT"
36
+ INSTANCE_SELF_HOSTED_LS = "INSTANCE_SELF_HOSTED_LS"
37
+ INSTANCE_SELF_HOSTED_CONNECT = "INSTANCE_SELF_HOSTED_CONNECT"
38
+ CONFIG_GET = "CONFIG_GET"
39
+ CONFIG_SET = "CONFIG_SET"
40
+ CONFIG_CLEAR = "CONFIG_CLEAR"
41
+ CONFIG_UPLOAD_SSH_KEY = "CONFIG_UPLOAD_SSH_KEY"
42
+
43
+
44
+ class CliCommandAvailability(str, Enum):
45
+ ALLOWED = "ALLOWED"
46
+ RESTRICTED = "RESTRICTED"
47
+ DEPRECATED = "DEPRECATED"
48
+
49
+
50
+ ALWAYS_AVAILABLE_COMMANDS = [
51
+ CliCommand.VERSION,
52
+ CliCommand.PROJECT_CONFIG_GET,
53
+ CliCommand.CONFIG_GET,
54
+ CliCommand.CONFIG_SET,
55
+ CliCommand.CONFIG_CLEAR,
56
+ ]
@@ -0,0 +1,51 @@
1
+ from typing import Callable
2
+
3
+ import typer
4
+
5
+ from thestage.cli_command import CliCommand, CliCommandAvailability
6
+ from thestage.color_scheme.color_scheme import ColorScheme
7
+ from thestage.config import config_storage
8
+ from rich import print
9
+
10
+
11
+ def cli_command(command_id: CliCommand):
12
+ def decorator(func: Callable):
13
+ setattr(func, "__cli_command__", command_id)
14
+ return func
15
+ return decorator
16
+
17
+
18
+ def get_command_metadata(command_id: CliCommand) -> dict:
19
+ return {
20
+ "rich_help_panel": get_command_help_panel(command_id),
21
+ "deprecated": is_command_deprecated(command_id),
22
+ }
23
+
24
+
25
+ def get_command_group_help_panel() -> str:
26
+ return "Command Groups"
27
+
28
+
29
+ def get_command_help_panel(command: CliCommand) -> str:
30
+ if config_storage.APP_CONFIG.runtime.allowed_commands.get(command) == CliCommandAvailability.ALLOWED:
31
+ return "Allowed Commands"
32
+ if config_storage.APP_CONFIG.runtime.allowed_commands.get(command) == CliCommandAvailability.RESTRICTED:
33
+ return "Restricted Commands"
34
+ if config_storage.APP_CONFIG.runtime.allowed_commands.get(command) == CliCommandAvailability.DEPRECATED:
35
+ return "Deprecated Commands"
36
+
37
+
38
+ def is_command_deprecated(command: CliCommand) -> bool:
39
+ if config_storage.APP_CONFIG.runtime.allowed_commands.get(command) == CliCommandAvailability.DEPRECATED:
40
+ return True
41
+ return False
42
+
43
+
44
+ def check_command_permission(executed_command: CliCommand):
45
+ if config_storage.APP_CONFIG.runtime.is_token_valid == False and executed_command != CliCommand.CONFIG_SET:
46
+ print(f"[{ColorScheme.WARNING.value}]Your API Token is not valid. You can update the token using 'thestage config set' command[{ColorScheme.WARNING.value}]")
47
+
48
+ is_allowed = config_storage.APP_CONFIG.runtime.allowed_commands.get(executed_command) == CliCommandAvailability.ALLOWED
49
+ if not is_allowed:
50
+ typer.echo("Action is not allowed")
51
+ raise typer.Exit(code=1)
@@ -1,7 +1,7 @@
1
- from enum import Enum
2
-
3
- # https://rich.readthedocs.io/en/stable/appendix/colors.html
4
- class ColorScheme(str, Enum):
5
- GIT_HEADLESS = "orange_red1"
6
- WARNING = "orange_red1"
7
- USEFUL_INFO = "deep_sky_blue1"
1
+ from enum import Enum
2
+
3
+ # https://rich.readthedocs.io/en/stable/appendix/colors.html
4
+ class ColorScheme(str, Enum):
5
+ GIT_HEADLESS = "orange_red1"
6
+ WARNING = "orange_red1"
7
+ USEFUL_INFO = "deep_sky_blue1"
@@ -1,18 +1,18 @@
1
- # Init project settings by ENV environment variable
2
- import locale
3
- from pathlib import Path
4
-
5
-
6
- from python_gettext_translations.translations import init_translations
7
-
8
- from thestage.config.env_base import *
9
-
10
-
11
- THESTAGE_LOCAL_LANGUAGE = 'en_GB'
12
- if locale.getlocale():
13
- THESTAGE_LOCAL_LANGUAGE = locale.getlocale()[0]
14
-
15
- translation = Path(f'i18n/')
16
-
17
- if translation.exists() and translation.is_dir():
18
- init_translations(f'i18n/')
1
+ # Init project settings by ENV environment variable
2
+ import locale
3
+ from pathlib import Path
4
+
5
+
6
+ from python_gettext_translations.translations import init_translations
7
+
8
+ from thestage.config.env_base import *
9
+
10
+
11
+ THESTAGE_LOCAL_LANGUAGE = 'en_GB'
12
+ if locale.getlocale():
13
+ THESTAGE_LOCAL_LANGUAGE = locale.getlocale()[0]
14
+
15
+ translation = Path(f'i18n/')
16
+
17
+ if translation.exists() and translation.is_dir():
18
+ init_translations(f'i18n/')
@@ -0,0 +1,5 @@
1
+ from typing import Optional
2
+
3
+ from thestage.services.core_files.config_entity import ConfigEntity
4
+
5
+ APP_CONFIG: Optional[ConfigEntity] = None
@@ -1,7 +1,7 @@
1
- import os
2
-
3
- THESTAGE_CONFIG_DIR = os.getenv('THESTAGE_CONFIG_DIR', '.thestage')
4
- THESTAGE_CONFIG_FILE = os.getenv('THESTAGE_CONFIG_FILE', 'config.json')
5
- THESTAGE_AUTH_TOKEN = os.getenv('THESTAGE_AUTH_TOKEN', None)
6
- THESTAGE_LOGGING_FILE = os.getenv('THESTAGE_LOGGING_FILE', 'thestage.log')
7
- THESTAGE_API_URL = os.getenv('THESTAGE_API_URL', 'https://backend.thestage.ai')
1
+ import os
2
+
3
+ THESTAGE_CONFIG_DIR = os.getenv('THESTAGE_CONFIG_DIR', '.thestage')
4
+ THESTAGE_CONFIG_FILE = os.getenv('THESTAGE_CONFIG_FILE', 'config.json')
5
+ THESTAGE_AUTH_TOKEN = os.getenv('THESTAGE_AUTH_TOKEN', None)
6
+ THESTAGE_LOGGING_FILE = os.getenv('THESTAGE_LOGGING_FILE', 'thestage.log')
7
+ THESTAGE_API_URL = os.getenv('THESTAGE_API_URL', 'https://backend.thestage.ai')
File without changes
@@ -1,63 +1,67 @@
1
- from pathlib import Path
2
- from typing import Optional
3
-
4
- from thestage.i18n.translation import __
5
- from thestage.helpers.logger.app_logger import app_logger
6
- from thestage.controllers.utils_controller import get_current_directory, validate_config_and_get_service_factory
7
- from thestage import __app_name__, __version__
8
-
9
- import typer
10
-
11
- from thestage.services.connect.connect_service import ConnectService
12
-
13
- app = typer.Typer(no_args_is_help=True)
14
-
15
-
16
- @app.command(no_args_is_help=False)
17
- def version():
18
- """
19
- Returns the application's name and version
20
- """
21
- app_logger.info(f'Start version from {get_current_directory()}')
22
- typer.echo(
23
- __("%app_name% v%version%", {'app_name': __app_name__, 'version': __version__}))
24
- raise typer.Exit(0)
25
-
26
-
27
- @app.command(name="connect", no_args_is_help=True, help=__("Connect to server instance or container using unique ID"))
28
- def connect(
29
- uid: Optional[str] = typer.Argument(
30
- help=__("Unique ID of server instance or container"), ),
31
- username: Optional[str] = typer.Option(
32
- None,
33
- '--username',
34
- '-u',
35
- help=__("Username for the server instance (required when connecting to self-hosted instance)"),
36
- is_eager=False,
37
- ),
38
- private_ssh_key_path: str = typer.Option(
39
- None,
40
- "--private-key-path",
41
- "-pk",
42
- help=__("Path to private key that will be accepted by remote server (optional)"),
43
- is_eager=False,
44
- ),
45
- ):
46
- """
47
- Connects to entity with a unique ID
48
- """
49
- app_logger.info(f'Connect to some entity with UID')
50
-
51
- if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
52
- typer.echo(f'No file found at provided path {private_ssh_key_path}')
53
- raise typer.Exit(1)
54
-
55
- service_factory = validate_config_and_get_service_factory()
56
-
57
- connect_service: ConnectService = service_factory.get_connect_service()
58
-
59
- connect_service.connect_to_entity(uid=uid, username=username, private_key_path=private_ssh_key_path)
60
-
61
-
62
- app_logger.info(f'Stop connect to entity')
63
- raise typer.Exit(0)
1
+ from pathlib import Path
2
+ from typing import Optional
3
+
4
+ from thestage.cli_command import CliCommand
5
+ from thestage.cli_command_helper import get_command_metadata, check_command_permission
6
+ from thestage.i18n.translation import __
7
+ from thestage.helpers.logger.app_logger import app_logger
8
+ from thestage.controllers.utils_controller import get_current_directory, validate_config_and_get_service_factory
9
+ from thestage import __app_name__, __version__
10
+
11
+ import typer
12
+
13
+ from thestage.services.connect.connect_service import ConnectService
14
+
15
+ app = typer.Typer(no_args_is_help=True,)
16
+
17
+
18
+ @app.command(name='version', help="Get application's name and version", no_args_is_help=False, **get_command_metadata(CliCommand.VERSION))
19
+ def version():
20
+ command_name = CliCommand.VERSION
21
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
22
+ check_command_permission(command_name)
23
+
24
+ typer.echo(f"{__app_name__} v{__version__}")
25
+ raise typer.Exit(0)
26
+
27
+
28
+ @app.command(name="connect", no_args_is_help=True, help=__("Connect to server instance or container or task"), **get_command_metadata(CliCommand.CONNECT))
29
+ def connect(
30
+ uid: Optional[str] = typer.Argument(
31
+ help=__("Unique ID of server instance or container or task ID"), ),
32
+ username: Optional[str] = typer.Option(
33
+ None,
34
+ '--username',
35
+ '-u',
36
+ help=__("Username for the server instance (required when connecting to self-hosted instance)"),
37
+ is_eager=False,
38
+ ),
39
+ private_ssh_key_path: str = typer.Option(
40
+ None,
41
+ "--private-key-path",
42
+ "-pk",
43
+ help=__("Path to private key that will be accepted by remote server (optional)"),
44
+ is_eager=False,
45
+ ),
46
+ ):
47
+ command_name = CliCommand.CONNECT
48
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
49
+ check_command_permission(command_name)
50
+
51
+ if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
52
+ typer.echo(f'No file found at provided path {private_ssh_key_path}')
53
+ raise typer.Exit(1)
54
+
55
+ service_factory = validate_config_and_get_service_factory()
56
+
57
+ connect_service: ConnectService = service_factory.get_connect_service()
58
+
59
+ connect_service.connect_to_entity(
60
+ uid=uid,
61
+ username=username,
62
+ private_key_path=private_ssh_key_path
63
+ )
64
+
65
+
66
+ app_logger.info(f'Stop connect to entity')
67
+ raise typer.Exit(0)
@@ -1,145 +1,137 @@
1
- import os
2
- from pathlib import Path
3
-
4
- import click
5
- from thestage.services.core_files.config_entity import ConfigEntity
6
-
7
- from thestage.entities.enums.yes_no_response import YesOrNoResponse
8
- from thestage.i18n.translation import __
9
- from thestage.helpers.logger.app_logger import app_logger, get_log_path_from_os
10
- from thestage.services.config_provider.config_provider import ConfigProvider
11
- from thestage.services.connect.connect_service import ConnectService
12
- from thestage.services.service_factory import ServiceFactory
13
- from thestage.controllers.utils_controller import get_current_directory, validate_config_and_get_service_factory
14
-
15
- import typer
16
-
17
- app = typer.Typer(no_args_is_help=True, help=__("Manage configuration settings"))
18
-
19
-
20
- @app.command(name='get', no_args_is_help=False, help=__("Display all configuration settings"))
21
- def config_get():
22
- """
23
- Lists all configuration settings
24
- """
25
- app_logger.info(f'Start config from {get_current_directory()}')
26
-
27
- local_path = get_current_directory()
28
- config_provider = ConfigProvider(local_path=local_path)
29
- config: ConfigEntity = config_provider.get_full_config()
30
-
31
- if not config:
32
- typer.echo(__('No configuration found'))
33
- raise typer.Exit(1)
34
-
35
- config_provider.save_config(config=config)
36
-
37
- typer.echo(__('THESTAGE TOKEN: %token%', {'token': config.main.thestage_auth_token or ''}))
38
- typer.echo(__('THESTAGE API LINK: %link%', {'link': config.main.thestage_api_url or ''}))
39
-
40
- if config.runtime.config_global_path:
41
- typer.echo(__('CONFIG PATH: %path%', {'path': str(config.runtime.config_global_path or '') + f'/config.json'}))
42
-
43
- typer.echo(__('APPLICATION LOGS PATH: %path%', {'path': str(get_log_path_from_os())}))
44
-
45
- raise typer.Exit(0)
46
-
47
-
48
- @app.command(name='set', no_args_is_help=True, help=__("Update configuration settings"))
49
- def config_set(
50
- token: str = typer.Option(
51
- None,
52
- "--api-token",
53
- "-t",
54
- help=__("Set or update API token"),
55
- is_eager=False,
56
- ),
57
- ):
58
- """
59
- Updates configuration settings
60
- """
61
- app_logger.info(f'Start config from {get_current_directory()}')
62
-
63
- config_provider = ConfigProvider(local_path=get_current_directory())
64
- service_factory = ServiceFactory(config_provider)
65
-
66
- app_service = service_factory.get_app_config_service()
67
-
68
- if token:
69
- app_service.app_change_token(config=config_provider.get_full_config(), token=token)
70
-
71
- typer.echo('Configuration updated successfully')
72
- raise typer.Exit(0)
73
-
74
-
75
- @app.command(name='clear', no_args_is_help=False, help=__("Clear configuration"))
76
- def config_clear():
77
- """
78
- Clears all configuration settings
79
- """
80
- app_logger.info(f'Start config from {get_current_directory()}')
81
- local_path = get_current_directory()
82
- config_provider = ConfigProvider(local_path=local_path)
83
- config_dir = config_provider.get_full_config().runtime.config_global_path
84
- config_provider.clear_config()
85
- typer.echo(f'Removed {config_dir}')
86
-
87
- raise typer.Exit(0)
88
-
89
-
90
- @app.command(name='upload-ssh-key', no_args_is_help=True, help=__("Send your public SSH key to the platform and / or rented server instance"))
91
- def config_set(
92
- ssh_public_key: str = typer.Argument(
93
- help=__("Path to your public SSH key file or your public SSH key contents"),
94
- ),
95
- instance_rented_slug: str = typer.Option(
96
- None,
97
- "--instance-uid",
98
- "-uid",
99
- help=__("Unique ID of your rented instance to add the key to (optional)"),
100
- is_eager=False,
101
- )
102
- ):
103
- """
104
- Sends SSH key to the platform
105
- """
106
-
107
- app_logger.info(f'Start config from {get_current_directory()}')
108
-
109
- config_provider = ConfigProvider(local_path=get_current_directory())
110
- service_factory = ServiceFactory(config_provider)
111
- connect_service: ConnectService = service_factory.get_connect_service()
112
-
113
- is_path_provided_confirmed = False
114
- ssh_key_contents = ssh_public_key
115
-
116
- if ssh_public_key.startswith("/") or ssh_public_key.startswith("~") or ssh_public_key.endswith(".pub") or len(ssh_public_key) < 30:
117
- is_path_provided_confirmed = True
118
-
119
- ssh_key_path = Path(ssh_public_key).absolute()
120
- if is_path_provided_confirmed and not ssh_key_path.exists():
121
- typer.echo(f"No key was found at {ssh_key_path}")
122
- raise typer.Exit(1)
123
-
124
- if is_path_provided_confirmed or ssh_key_path.exists():
125
- if '.' not in ssh_key_path.name:
126
- proceed_with_no_extension: YesOrNoResponse = typer.prompt(
127
- text=f"File '{ssh_key_path.name}' probably contains a private key. Proceed?",
128
- show_choices=True,
129
- default=YesOrNoResponse.YES.value,
130
- type=click.Choice([r.value for r in YesOrNoResponse]),
131
- show_default=True,
132
- )
133
- if proceed_with_no_extension == YesOrNoResponse.NO:
134
- raise typer.Exit(0)
135
- ssh_key_contents = ssh_key_path.open("r").read()
136
- if 'private key-----' in ssh_key_contents.lower():
137
- typer.echo(f"{ssh_key_path} is identified as a private key. Please provide a public SSH key.")
138
- raise typer.Exit(1)
139
-
140
- connect_service.upload_ssh_key(
141
- public_key_contents=ssh_key_contents,
142
- instance_slug=instance_rented_slug,
143
- )
144
-
145
- raise typer.Exit(0)
1
+ from pathlib import Path
2
+
3
+ import click
4
+
5
+ from thestage.cli_command import CliCommand
6
+ from thestage.cli_command_helper import get_command_metadata, check_command_permission
7
+ from thestage.services.core_files.config_entity import ConfigEntity
8
+
9
+ from thestage.entities.enums.yes_no_response import YesOrNoResponse
10
+ from thestage.i18n.translation import __
11
+ from thestage.helpers.logger.app_logger import app_logger, get_log_path_from_os
12
+ from thestage.services.connect.connect_service import ConnectService
13
+ from thestage.services.service_factory import ServiceFactory
14
+ from thestage.controllers.utils_controller import get_current_directory
15
+
16
+ import typer
17
+
18
+ app = typer.Typer(no_args_is_help=True, help=__("Manage configuration settings"))
19
+
20
+
21
+ @app.command(name='get', no_args_is_help=False, help=__("Display all configuration settings"), **get_command_metadata(CliCommand.CONFIG_GET))
22
+ def config_get():
23
+ command_name = CliCommand.CONFIG_GET
24
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
25
+ check_command_permission(command_name)
26
+
27
+ config_provider = ServiceFactory().get_config_provider()
28
+ config: ConfigEntity = config_provider.get_config()
29
+
30
+ if not config:
31
+ typer.echo(__('No configuration found'))
32
+ raise typer.Exit(1)
33
+
34
+ config_provider.save_config()
35
+
36
+ typer.echo(__('THESTAGE TOKEN: %token%', {'token': config.main.thestage_auth_token or ''}))
37
+ typer.echo(__('THESTAGE API LINK: %link%', {'link': config.main.thestage_api_url or ''}))
38
+
39
+ if config.runtime.config_global_path:
40
+ typer.echo(__('CONFIG PATH: %path%', {'path': str(config.runtime.config_global_path or '') + f'/config.json'}))
41
+
42
+ typer.echo(__('APPLICATION LOGS PATH: %path%', {'path': str(get_log_path_from_os())}))
43
+
44
+ raise typer.Exit(0)
45
+
46
+
47
+ @app.command(name='set', no_args_is_help=True, help=__("Update configuration settings"), **get_command_metadata(CliCommand.CONFIG_SET))
48
+ def config_set(
49
+ token: str = typer.Option(
50
+ None,
51
+ "--api-token",
52
+ "-t",
53
+ help=__("Set or update API token"),
54
+ is_eager=False,
55
+ ),
56
+ ):
57
+ command_name = CliCommand.CONFIG_SET
58
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
59
+ check_command_permission(command_name)
60
+
61
+ service_factory = ServiceFactory()
62
+ app_service = service_factory.get_app_config_service()
63
+
64
+ if token:
65
+ app_service.app_change_token(token=token)
66
+
67
+ typer.echo('Configuration updated successfully')
68
+ raise typer.Exit(0)
69
+
70
+
71
+ @app.command(name='clear', no_args_is_help=False, help=__("Clear configuration"), **get_command_metadata(CliCommand.CONFIG_CLEAR))
72
+ def config_clear():
73
+ command_name = CliCommand.CONFIG_CLEAR
74
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
75
+ check_command_permission(command_name)
76
+
77
+ config_provider = ServiceFactory().get_config_provider()
78
+ config_dir = config_provider.get_config().runtime.config_global_path
79
+ config_provider.clear_config()
80
+ typer.echo(f'Removed {config_dir}')
81
+
82
+ raise typer.Exit(0)
83
+
84
+
85
+ @app.command(name='upload-ssh-key', no_args_is_help=True, help=__("Send your public SSH key to the platform and / or rented server instance"), **get_command_metadata(CliCommand.CONFIG_UPLOAD_SSH_KEY))
86
+ def upload_ssh_key(
87
+ ssh_public_key: str = typer.Argument(
88
+ help=__("Path to your public SSH key file or your public SSH key contents"),
89
+ ),
90
+ instance_rented_slug: str = typer.Option(
91
+ None,
92
+ "--instance-uid",
93
+ "-uid",
94
+ help=__("Unique ID of your rented instance to add the key to (optional)"),
95
+ is_eager=False,
96
+ )
97
+ ):
98
+ command_name = CliCommand.CONFIG_UPLOAD_SSH_KEY
99
+ app_logger.info(f'Running {command_name} from {get_current_directory()}')
100
+ check_command_permission(command_name)
101
+
102
+ service_factory = ServiceFactory()
103
+ connect_service: ConnectService = service_factory.get_connect_service()
104
+
105
+ is_path_provided_confirmed = False
106
+ ssh_key_contents = ssh_public_key
107
+
108
+ if ssh_public_key.startswith("/") or ssh_public_key.startswith("~") or ssh_public_key.endswith(".pub") or len(ssh_public_key) < 30:
109
+ is_path_provided_confirmed = True
110
+
111
+ ssh_key_path = Path(ssh_public_key).absolute()
112
+ if is_path_provided_confirmed and not ssh_key_path.exists():
113
+ typer.echo(f"No key was found at {ssh_key_path}")
114
+ raise typer.Exit(1)
115
+
116
+ if is_path_provided_confirmed or ssh_key_path.exists():
117
+ if '.' not in ssh_key_path.name:
118
+ proceed_with_no_extension: YesOrNoResponse = typer.prompt(
119
+ text=f"File '{ssh_key_path.name}' probably contains a private key. Proceed?",
120
+ show_choices=True,
121
+ default=YesOrNoResponse.YES.value,
122
+ type=click.Choice([r.value for r in YesOrNoResponse]),
123
+ show_default=True,
124
+ )
125
+ if proceed_with_no_extension == YesOrNoResponse.NO:
126
+ raise typer.Exit(0)
127
+ ssh_key_contents = ssh_key_path.open("r").read()
128
+ if 'private key-----' in ssh_key_contents.lower():
129
+ typer.echo(f"{ssh_key_path} is identified as a private key. Please provide a public SSH key.")
130
+ raise typer.Exit(1)
131
+
132
+ connect_service.upload_ssh_key(
133
+ public_key_contents=ssh_key_contents,
134
+ instance_slug=instance_rented_slug,
135
+ )
136
+
137
+ raise typer.Exit(0)