thestage 0.5.471__py3-none-any.whl → 0.6.2__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 -5
  2. thestage/__init__.py +3 -4
  3. thestage/__main__.py +9 -9
  4. thestage/cli_command.py +56 -56
  5. thestage/cli_command_helper.py +51 -51
  6. thestage/color_scheme/color_scheme.py +7 -7
  7. thestage/config/__init__.py +18 -18
  8. thestage/config/config_storage.py +5 -5
  9. thestage/config/env_base.py +7 -7
  10. thestage/controllers/__init__.py +0 -0
  11. thestage/controllers/base_controller.py +67 -67
  12. thestage/controllers/config_controller.py +137 -137
  13. thestage/controllers/container_controller.py +389 -389
  14. thestage/controllers/instance_controller.py +183 -183
  15. thestage/controllers/project_controller.py +810 -783
  16. thestage/controllers/utils_controller.py +32 -32
  17. thestage/debug_main.dist.py +28 -28
  18. thestage/entities/__init__.py +0 -0
  19. thestage/entities/container.py +17 -17
  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 -19
  30. thestage/entities/self_hosted_instance.py +18 -18
  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 -14
  43. thestage/helpers/logger/__init__.py +0 -0
  44. thestage/helpers/logger/app_logger.py +50 -50
  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 -36
  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 -87
  53. thestage/services/app_config_service.py +52 -52
  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 +436 -331
  57. thestage/services/clients/thestage_api/__init__.py +0 -0
  58. thestage/services/clients/thestage_api/api_client.py +718 -720
  59. thestage/services/clients/thestage_api/core/api_client_core.py +108 -108
  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 -11
  138. thestage/services/config_provider/__init__.py +0 -0
  139. thestage/services/config_provider/config_provider.py +237 -237
  140. thestage/services/connect/connect_service.py +196 -196
  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 -374
  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 -26
  147. thestage/services/filesystem_service.py +133 -133
  148. thestage/services/instance/__init__.py +0 -0
  149. thestage/services/instance/instance_service.py +303 -303
  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 -367
  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 +1253 -1241
  168. thestage/services/remote_server_service.py +609 -609
  169. thestage/services/service_factory.py +97 -97
  170. thestage/services/task/dto/task_dto.py +40 -40
  171. thestage/services/validation_service.py +61 -61
  172. {thestage-0.5.471.dist-info → thestage-0.6.2.dist-info}/LICENSE.txt +12 -12
  173. {thestage-0.5.471.dist-info → thestage-0.6.2.dist-info}/METADATA +1 -1
  174. thestage-0.6.2.dist-info/RECORD +176 -0
  175. {thestage-0.5.471.dist-info → thestage-0.6.2.dist-info}/WHEEL +1 -1
  176. thestage/debug_tests.py +0 -12
  177. thestage/services/clients/.DS_Store +0 -0
  178. thestage-0.5.471.dist-info/RECORD +0 -178
  179. {thestage-0.5.471.dist-info → thestage-0.6.2.dist-info}/entry_points.txt +0 -0
@@ -1,137 +1,137 @@
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)
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)