thestage 0.6.4__py3-none-any.whl → 0.6.6__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.
- thestage/__init__.py +1 -1
- thestage/color_scheme/color_scheme.py +1 -0
- thestage/controllers/base_controller.py +4 -3
- thestage/controllers/config_controller.py +16 -4
- thestage/controllers/container_controller.py +147 -49
- thestage/controllers/instance_controller.py +35 -9
- thestage/controllers/project_controller.py +334 -86
- thestage/entities/container.py +5 -3
- thestage/entities/project_inference_simulator.py +2 -1
- thestage/entities/project_inference_simulator_model.py +1 -1
- thestage/entities/project_task.py +2 -3
- thestage/entities/rented_instance.py +2 -2
- thestage/entities/self_hosted_instance.py +2 -2
- thestage/helpers/error_handler.py +3 -3
- thestage/services/clients/git/git_client.py +8 -12
- thestage/services/clients/thestage_api/api_client.py +144 -109
- thestage/services/clients/thestage_api/dtos/base_controller/connect_resolve_response.py +21 -0
- thestage/services/clients/thestage_api/dtos/container_param_request.py +1 -1
- thestage/services/clients/thestage_api/dtos/container_response.py +1 -21
- thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_request.py +2 -1
- thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +7 -1
- thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +0 -1
- thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_request.py +1 -0
- thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +2 -1
- thestage/services/clients/thestage_api/dtos/inference_controller/{inference_simulator_list_for_project_request.py → inference_simulator_list_request.py} +3 -2
- thestage/services/clients/thestage_api/dtos/inference_controller/{inference_simulator_list_for_project_response.py → inference_simulator_list_response.py} +1 -1
- thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_request.py +2 -1
- thestage/services/clients/thestage_api/dtos/instance_rented_response.py +4 -37
- thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_request.py +3 -3
- thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_request.py +3 -11
- thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py +1 -0
- thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py +2 -1
- thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_request.py +2 -4
- thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py +5 -3
- thestage/services/clients/thestage_api/dtos/project_response.py +3 -15
- thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +2 -20
- thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_request.py +4 -2
- thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_response.py +1 -1
- thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py +4 -1
- thestage/services/clients/thestage_api/dtos/task_controller/task_view_response.py +0 -2
- thestage/services/config_provider/config_provider.py +2 -2
- thestage/services/connect/connect_service.py +76 -73
- thestage/services/container/container_service.py +23 -19
- thestage/services/container/mapper/container_mapper.py +2 -1
- thestage/services/instance/instance_service.py +13 -20
- thestage/services/instance/mapper/instance_mapper.py +1 -3
- thestage/services/instance/mapper/selfhosted_mapper.py +3 -4
- thestage/services/logging/logging_service.py +40 -40
- thestage/services/project/dto/inference_simulator_dto.py +1 -10
- thestage/services/project/dto/inference_simulator_model_dto.py +2 -10
- thestage/services/project/dto/project_config.py +3 -2
- thestage/services/project/mapper/project_inference_simulator_mapper.py +1 -0
- thestage/services/project/mapper/project_inference_simulator_model_mapper.py +3 -3
- thestage/services/project/mapper/project_task_mapper.py +2 -3
- thestage/services/project/project_service.py +161 -131
- thestage/services/remote_server_service.py +1 -0
- thestage/services/task/dto/task_dto.py +3 -23
- {thestage-0.6.4.dist-info → thestage-0.6.6.dist-info}/METADATA +3 -2
- {thestage-0.6.4.dist-info → thestage-0.6.6.dist-info}/RECORD +63 -72
- {thestage-0.6.4.dist-info → thestage-0.6.6.dist-info}/WHEEL +1 -1
- thestage/services/clients/thestage_api/dtos/cloud_provider_region.py +0 -19
- thestage/services/clients/thestage_api/dtos/docker_container_assigned_device.py +0 -10
- thestage/services/clients/thestage_api/dtos/enums/currency_type.py +0 -10
- thestage/services/clients/thestage_api/dtos/enums/daemon_status.py +0 -9
- thestage/services/clients/thestage_api/dtos/enums/disk_type.py +0 -7
- thestage/services/clients/thestage_api/dtos/enums/drive_type.py +0 -7
- thestage/services/clients/thestage_api/dtos/enums/instance_type.py +0 -7
- thestage/services/clients/thestage_api/dtos/enums/location_region.py +0 -11
- thestage/services/clients/thestage_api/dtos/enums/power_status.py +0 -10
- thestage/services/clients/thestage_api/dtos/price_definition.py +0 -14
- {thestage-0.6.4.dist-info → thestage-0.6.6.dist-info}/entry_points.txt +0 -0
- {thestage-0.6.4.dist-info → thestage-0.6.6.dist-info/licenses}/LICENSE.txt +0 -0
|
@@ -3,21 +3,18 @@ import typer
|
|
|
3
3
|
|
|
4
4
|
from thestage.cli_command import CliCommand
|
|
5
5
|
from thestage.cli_command_helper import check_command_permission
|
|
6
|
+
from thestage.color_scheme.color_scheme import ColorScheme
|
|
6
7
|
from thestage.i18n.translation import __
|
|
7
8
|
from thestage.services.clients.thestage_api.core.http_client_exception import HttpClientException
|
|
8
|
-
from thestage.services.clients.thestage_api.dtos.enums.container_status import DockerContainerStatus
|
|
9
|
-
from thestage.services.clients.thestage_api.dtos.enums.selfhosted_status import SelfhostedBusinessStatus
|
|
10
9
|
from thestage.services.clients.thestage_api.dtos.enums.instance_rented_status import InstanceRentedBusinessStatus
|
|
11
10
|
from thestage.services.abstract_service import AbstractService
|
|
12
11
|
from thestage.helpers.error_handler import error_handler
|
|
13
12
|
from thestage.services.clients.thestage_api.api_client import TheStageApiClient
|
|
14
|
-
from thestage.services.clients.thestage_api.dtos.enums.task_status import TaskStatus
|
|
15
13
|
from thestage.services.clients.thestage_api.dtos.instance_rented_response import InstanceRentedDto
|
|
16
14
|
from thestage.services.container.container_service import ContainerService
|
|
17
15
|
from thestage.services.instance.instance_service import InstanceService
|
|
18
16
|
from thestage.services.logging.logging_service import LoggingService
|
|
19
|
-
from
|
|
20
|
-
from thestage.helpers.logger.app_logger import app_logger
|
|
17
|
+
from rich import print
|
|
21
18
|
|
|
22
19
|
|
|
23
20
|
class ConnectService(AbstractService):
|
|
@@ -44,107 +41,113 @@ class ConnectService(AbstractService):
|
|
|
44
41
|
@error_handler()
|
|
45
42
|
def connect_to_entity(
|
|
46
43
|
self,
|
|
47
|
-
|
|
44
|
+
input_entity_identifier: str,
|
|
48
45
|
username: Optional[str],
|
|
49
46
|
private_key_path: Optional[str],
|
|
50
47
|
):
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if
|
|
48
|
+
resolved_options = self.__thestage_api_client.resolve_connect_options(entity_identifier=input_entity_identifier)
|
|
49
|
+
entities_available_for_connect_count = 0
|
|
50
|
+
task_presence = False
|
|
51
|
+
container_presence = False
|
|
52
|
+
rented_presence = False
|
|
53
|
+
selfhosted_presence = False
|
|
54
|
+
resolved_entity_public_id = None
|
|
55
|
+
|
|
56
|
+
if resolved_options.taskMatchData:
|
|
57
|
+
for task_item in resolved_options.taskMatchData:
|
|
58
|
+
message = f"Found a task with with matching {task_item.matchedField} in status: '{task_item.frontendStatus.status_translation}' (ID: {task_item.publicId})"
|
|
59
|
+
line_color = ColorScheme.SUCCESS if task_item.canConnect else 'default'
|
|
60
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
61
|
+
if task_item.canConnect:
|
|
62
|
+
task_presence = True
|
|
63
|
+
resolved_entity_public_id = task_item.publicId
|
|
64
|
+
entities_available_for_connect_count += 1
|
|
65
|
+
|
|
66
|
+
if resolved_options.dockerContainerMatchData:
|
|
67
|
+
for container_item in resolved_options.dockerContainerMatchData:
|
|
68
|
+
message = f"Found a container with matching {container_item.matchedField} in status: '{container_item.frontendStatus.status_translation}' (ID: {container_item.publicId})"
|
|
69
|
+
line_color = ColorScheme.SUCCESS if container_item.canConnect else 'default'
|
|
70
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
71
|
+
if container_item.canConnect:
|
|
72
|
+
container_presence = True
|
|
73
|
+
resolved_entity_public_id = container_item.publicId
|
|
74
|
+
entities_available_for_connect_count += 1
|
|
75
|
+
|
|
76
|
+
if resolved_options.instanceRentedMatchData:
|
|
77
|
+
for instance_rented_item in resolved_options.instanceRentedMatchData:
|
|
78
|
+
message = f"Found a rented instance with matching {instance_rented_item.matchedField} in status: '{instance_rented_item.frontendStatus.status_translation}' (ID: {instance_rented_item.publicId})"
|
|
79
|
+
line_color = ColorScheme.SUCCESS if instance_rented_item.canConnect else 'default'
|
|
80
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
81
|
+
|
|
82
|
+
if instance_rented_item.canConnect:
|
|
83
|
+
rented_presence = True
|
|
84
|
+
resolved_entity_public_id = instance_rented_item.publicId
|
|
85
|
+
entities_available_for_connect_count += 1
|
|
86
|
+
|
|
87
|
+
if resolved_options.selfhostedInstanceMatchData:
|
|
88
|
+
for selfhosted_item in resolved_options.selfhostedInstanceMatchData:
|
|
89
|
+
message = f"Found a self-hosted instance with matching {selfhosted_item.matchedField} in status: '{selfhosted_item.frontendStatus.status_translation}' (ID: {selfhosted_item.publicId})"
|
|
90
|
+
line_color = ColorScheme.SUCCESS if selfhosted_item.canConnect else 'default'
|
|
91
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
92
|
+
|
|
93
|
+
if selfhosted_item.canConnect:
|
|
94
|
+
selfhosted_presence = True
|
|
95
|
+
resolved_entity_public_id = selfhosted_item.publicId
|
|
96
|
+
entities_available_for_connect_count += 1
|
|
97
|
+
|
|
98
|
+
if entities_available_for_connect_count > 1:
|
|
102
99
|
typer.echo("Provided identifier caused ambiguity")
|
|
103
100
|
typer.echo("Consider running a dedicated command to connect to the entity you need")
|
|
104
101
|
raise typer.Exit(code=1)
|
|
105
102
|
|
|
106
|
-
if
|
|
103
|
+
if entities_available_for_connect_count == 0:
|
|
107
104
|
typer.echo("There is nothing to connect to with the provided identifier")
|
|
108
105
|
raise typer.Exit(code=1)
|
|
109
106
|
|
|
110
107
|
if rented_presence:
|
|
111
108
|
check_command_permission(CliCommand.INSTANCE_RENTED_CONNECT)
|
|
112
|
-
typer.echo("Connecting to rented instance...")
|
|
109
|
+
typer.echo(f"Connecting to rented instance '{resolved_entity_public_id}'...")
|
|
113
110
|
self.__instance_service.connect_to_rented_instance(
|
|
114
|
-
|
|
111
|
+
instance_rented_public_id=resolved_entity_public_id,
|
|
112
|
+
instance_rented_slug=None,
|
|
115
113
|
input_ssh_key_path=private_key_path
|
|
116
114
|
)
|
|
117
115
|
|
|
118
116
|
if container_presence:
|
|
119
117
|
check_command_permission(CliCommand.CONTAINER_CONNECT)
|
|
120
|
-
typer.echo("Connecting to docker container...")
|
|
118
|
+
typer.echo(f"Connecting to docker container '{resolved_entity_public_id}'...")
|
|
121
119
|
self.__container_service.connect_to_container(
|
|
122
|
-
|
|
120
|
+
container_public_id=resolved_entity_public_id,
|
|
121
|
+
container_slug=None,
|
|
123
122
|
username=username,
|
|
124
123
|
input_ssh_key_path=private_key_path
|
|
125
124
|
)
|
|
126
125
|
|
|
127
126
|
if selfhosted_presence:
|
|
128
127
|
check_command_permission(CliCommand.INSTANCE_SELF_HOSTED_CONNECT)
|
|
129
|
-
typer.echo("Connecting to self-hosted instance...")
|
|
128
|
+
typer.echo(f"Connecting to self-hosted instance '{resolved_entity_public_id}'...")
|
|
130
129
|
|
|
131
130
|
self.__instance_service.connect_to_selfhosted_instance(
|
|
132
|
-
|
|
131
|
+
selfhosted_instance_public_id=resolved_entity_public_id,
|
|
132
|
+
selfhosted_instance_slug=None,
|
|
133
133
|
username=username,
|
|
134
134
|
input_ssh_key_path=private_key_path
|
|
135
135
|
)
|
|
136
136
|
|
|
137
137
|
if task_presence:
|
|
138
|
-
typer.echo(
|
|
139
|
-
self.__logging_service.stream_task_logs_with_controls(
|
|
138
|
+
typer.echo(f"Connecting to task '{resolved_entity_public_id}'...")
|
|
139
|
+
self.__logging_service.stream_task_logs_with_controls(task_public_id=resolved_entity_public_id)
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
@error_handler()
|
|
143
|
-
def upload_ssh_key(self, public_key_contents: str, instance_slug: Optional[str]):
|
|
143
|
+
def upload_ssh_key(self, public_key_contents: str, instance_public_id: Optional[str], instance_slug: Optional[str]):
|
|
144
144
|
instance_rented: Optional[InstanceRentedDto] = None
|
|
145
|
-
if instance_slug:
|
|
145
|
+
if instance_slug or instance_public_id:
|
|
146
146
|
try:
|
|
147
|
-
instance_rented = self.__thestage_api_client.get_rented_instance(
|
|
147
|
+
instance_rented = self.__thestage_api_client.get_rented_instance(
|
|
148
|
+
instance_public_id=instance_public_id,
|
|
149
|
+
instance_slug=instance_slug
|
|
150
|
+
)
|
|
148
151
|
except HttpClientException as e:
|
|
149
152
|
instance_rented = None
|
|
150
153
|
|
|
@@ -159,7 +162,7 @@ class ConnectService(AbstractService):
|
|
|
159
162
|
public_key=public_key_contents
|
|
160
163
|
)
|
|
161
164
|
|
|
162
|
-
|
|
165
|
+
ssh_key_pair_public_id = is_user_already_has_key_response.sshKeyPairPublicId
|
|
163
166
|
is_adding_key_to_user = not is_user_already_has_key_response.isUserHasPublicKey
|
|
164
167
|
|
|
165
168
|
if is_adding_key_to_user and not note_to_send:
|
|
@@ -179,12 +182,12 @@ class ConnectService(AbstractService):
|
|
|
179
182
|
note=note_to_send
|
|
180
183
|
)
|
|
181
184
|
typer.echo(f"Public key '{note_to_send}' added to your profile")
|
|
182
|
-
|
|
185
|
+
ssh_key_pair_public_id = add_ssh_key_to_user_response.sshKeyPairPublicId
|
|
183
186
|
|
|
184
187
|
if instance_rented:
|
|
185
188
|
self.__thestage_api_client.add_public_ssh_key_to_instance_rented(
|
|
186
|
-
|
|
187
|
-
|
|
189
|
+
instance_rented_public_id=instance_rented.public_id,
|
|
190
|
+
ssh_key_pair_public_id=ssh_key_pair_public_id
|
|
188
191
|
)
|
|
189
192
|
|
|
190
193
|
if instance_rented.frontend_status.status_key != InstanceRentedBusinessStatus.ONLINE:
|
|
@@ -42,7 +42,8 @@ class ContainerService(AbstractService):
|
|
|
42
42
|
self,
|
|
43
43
|
row: int,
|
|
44
44
|
page: int,
|
|
45
|
-
|
|
45
|
+
project_public_id: Optional[str],
|
|
46
|
+
project_slug: Optional[str],
|
|
46
47
|
statuses: List[str],
|
|
47
48
|
):
|
|
48
49
|
container_status_map = self.__thestage_api_client.get_container_business_status_map()
|
|
@@ -72,22 +73,18 @@ class ContainerService(AbstractService):
|
|
|
72
73
|
|
|
73
74
|
backend_statuses: List[str] = [key for key, value in container_status_map.items() if value in statuses]
|
|
74
75
|
|
|
75
|
-
project_id: Optional[int] = None
|
|
76
|
-
if project_uid:
|
|
77
|
-
project = self.__thestage_api_client.get_project_by_slug(slug=project_uid)
|
|
78
|
-
project_id = project.id
|
|
79
|
-
|
|
80
76
|
self.print(
|
|
81
77
|
func_get_data=self.get_list,
|
|
82
78
|
func_special_params={
|
|
83
79
|
'statuses': backend_statuses,
|
|
84
|
-
'
|
|
80
|
+
'project_slug': project_slug,
|
|
81
|
+
'project_public_id': project_public_id,
|
|
85
82
|
},
|
|
86
83
|
mapper=ContainerMapper(),
|
|
87
84
|
headers=list(map(lambda x: x.alias, DockerContainerEntity.model_fields.values())),
|
|
88
85
|
row=row,
|
|
89
86
|
page=page,
|
|
90
|
-
max_col_width=[
|
|
87
|
+
max_col_width=[35, 20, 25],
|
|
91
88
|
show_index="never",
|
|
92
89
|
)
|
|
93
90
|
|
|
@@ -98,26 +95,29 @@ class ContainerService(AbstractService):
|
|
|
98
95
|
statuses: List[str],
|
|
99
96
|
row: int = 5,
|
|
100
97
|
page: int = 1,
|
|
101
|
-
|
|
98
|
+
project_public_id: Optional[str] = None,
|
|
99
|
+
project_slug: Optional[str] = None,
|
|
102
100
|
) -> PaginatedEntityList[DockerContainerDto]:
|
|
103
101
|
|
|
104
102
|
list = self.__thestage_api_client.get_container_list(
|
|
105
103
|
statuses=statuses,
|
|
106
104
|
page=page,
|
|
107
105
|
limit=row,
|
|
108
|
-
|
|
106
|
+
project_public_id=project_public_id,
|
|
107
|
+
project_slug=project_slug
|
|
109
108
|
)
|
|
110
109
|
|
|
111
110
|
return list
|
|
112
111
|
|
|
112
|
+
# TODO delete this proxy method
|
|
113
113
|
@error_handler()
|
|
114
114
|
def get_container(
|
|
115
115
|
self,
|
|
116
|
-
|
|
116
|
+
container_public_id: Optional[str] = None,
|
|
117
117
|
container_slug: Optional[str] = None,
|
|
118
118
|
) -> Optional[DockerContainerDto]:
|
|
119
119
|
return self.__thestage_api_client.get_container(
|
|
120
|
-
|
|
120
|
+
container_public_id=container_public_id,
|
|
121
121
|
container_slug=container_slug,
|
|
122
122
|
)
|
|
123
123
|
|
|
@@ -160,16 +160,18 @@ class ContainerService(AbstractService):
|
|
|
160
160
|
@error_handler()
|
|
161
161
|
def connect_to_container(
|
|
162
162
|
self,
|
|
163
|
-
|
|
163
|
+
container_public_id: Optional[str],
|
|
164
|
+
container_slug: Optional[str],
|
|
164
165
|
username: Optional[str],
|
|
165
166
|
input_ssh_key_path: Optional[str],
|
|
166
167
|
):
|
|
167
168
|
container: Optional[DockerContainerDto] = self.get_container(
|
|
168
|
-
|
|
169
|
+
container_public_id=container_public_id,
|
|
170
|
+
container_slug=container_slug,
|
|
169
171
|
)
|
|
170
172
|
|
|
171
173
|
if not container:
|
|
172
|
-
typer.echo(f"Container
|
|
174
|
+
typer.echo(f"Container not found")
|
|
173
175
|
raise typer.Exit(1)
|
|
174
176
|
|
|
175
177
|
self.check_if_container_running(
|
|
@@ -346,14 +348,16 @@ class ContainerService(AbstractService):
|
|
|
346
348
|
@error_handler()
|
|
347
349
|
def request_docker_container_action(
|
|
348
350
|
self,
|
|
349
|
-
|
|
351
|
+
container_public_id: Optional[str],
|
|
352
|
+
container_slug: Optional[str],
|
|
350
353
|
action: DockerContainerAction,
|
|
351
354
|
):
|
|
352
355
|
container: Optional[DockerContainerDto] = self.get_container(
|
|
353
|
-
|
|
356
|
+
container_public_id=container_public_id,
|
|
357
|
+
container_slug=container_slug,
|
|
354
358
|
)
|
|
355
359
|
if not container:
|
|
356
|
-
typer.echo(f"Container
|
|
360
|
+
typer.echo(f"Container not found")
|
|
357
361
|
raise typer.Exit(1)
|
|
358
362
|
|
|
359
363
|
if action == DockerContainerAction.START:
|
|
@@ -363,7 +367,7 @@ class ContainerService(AbstractService):
|
|
|
363
367
|
self.check_if_container_running(container=container)
|
|
364
368
|
|
|
365
369
|
request_params = DockerContainerActionRequestDto(
|
|
366
|
-
|
|
370
|
+
dockerContainerPublicId=container.public_id,
|
|
367
371
|
action=action,
|
|
368
372
|
)
|
|
369
373
|
result = self.__thestage_api_client.container_action(
|
|
@@ -22,8 +22,9 @@ class ContainerMapper(AbstractMapper):
|
|
|
22
22
|
|
|
23
23
|
return DockerContainerEntity(
|
|
24
24
|
status=item.frontend_status.status_translation if item.frontend_status else '',
|
|
25
|
+
public_id=item.public_id or '',
|
|
25
26
|
slug=item.slug or '',
|
|
26
|
-
|
|
27
|
+
project_slug=item.project.slug if item.project else '',
|
|
27
28
|
instance_type=instance_type,
|
|
28
29
|
instance_slug=instance_slug,
|
|
29
30
|
docker_image=item.docker_image or '',
|
|
@@ -35,21 +35,6 @@ class InstanceService(AbstractService):
|
|
|
35
35
|
self.__remote_server_service = remote_server_service
|
|
36
36
|
self.__config_provider = config_provider
|
|
37
37
|
|
|
38
|
-
def get_rented_instance(
|
|
39
|
-
self,
|
|
40
|
-
instance_slug: str,
|
|
41
|
-
) -> Optional[InstanceRentedDto]:
|
|
42
|
-
return self.__thestage_api_client.get_rented_instance(
|
|
43
|
-
instance_slug=instance_slug,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
def get_self_hosted_instance(
|
|
47
|
-
self,
|
|
48
|
-
instance_slug: str,
|
|
49
|
-
) -> Optional[SelfHostedInstanceDto]:
|
|
50
|
-
return self.__thestage_api_client.get_selfhosted_instance(
|
|
51
|
-
instance_slug=instance_slug,
|
|
52
|
-
)
|
|
53
38
|
|
|
54
39
|
@error_handler()
|
|
55
40
|
def check_instance_status_to_connect(
|
|
@@ -116,10 +101,14 @@ class InstanceService(AbstractService):
|
|
|
116
101
|
@error_handler()
|
|
117
102
|
def connect_to_rented_instance(
|
|
118
103
|
self,
|
|
119
|
-
|
|
104
|
+
instance_rented_public_id: Optional[str],
|
|
105
|
+
instance_rented_slug: Optional[str],
|
|
120
106
|
input_ssh_key_path: Optional[str]
|
|
121
107
|
):
|
|
122
|
-
instance = self.get_rented_instance(
|
|
108
|
+
instance = self.__thestage_api_client.get_rented_instance(
|
|
109
|
+
instance_public_id=instance_rented_public_id,
|
|
110
|
+
instance_slug=instance_rented_slug,
|
|
111
|
+
)
|
|
123
112
|
|
|
124
113
|
if instance:
|
|
125
114
|
self.check_instance_status_to_connect(
|
|
@@ -151,7 +140,8 @@ class InstanceService(AbstractService):
|
|
|
151
140
|
@error_handler()
|
|
152
141
|
def connect_to_selfhosted_instance(
|
|
153
142
|
self,
|
|
154
|
-
|
|
143
|
+
selfhosted_instance_public_id: Optional[str],
|
|
144
|
+
selfhosted_instance_slug: Optional[str],
|
|
155
145
|
username: str,
|
|
156
146
|
input_ssh_key_path: Optional[str],
|
|
157
147
|
):
|
|
@@ -159,7 +149,10 @@ class InstanceService(AbstractService):
|
|
|
159
149
|
username = 'root'
|
|
160
150
|
typer.echo(__("No remote server username provided, using 'root' as username"))
|
|
161
151
|
|
|
162
|
-
instance = self.
|
|
152
|
+
instance = self.__thestage_api_client.get_selfhosted_instance(
|
|
153
|
+
instance_public_id=selfhosted_instance_public_id,
|
|
154
|
+
instance_slug=selfhosted_instance_slug,
|
|
155
|
+
)
|
|
163
156
|
|
|
164
157
|
if instance:
|
|
165
158
|
self.check_selfhosted_status_to_connect(
|
|
@@ -184,7 +177,7 @@ class InstanceService(AbstractService):
|
|
|
184
177
|
if input_ssh_key_path:
|
|
185
178
|
self.__config_provider.update_remote_server_config_entry(ip_address=instance.ip_address, ssh_key_path=Path(input_ssh_key_path))
|
|
186
179
|
else:
|
|
187
|
-
typer.echo(
|
|
180
|
+
typer.echo("Self-hosted instance not found")
|
|
188
181
|
|
|
189
182
|
|
|
190
183
|
@error_handler()
|
|
@@ -13,12 +13,10 @@ class InstanceMapper(AbstractMapper):
|
|
|
13
13
|
|
|
14
14
|
return RentedInstanceEntity(
|
|
15
15
|
slug=item.slug if item.slug else '',
|
|
16
|
-
|
|
16
|
+
public_id=item.public_id if item.public_id else '',
|
|
17
17
|
cpu_type=item.cpu_type if item.cpu_type else '',
|
|
18
18
|
gpu_type=item.gpu_type if item.gpu_type else '',
|
|
19
19
|
cpu_cores=str(item.cpu_cores) if item.cpu_cores else '',
|
|
20
20
|
ip_address=item.ip_address if item.ip_address else '',
|
|
21
21
|
status=item.frontend_status.status_translation if item.frontend_status else '',
|
|
22
|
-
created_at=str(item.created_at.strftime("%Y-%m-%d %H:%M:%S")) if item.created_at else '',
|
|
23
|
-
updated_at=str(item.updated_at.strftime("%Y-%m-%d %H:%M:%S")) if item.updated_at else '',
|
|
24
22
|
)
|
|
@@ -3,6 +3,7 @@ from typing import Optional, Any, Tuple
|
|
|
3
3
|
|
|
4
4
|
from thestage.entities.rented_instance import RentedInstanceEntity
|
|
5
5
|
from thestage.entities.self_hosted_instance import SelfHostedInstanceEntity
|
|
6
|
+
from thestage.services.clients.thestage_api.dtos.enums.gpu_name import InstanceGpuType
|
|
6
7
|
from thestage.services.clients.thestage_api.dtos.selfhosted_instance_response import SelfHostedInstanceDto
|
|
7
8
|
from thestage.services.abstract_mapper import AbstractMapper
|
|
8
9
|
|
|
@@ -18,16 +19,14 @@ class SelfHostedMapper(AbstractMapper):
|
|
|
18
19
|
gpus = [item.type.value for item in item.detected_gpus.gpus]
|
|
19
20
|
|
|
20
21
|
if len(gpus) == 0:
|
|
21
|
-
gpus = [
|
|
22
|
+
gpus = [InstanceGpuType.NO_GPU]
|
|
22
23
|
|
|
23
24
|
return SelfHostedInstanceEntity(
|
|
24
25
|
slug=item.slug,
|
|
25
|
-
|
|
26
|
+
public_id=item.public_id,
|
|
26
27
|
cpu_type=item.cpu_type,
|
|
27
28
|
cpu_cores=item.cpu_cores,
|
|
28
29
|
gpu_type=', '.join(gpus),
|
|
29
30
|
ip_address=item.ip_address,
|
|
30
31
|
status=item.frontend_status.status_translation if item.frontend_status else None,
|
|
31
|
-
created_at=item.created_at.strftime("%Y-%m-%d %H:%M:%S") if item.created_at else '',
|
|
32
|
-
updated_at=item.updated_at.strftime("%Y-%m-%d %H:%M:%S") if item.updated_at else '',
|
|
33
32
|
)
|