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
|
@@ -80,11 +80,13 @@ class ProjectService(AbstractService):
|
|
|
80
80
|
@error_handler()
|
|
81
81
|
def init_project(
|
|
82
82
|
self,
|
|
83
|
-
project_slug: str,
|
|
83
|
+
project_slug: Optional[str] = None,
|
|
84
|
+
project_public_id: Optional[str] = None,
|
|
84
85
|
):
|
|
85
86
|
config = self.__config_provider.get_config()
|
|
86
|
-
project: Optional[ProjectDto] = self.__thestage_api_client.
|
|
87
|
+
project: Optional[ProjectDto] = self.__thestage_api_client.get_project(
|
|
87
88
|
slug=project_slug,
|
|
89
|
+
public_id=project_public_id,
|
|
88
90
|
)
|
|
89
91
|
|
|
90
92
|
if not project:
|
|
@@ -119,13 +121,12 @@ class ProjectService(AbstractService):
|
|
|
119
121
|
raise typer.Exit(0)
|
|
120
122
|
|
|
121
123
|
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(
|
|
122
|
-
|
|
124
|
+
public_id=project.public_id,
|
|
123
125
|
)
|
|
124
126
|
|
|
125
127
|
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(
|
|
126
128
|
deploy_ssh_key=deploy_ssh_key,
|
|
127
|
-
|
|
128
|
-
project_id=project.id,
|
|
129
|
+
project_public_id=project.public_id,
|
|
129
130
|
)
|
|
130
131
|
|
|
131
132
|
if is_git_folder:
|
|
@@ -156,7 +157,7 @@ class ProjectService(AbstractService):
|
|
|
156
157
|
self.__git_local_client.git_add_all(repo_path=config.runtime.working_directory)
|
|
157
158
|
|
|
158
159
|
project_config = ProjectConfig()
|
|
159
|
-
project_config.
|
|
160
|
+
project_config.public_id = project.public_id
|
|
160
161
|
project_config.slug = project.slug
|
|
161
162
|
project_config.git_repository_url = project.git_repository_url
|
|
162
163
|
project_config.deploy_key_path = str(deploy_key_path)
|
|
@@ -169,10 +170,12 @@ class ProjectService(AbstractService):
|
|
|
169
170
|
def clone_project(
|
|
170
171
|
self,
|
|
171
172
|
project_slug: str,
|
|
173
|
+
project_public_id: str
|
|
172
174
|
):
|
|
173
175
|
config = self.__config_provider.get_config()
|
|
174
|
-
project: Optional[ProjectDto] = self.__thestage_api_client.
|
|
176
|
+
project: Optional[ProjectDto] = self.__thestage_api_client.get_project(
|
|
175
177
|
slug=project_slug,
|
|
178
|
+
public_id=project_public_id
|
|
176
179
|
)
|
|
177
180
|
|
|
178
181
|
if not project:
|
|
@@ -195,8 +198,8 @@ class ProjectService(AbstractService):
|
|
|
195
198
|
typer.echo(__("Unexpected Project error, missing Repository"))
|
|
196
199
|
raise typer.Exit(1)
|
|
197
200
|
|
|
198
|
-
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(
|
|
199
|
-
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(deploy_ssh_key=deploy_ssh_key,
|
|
201
|
+
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(public_id=project.public_id)
|
|
202
|
+
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(deploy_ssh_key=deploy_ssh_key, project_public_id=project.public_id,)
|
|
200
203
|
|
|
201
204
|
try:
|
|
202
205
|
self.__git_local_client.clone(
|
|
@@ -217,7 +220,7 @@ class ProjectService(AbstractService):
|
|
|
217
220
|
raise typer.Exit(1)
|
|
218
221
|
|
|
219
222
|
project_config = ProjectConfig()
|
|
220
|
-
project_config.
|
|
223
|
+
project_config.public_id = project.public_id
|
|
221
224
|
project_config.slug = project.slug
|
|
222
225
|
project_config.git_repository_url = project.git_repository_url
|
|
223
226
|
project_config.deploy_key_path = str(deploy_key_path)
|
|
@@ -229,9 +232,10 @@ class ProjectService(AbstractService):
|
|
|
229
232
|
def project_run_task(
|
|
230
233
|
self,
|
|
231
234
|
run_command: str,
|
|
235
|
+
docker_container_slug: str,
|
|
236
|
+
docker_container_public_id: str,
|
|
232
237
|
task_title: Optional[str] = None,
|
|
233
238
|
commit_hash: Optional[str] = None,
|
|
234
|
-
docker_container_slug: Optional[str] = None,
|
|
235
239
|
files_to_add: Optional[str] = None,
|
|
236
240
|
is_skip_auto_commit: Optional[bool] = False,
|
|
237
241
|
) -> Optional[TaskDto]:
|
|
@@ -241,34 +245,39 @@ class ProjectService(AbstractService):
|
|
|
241
245
|
typer.echo(__("No project found at the path: %path%. Please initialize or clone a project first.", {"path": config.runtime.working_directory}))
|
|
242
246
|
raise typer.Exit(1)
|
|
243
247
|
|
|
244
|
-
if not docker_container_slug and not project_config.
|
|
245
|
-
typer.echo(__('Docker container
|
|
248
|
+
if not docker_container_public_id and not docker_container_slug and not project_config.default_container_public_id:
|
|
249
|
+
typer.echo(__('Docker container ID or name is required'))
|
|
246
250
|
raise typer.Exit(1)
|
|
247
251
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if not
|
|
251
|
-
|
|
252
|
+
final_container_public_id = docker_container_public_id
|
|
253
|
+
final_container_slug = docker_container_slug
|
|
254
|
+
if not final_container_public_id and not final_container_slug:
|
|
255
|
+
final_container_public_id = project_config.default_container_public_id
|
|
256
|
+
typer.echo(f"Using default docker container for this project: '{project_config.default_container_public_id}'")
|
|
252
257
|
|
|
253
258
|
container: DockerContainerDto = self.__thestage_api_client.get_container(
|
|
254
|
-
container_slug=
|
|
259
|
+
container_slug=final_container_slug,
|
|
260
|
+
container_public_id=final_container_public_id
|
|
255
261
|
)
|
|
256
262
|
|
|
257
263
|
if container is None:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
if final_container_slug:
|
|
265
|
+
typer.echo(f"Could not find container with name '{final_container_slug}'")
|
|
266
|
+
if final_container_public_id:
|
|
267
|
+
typer.echo(f"Could not find container with ID '{final_container_public_id}'")
|
|
268
|
+
if project_config.default_container_public_id == final_container_public_id:
|
|
269
|
+
project_config.default_container_public_id = None
|
|
261
270
|
project_config.prompt_for_default_container = True
|
|
262
271
|
self.__config_provider.save_project_config(project_config=project_config)
|
|
263
272
|
typer.echo(f"Default container settings were reset")
|
|
264
273
|
raise typer.Exit(1)
|
|
265
274
|
|
|
266
|
-
if container.
|
|
267
|
-
typer.echo(f"Provided container '{
|
|
275
|
+
if container.project.public_id != project_config.public_id:
|
|
276
|
+
typer.echo(f"Provided container '{container.public_id}' is not related to project '{project_config.public_id}'")
|
|
268
277
|
raise typer.Exit(1)
|
|
269
278
|
|
|
270
|
-
if (project_config.prompt_for_default_container is None or project_config.prompt_for_default_container) and docker_container_slug and (project_config.
|
|
271
|
-
|
|
279
|
+
if (project_config.prompt_for_default_container is None or project_config.prompt_for_default_container) and (docker_container_slug or docker_container_public_id) and (project_config.default_container_public_id != container.public_id):
|
|
280
|
+
set_default_container_answer: str = typer.prompt(
|
|
272
281
|
text=f"Would you like to set '{docker_container_slug}' as a default container for this project installation?",
|
|
273
282
|
show_choices=True,
|
|
274
283
|
default=YesOrNoResponse.YES.value,
|
|
@@ -276,8 +285,8 @@ class ProjectService(AbstractService):
|
|
|
276
285
|
show_default=True,
|
|
277
286
|
)
|
|
278
287
|
project_config.prompt_for_default_container = False
|
|
279
|
-
if
|
|
280
|
-
project_config.
|
|
288
|
+
if set_default_container_answer == YesOrNoResponse.YES.value:
|
|
289
|
+
project_config.default_container_public_id = container.public_id
|
|
281
290
|
|
|
282
291
|
self.__config_provider.save_project_config(project_config=project_config)
|
|
283
292
|
|
|
@@ -395,8 +404,8 @@ class ProjectService(AbstractService):
|
|
|
395
404
|
typer.echo(f'Commit message is empty. Task title is set to "{task_title}"')
|
|
396
405
|
|
|
397
406
|
run_task_response: ProjectRunTaskResponse = self.__thestage_api_client.execute_project_task(
|
|
398
|
-
|
|
399
|
-
|
|
407
|
+
project_public_id=project_config.public_id,
|
|
408
|
+
docker_container_public_id=container.public_id,
|
|
400
409
|
run_command=run_command,
|
|
401
410
|
commit_hash=commit_hash,
|
|
402
411
|
task_title=task_title,
|
|
@@ -405,7 +414,7 @@ class ProjectService(AbstractService):
|
|
|
405
414
|
if run_task_response.message:
|
|
406
415
|
print(f"[{ColorScheme.WARNING.value}]{run_task_response.message}[{ColorScheme.WARNING.value}]")
|
|
407
416
|
if run_task_response.is_success and run_task_response.task:
|
|
408
|
-
typer.echo(f"Task '{run_task_response.task.title}' has been scheduled successfully. Task ID: {run_task_response.task.
|
|
417
|
+
typer.echo(f"Task '{run_task_response.task.title}' has been scheduled successfully. Task ID: {run_task_response.task.public_id}")
|
|
409
418
|
return run_task_response.task
|
|
410
419
|
else:
|
|
411
420
|
typer.echo(f'The task failed with an error: {run_task_response.message}')
|
|
@@ -415,23 +424,25 @@ class ProjectService(AbstractService):
|
|
|
415
424
|
raise typer.Exit(1)
|
|
416
425
|
|
|
417
426
|
@error_handler()
|
|
418
|
-
def cancel_task(self,
|
|
427
|
+
def cancel_task(self, task_public_id: str):
|
|
419
428
|
cancel_result = self.__thestage_api_client.cancel_task(
|
|
420
|
-
|
|
429
|
+
task_public_id=task_public_id,
|
|
421
430
|
)
|
|
422
431
|
|
|
423
432
|
if cancel_result.is_success:
|
|
424
|
-
typer.echo(f'Task {
|
|
433
|
+
typer.echo(f'Task {task_public_id} has been canceled')
|
|
425
434
|
else:
|
|
426
|
-
typer.echo(f'Task {
|
|
435
|
+
typer.echo(f'Task {task_public_id} could not be canceled: {cancel_result.message}')
|
|
427
436
|
|
|
428
437
|
|
|
429
438
|
@error_handler()
|
|
430
439
|
def project_run_inference_simulator(
|
|
431
440
|
self,
|
|
432
441
|
commit_hash: Optional[str] = None,
|
|
433
|
-
|
|
434
|
-
|
|
442
|
+
rented_instance_public_id: Optional[str] = None,
|
|
443
|
+
rented_instance_slug: Optional[str] = None,
|
|
444
|
+
self_hosted_instance_public_id: Optional[str] = None,
|
|
445
|
+
self_hosted_instance_slug: Optional[str] = None,
|
|
435
446
|
inference_dir: Optional[str] = None,
|
|
436
447
|
is_skip_installation: Optional[bool] = False,
|
|
437
448
|
files_to_add: Optional[str] = None,
|
|
@@ -444,16 +455,12 @@ class ProjectService(AbstractService):
|
|
|
444
455
|
{"path": config.runtime.working_directory}))
|
|
445
456
|
raise typer.Exit(1)
|
|
446
457
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if not rented_instance_unique_id and not self_hosted_instance_unique_id:
|
|
452
|
-
typer.echo(__("Error: Either a rented instance ID or a self-hosted instance unique ID must be provided."))
|
|
458
|
+
instance_args_count = sum(v is not None for v in [rented_instance_public_id, rented_instance_slug, self_hosted_instance_public_id, self_hosted_instance_slug])
|
|
459
|
+
if instance_args_count != 1:
|
|
460
|
+
typer.echo("Please provide a single instance (rented or self-hosted) identifier - name or ID.")
|
|
453
461
|
raise typer.Exit(1)
|
|
454
462
|
|
|
455
463
|
has_wrong_args = files_to_add and commit_hash or is_skip_auto_commit and commit_hash or files_to_add and is_skip_auto_commit
|
|
456
|
-
|
|
457
464
|
if has_wrong_args:
|
|
458
465
|
warning_msg = f"[{ColorScheme.WARNING.value}][WARNING] You can provide only one of the following arguments: --commit-hash, --files-add, --skip-autocommit[{ColorScheme.WARNING.value}]"
|
|
459
466
|
print(warning_msg)
|
|
@@ -555,10 +562,12 @@ class ProjectService(AbstractService):
|
|
|
555
562
|
commit_hash = commit.hexsha
|
|
556
563
|
|
|
557
564
|
start_inference_simulator_response: ProjectStartInferenceSimulatorResponse = self.__thestage_api_client.start_project_inference_simulator(
|
|
558
|
-
|
|
565
|
+
project_public_id=project_config.public_id,
|
|
559
566
|
commit_hash=commit_hash,
|
|
560
|
-
|
|
561
|
-
|
|
567
|
+
rented_instance_public_id=rented_instance_public_id,
|
|
568
|
+
rented_instance_slug=rented_instance_slug,
|
|
569
|
+
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
570
|
+
self_hosted_instance_slug=self_hosted_instance_slug,
|
|
562
571
|
inference_dir=inference_dir,
|
|
563
572
|
is_skip_installation=is_skip_installation,
|
|
564
573
|
)
|
|
@@ -582,10 +591,12 @@ class ProjectService(AbstractService):
|
|
|
582
591
|
@error_handler()
|
|
583
592
|
def project_push_inference_simulator(
|
|
584
593
|
self,
|
|
594
|
+
public_id: Optional[str] = None,
|
|
585
595
|
slug: Optional[str] = None,
|
|
586
596
|
):
|
|
587
597
|
|
|
588
598
|
push_inference_simulator_model_response: ProjectPushInferenceSimulatorModelResponse = self.__thestage_api_client.push_project_inference_simulator_model(
|
|
599
|
+
public_id=public_id,
|
|
589
600
|
slug=slug,
|
|
590
601
|
)
|
|
591
602
|
if push_inference_simulator_model_response:
|
|
@@ -606,11 +617,13 @@ class ProjectService(AbstractService):
|
|
|
606
617
|
@error_handler()
|
|
607
618
|
def project_get_and_save_inference_simulator_metadata(
|
|
608
619
|
self,
|
|
609
|
-
|
|
620
|
+
inference_simulator_public_id: Optional[str] = None,
|
|
621
|
+
inference_simulator_slug: Optional[str] = None,
|
|
610
622
|
file_path: Optional[str] = None,
|
|
611
623
|
):
|
|
612
624
|
get_inference_metadata_response: GetInferenceSimulatorResponse = self.__thestage_api_client.get_inference_simulator(
|
|
613
|
-
|
|
625
|
+
public_id=inference_simulator_public_id,
|
|
626
|
+
slug=inference_simulator_slug,
|
|
614
627
|
)
|
|
615
628
|
|
|
616
629
|
metadata = get_inference_metadata_response.inferenceSimulator.qlip_serve_metadata
|
|
@@ -643,13 +656,15 @@ class ProjectService(AbstractService):
|
|
|
643
656
|
@error_handler()
|
|
644
657
|
def get_project_inference_simulator_list(
|
|
645
658
|
self,
|
|
646
|
-
|
|
659
|
+
project_public_id: Optional[str],
|
|
660
|
+
project_slug: Optional[str],
|
|
647
661
|
statuses: List[str],
|
|
648
662
|
row: int = 5,
|
|
649
663
|
page: int = 1,
|
|
650
664
|
) -> PaginatedEntityList[InferenceSimulatorDto]:
|
|
651
|
-
data: Optional[PaginatedEntityList[InferenceSimulatorDto]] = self.__thestage_api_client.
|
|
665
|
+
data: Optional[PaginatedEntityList[InferenceSimulatorDto]] = self.__thestage_api_client.get_inference_simulator_list(
|
|
652
666
|
statuses=statuses,
|
|
667
|
+
project_public_id=project_public_id,
|
|
653
668
|
project_slug=project_slug,
|
|
654
669
|
page=page,
|
|
655
670
|
limit=row,
|
|
@@ -661,7 +676,8 @@ class ProjectService(AbstractService):
|
|
|
661
676
|
@error_handler()
|
|
662
677
|
def get_project_inference_simulator_model_list(
|
|
663
678
|
self,
|
|
664
|
-
|
|
679
|
+
project_public_id: Optional[str],
|
|
680
|
+
project_slug: Optional[str],
|
|
665
681
|
statuses: List[str],
|
|
666
682
|
row: int = 5,
|
|
667
683
|
page: int = 1,
|
|
@@ -669,22 +685,7 @@ class ProjectService(AbstractService):
|
|
|
669
685
|
data: Optional[
|
|
670
686
|
PaginatedEntityList[InferenceSimulatorModelDto]] = self.__thestage_api_client.get_inference_simulator_model_list_for_project(
|
|
671
687
|
statuses=statuses,
|
|
672
|
-
|
|
673
|
-
page=page,
|
|
674
|
-
limit=row,
|
|
675
|
-
)
|
|
676
|
-
|
|
677
|
-
return data
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
@error_handler()
|
|
681
|
-
def get_project_task_list(
|
|
682
|
-
self,
|
|
683
|
-
project_slug: str,
|
|
684
|
-
row: int = 5,
|
|
685
|
-
page: int = 1,
|
|
686
|
-
) -> PaginatedEntityList[TaskDto]:
|
|
687
|
-
data: Optional[PaginatedEntityList[TaskDto]] = self.__thestage_api_client.get_task_list_for_project(
|
|
688
|
+
project_public_id=project_public_id,
|
|
688
689
|
project_slug=project_slug,
|
|
689
690
|
page=page,
|
|
690
691
|
limit=row,
|
|
@@ -696,7 +697,7 @@ class ProjectService(AbstractService):
|
|
|
696
697
|
@error_handler()
|
|
697
698
|
def checkout_project(
|
|
698
699
|
self,
|
|
699
|
-
|
|
700
|
+
task_public_id: Optional[str],
|
|
700
701
|
branch_name: Optional[str],
|
|
701
702
|
):
|
|
702
703
|
config = self.__config_provider.get_config()
|
|
@@ -706,21 +707,21 @@ class ProjectService(AbstractService):
|
|
|
706
707
|
raise typer.Exit(1)
|
|
707
708
|
|
|
708
709
|
target_commit_hash: Optional[str] = None
|
|
709
|
-
if
|
|
710
|
+
if task_public_id:
|
|
710
711
|
task_view_response: Optional[TaskViewResponse] = None
|
|
711
712
|
try:
|
|
712
|
-
task_view_response = self.__thestage_api_client.get_task(
|
|
713
|
+
task_view_response = self.__thestage_api_client.get_task(task_public_id=task_public_id)
|
|
713
714
|
except HttpClientException as e:
|
|
714
715
|
if e.get_status_code() == 400:
|
|
715
|
-
typer.echo(f"Task {
|
|
716
|
+
typer.echo(f"Task {task_public_id} was not found")
|
|
716
717
|
# overriding arguments here
|
|
717
|
-
branch_name = str(
|
|
718
|
-
|
|
718
|
+
branch_name = str(task_public_id)
|
|
719
|
+
task_public_id = None
|
|
719
720
|
|
|
720
721
|
if task_view_response and task_view_response.task:
|
|
721
722
|
target_commit_hash = task_view_response.task.commit_hash
|
|
722
723
|
if not target_commit_hash:
|
|
723
|
-
typer.echo(f"Provided task ({
|
|
724
|
+
typer.echo(f"Provided task ({task_public_id}) has no commit hash") # possible legacy problems
|
|
724
725
|
raise typer.Exit(1)
|
|
725
726
|
|
|
726
727
|
is_commit_allowed: bool = True
|
|
@@ -833,48 +834,40 @@ class ProjectService(AbstractService):
|
|
|
833
834
|
|
|
834
835
|
|
|
835
836
|
@error_handler()
|
|
836
|
-
def set_default_container(
|
|
837
|
+
def set_default_container(
|
|
838
|
+
self,
|
|
839
|
+
container_public_id: Optional[str],
|
|
840
|
+
container_slug: Optional[str],
|
|
841
|
+
):
|
|
837
842
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
838
843
|
|
|
839
844
|
if project_config is None:
|
|
840
845
|
typer.echo(f"No project found in working directory")
|
|
841
846
|
raise typer.Exit(1)
|
|
842
847
|
|
|
843
|
-
|
|
848
|
+
container: Optional[DockerContainerDto] = None
|
|
849
|
+
if container_slug or container_public_id:
|
|
844
850
|
container: DockerContainerDto = self.__thestage_api_client.get_container(
|
|
845
|
-
|
|
851
|
+
container_public_id=container_public_id,
|
|
852
|
+
container_slug=container_slug,
|
|
846
853
|
)
|
|
847
854
|
if container is None:
|
|
848
|
-
typer.echo(f"Could not find container '{
|
|
855
|
+
typer.echo(f"Could not find container '{container_slug or container_public_id}'")
|
|
849
856
|
raise typer.Exit(1)
|
|
850
857
|
|
|
851
|
-
if container.
|
|
852
|
-
typer.echo(f"Provided container '{
|
|
858
|
+
if container.project.public_id != project_config.public_id:
|
|
859
|
+
typer.echo(f"Provided container '{container_slug or container_public_id}' is not related to current project '{project_config.public_id}'")
|
|
853
860
|
raise typer.Exit(1)
|
|
854
861
|
|
|
855
862
|
if container.frontend_status.status_key != DockerContainerStatus.RUNNING:
|
|
856
|
-
typer.echo(f"Note: provided container '{
|
|
863
|
+
typer.echo(f"Note: provided container '{container_slug or container_public_id}' is in status '{container.frontend_status.status_translation}'")
|
|
857
864
|
|
|
858
|
-
project_config.
|
|
865
|
+
project_config.default_container_public_id = container.public_id if container else None
|
|
859
866
|
project_config.prompt_for_default_container = False
|
|
860
867
|
self.__config_provider.save_project_config(project_config=project_config)
|
|
861
868
|
typer.echo("Default container settings were updated")
|
|
862
869
|
|
|
863
870
|
|
|
864
|
-
@error_handler()
|
|
865
|
-
def unset_default_container(self):
|
|
866
|
-
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
867
|
-
|
|
868
|
-
if project_config is None:
|
|
869
|
-
typer.echo(f"No project found in working directory")
|
|
870
|
-
raise typer.Exit(1)
|
|
871
|
-
|
|
872
|
-
project_config.default_container_uid = None
|
|
873
|
-
project_config.prompt_for_default_container = True # True or False?
|
|
874
|
-
self.__config_provider.save_project_config(project_config=project_config)
|
|
875
|
-
typer.echo("Default container settings were updated")
|
|
876
|
-
|
|
877
|
-
|
|
878
871
|
@error_handler()
|
|
879
872
|
def print_project_config(self):
|
|
880
873
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
@@ -888,10 +881,13 @@ class ProjectService(AbstractService):
|
|
|
888
881
|
typer.echo(tabulate(
|
|
889
882
|
[
|
|
890
883
|
[
|
|
891
|
-
"Project
|
|
884
|
+
"Project ID", project_config.public_id
|
|
892
885
|
],
|
|
893
886
|
[
|
|
894
|
-
"
|
|
887
|
+
"Project name", project_config.slug
|
|
888
|
+
],
|
|
889
|
+
[
|
|
890
|
+
"Default docker container ID", project_config.default_container_public_id if project_config.default_container_public_id else "<None>"
|
|
895
891
|
],
|
|
896
892
|
[
|
|
897
893
|
"Deploy key path", project_config.deploy_key_path if is_deploy_key_exists else "<None>"
|
|
@@ -913,15 +909,19 @@ class ProjectService(AbstractService):
|
|
|
913
909
|
if project_config is None:
|
|
914
910
|
return None
|
|
915
911
|
|
|
912
|
+
if project_config.public_id is None:
|
|
913
|
+
project = self.__thestage_api_client.get_project(public_id=None, slug=project_config.slug)
|
|
914
|
+
project_config.public_id = project.public_id
|
|
915
|
+
self.__config_provider.save_project_config(project_config=project_config)
|
|
916
|
+
|
|
916
917
|
if not Path(project_config.deploy_key_path).is_file():
|
|
917
918
|
deploy_ssh_key = self.__thestage_api_client.get_project_deploy_ssh_key(
|
|
918
|
-
|
|
919
|
+
public_id=project_config.public_id,
|
|
919
920
|
)
|
|
920
921
|
|
|
921
922
|
deploy_key_path = self.__config_provider.save_project_deploy_ssh_key(
|
|
922
923
|
deploy_ssh_key=deploy_ssh_key,
|
|
923
|
-
|
|
924
|
-
project_id=project_config.id,
|
|
924
|
+
project_public_id=project_config.public_id,
|
|
925
925
|
)
|
|
926
926
|
|
|
927
927
|
project_config.deploy_key_path = deploy_key_path
|
|
@@ -933,10 +933,13 @@ class ProjectService(AbstractService):
|
|
|
933
933
|
@error_handler()
|
|
934
934
|
def project_deploy_inference_simulator_model_to_instance(
|
|
935
935
|
self,
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
936
|
+
model_public_id: Optional[str] = None,
|
|
937
|
+
model_slug: Optional[str] = None,
|
|
938
|
+
new_inference_simulator_slug: Optional[str] = None,
|
|
939
|
+
rented_instance_public_id: Optional[str] = None,
|
|
940
|
+
rented_instance_slug: Optional[str] = None,
|
|
941
|
+
self_hosted_instance_public_id: Optional[str] = None,
|
|
942
|
+
self_hosted_instance_slug: Optional[str] = None,
|
|
940
943
|
) -> None:
|
|
941
944
|
config = self.__config_provider.get_config()
|
|
942
945
|
project_config: ProjectConfig = self.__get_fixed_project_config()
|
|
@@ -946,20 +949,25 @@ class ProjectService(AbstractService):
|
|
|
946
949
|
{"path": config.runtime.working_directory}))
|
|
947
950
|
raise typer.Exit(1)
|
|
948
951
|
|
|
949
|
-
|
|
950
|
-
|
|
952
|
+
instance_args_count = sum(v is not None for v in [rented_instance_public_id, rented_instance_slug, self_hosted_instance_public_id, self_hosted_instance_slug])
|
|
953
|
+
if instance_args_count != 1:
|
|
954
|
+
typer.echo("Please provide a single instance (rented or self-hosted) identifier - name or ID.")
|
|
951
955
|
raise typer.Exit(1)
|
|
952
956
|
|
|
953
|
-
|
|
954
|
-
|
|
957
|
+
model_args_count = sum(v is not None for v in [model_public_id, model_slug])
|
|
958
|
+
if model_args_count != 1:
|
|
959
|
+
typer.echo("Please provide a single model identifier - name or ID.")
|
|
955
960
|
raise typer.Exit(1)
|
|
956
961
|
|
|
957
|
-
typer.echo(
|
|
962
|
+
typer.echo(f"Creating inference simulator with unique ID: {new_inference_simulator_slug}")
|
|
958
963
|
deploy_model_to_instance_response: DeployInferenceModelToInstanceResponse = self.__thestage_api_client.deploy_inference_model_to_instance(
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
964
|
+
model_public_id=model_public_id,
|
|
965
|
+
model_slug=model_slug,
|
|
966
|
+
new_inference_simulator_slug=new_inference_simulator_slug,
|
|
967
|
+
rented_instance_public_id=rented_instance_public_id,
|
|
968
|
+
rented_instance_slug=rented_instance_slug,
|
|
969
|
+
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
970
|
+
self_hosted_instance_slug=self_hosted_instance_slug,
|
|
963
971
|
)
|
|
964
972
|
if deploy_model_to_instance_response:
|
|
965
973
|
if deploy_model_to_instance_response.message:
|
|
@@ -980,7 +988,8 @@ class ProjectService(AbstractService):
|
|
|
980
988
|
@error_handler()
|
|
981
989
|
def project_deploy_inference_simulator_model_to_sagemaker(
|
|
982
990
|
self,
|
|
983
|
-
|
|
991
|
+
model_public_id: Optional[str] = None,
|
|
992
|
+
model_slug: Optional[str] = None,
|
|
984
993
|
arn: Optional[str] = None,
|
|
985
994
|
instance_type: Optional[str] = None,
|
|
986
995
|
initial_variant_weight: Optional[float] = 1.0,
|
|
@@ -1013,7 +1022,8 @@ class ProjectService(AbstractService):
|
|
|
1013
1022
|
raise typer.Exit(1)
|
|
1014
1023
|
|
|
1015
1024
|
deploy_model_to_sagemaker_response: DeployInferenceModelToSagemakerResponse = self.__thestage_api_client.deploy_inference_model_to_sagemaker(
|
|
1016
|
-
|
|
1025
|
+
model_public_id=model_public_id,
|
|
1026
|
+
model_slug=model_slug,
|
|
1017
1027
|
arn=arn,
|
|
1018
1028
|
)
|
|
1019
1029
|
|
|
@@ -1041,7 +1051,7 @@ class ProjectService(AbstractService):
|
|
|
1041
1051
|
},
|
|
1042
1052
|
}
|
|
1043
1053
|
|
|
1044
|
-
sm_model_name = f"{
|
|
1054
|
+
sm_model_name = f"{model_slug}-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
1045
1055
|
create_model_response = sm_client.create_model(
|
|
1046
1056
|
ModelName=sm_model_name,
|
|
1047
1057
|
ExecutionRoleArn=arn,
|
|
@@ -1049,7 +1059,7 @@ class ProjectService(AbstractService):
|
|
|
1049
1059
|
)
|
|
1050
1060
|
typer.echo(f"Model created successfully. Model ARN: {create_model_response['ModelArn']}")
|
|
1051
1061
|
|
|
1052
|
-
endpoint_config_name = f"{
|
|
1062
|
+
endpoint_config_name = f"{model_slug}-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
1053
1063
|
create_endpoint_config_response = sm_client.create_endpoint_config(
|
|
1054
1064
|
EndpointConfigName=endpoint_config_name,
|
|
1055
1065
|
ProductionVariants=[
|
|
@@ -1065,7 +1075,7 @@ class ProjectService(AbstractService):
|
|
|
1065
1075
|
typer.echo(
|
|
1066
1076
|
f"Endpoint configuration created successfully. Endpoint Config ARN: {create_endpoint_config_response['EndpointConfigArn']}")
|
|
1067
1077
|
|
|
1068
|
-
endpoint_name = f"{
|
|
1078
|
+
endpoint_name = f"{model_slug}-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
1069
1079
|
create_endpoint_response = sm_client.create_endpoint(
|
|
1070
1080
|
EndpointName=endpoint_name,
|
|
1071
1081
|
EndpointConfigName=endpoint_config_name,
|
|
@@ -1128,13 +1138,13 @@ class ProjectService(AbstractService):
|
|
|
1128
1138
|
|
|
1129
1139
|
|
|
1130
1140
|
@error_handler()
|
|
1131
|
-
def print_inference_simulator_list(self,
|
|
1132
|
-
if not
|
|
1141
|
+
def print_inference_simulator_list(self, project_public_id, project_slug, statuses, row, page):
|
|
1142
|
+
if not project_public_id and not project_slug:
|
|
1133
1143
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1134
1144
|
if not project_config:
|
|
1135
1145
|
typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
|
|
1136
1146
|
raise typer.Exit(1)
|
|
1137
|
-
|
|
1147
|
+
project_public_id = project_config.public_id
|
|
1138
1148
|
|
|
1139
1149
|
inference_simulator_status_map = self.__thestage_api_client.get_inference_simulator_business_status_map()
|
|
1140
1150
|
|
|
@@ -1167,7 +1177,8 @@ class ProjectService(AbstractService):
|
|
|
1167
1177
|
self.print(
|
|
1168
1178
|
func_get_data=self.get_project_inference_simulator_list,
|
|
1169
1179
|
func_special_params={
|
|
1170
|
-
'
|
|
1180
|
+
'project_public_id': project_public_id,
|
|
1181
|
+
'project_slug': project_slug,
|
|
1171
1182
|
'statuses': backend_statuses,
|
|
1172
1183
|
},
|
|
1173
1184
|
mapper=ProjectInferenceSimulatorMapper(),
|
|
@@ -1180,13 +1191,13 @@ class ProjectService(AbstractService):
|
|
|
1180
1191
|
|
|
1181
1192
|
|
|
1182
1193
|
@error_handler()
|
|
1183
|
-
def print_inference_simulator_model_list(self,
|
|
1184
|
-
if not
|
|
1194
|
+
def print_inference_simulator_model_list(self, project_public_id, project_slug, statuses, row, page):
|
|
1195
|
+
if not project_public_id and not project_slug:
|
|
1185
1196
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1186
1197
|
if not project_config:
|
|
1187
1198
|
typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
|
|
1188
1199
|
raise typer.Exit(1)
|
|
1189
|
-
|
|
1200
|
+
project_public_id = project_config.public_id
|
|
1190
1201
|
|
|
1191
1202
|
inference_simulator_model_status_map = self.__thestage_api_client.get_inference_simulator_model_business_status_map()
|
|
1192
1203
|
|
|
@@ -1219,7 +1230,8 @@ class ProjectService(AbstractService):
|
|
|
1219
1230
|
self.print(
|
|
1220
1231
|
func_get_data=self.get_project_inference_simulator_model_list,
|
|
1221
1232
|
func_special_params={
|
|
1222
|
-
'
|
|
1233
|
+
'project_public_id': project_public_id,
|
|
1234
|
+
'project_slug': project_slug,
|
|
1223
1235
|
'statuses': backend_statuses,
|
|
1224
1236
|
},
|
|
1225
1237
|
mapper=ProjectInferenceSimulatorModelMapper(),
|
|
@@ -1231,18 +1243,19 @@ class ProjectService(AbstractService):
|
|
|
1231
1243
|
)
|
|
1232
1244
|
|
|
1233
1245
|
|
|
1234
|
-
def print_task_list(self,
|
|
1235
|
-
if not
|
|
1246
|
+
def print_task_list(self, project_public_id: Optional[str], project_slug: Optional[str], row, page):
|
|
1247
|
+
if not project_slug and not project_public_id:
|
|
1236
1248
|
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
1237
1249
|
if not project_config:
|
|
1238
1250
|
typer.echo(__("Provide the project unique ID or run this command from within an initialized project directory"))
|
|
1239
1251
|
raise typer.Exit(1)
|
|
1240
|
-
|
|
1252
|
+
project_public_id = project_config.public_id
|
|
1241
1253
|
|
|
1242
1254
|
self.print(
|
|
1243
1255
|
func_get_data=self.get_project_task_list,
|
|
1244
1256
|
func_special_params={
|
|
1245
|
-
'
|
|
1257
|
+
'project_public_id': project_public_id,
|
|
1258
|
+
'project_slug': project_slug,
|
|
1246
1259
|
},
|
|
1247
1260
|
mapper=ProjectTaskMapper(),
|
|
1248
1261
|
headers=list(map(lambda x: x.alias, ProjectTaskEntity.model_fields.values())),
|
|
@@ -1251,3 +1264,20 @@ class ProjectService(AbstractService):
|
|
|
1251
1264
|
max_col_width=[100, 100, 100, 100, 100, 100, 100, 100],
|
|
1252
1265
|
show_index="never",
|
|
1253
1266
|
)
|
|
1267
|
+
|
|
1268
|
+
@error_handler()
|
|
1269
|
+
def get_project_task_list(
|
|
1270
|
+
self,
|
|
1271
|
+
project_public_id: Optional[str],
|
|
1272
|
+
project_slug: Optional[str],
|
|
1273
|
+
row: int = 5,
|
|
1274
|
+
page: int = 1,
|
|
1275
|
+
) -> PaginatedEntityList[TaskDto]:
|
|
1276
|
+
data: Optional[PaginatedEntityList[TaskDto]] = self.__thestage_api_client.get_task_list_for_project(
|
|
1277
|
+
project_public_id=project_public_id,
|
|
1278
|
+
project_slug=project_slug,
|
|
1279
|
+
page=page,
|
|
1280
|
+
limit=row,
|
|
1281
|
+
)
|
|
1282
|
+
|
|
1283
|
+
return data
|
|
@@ -116,6 +116,7 @@ class RemoteServerService:
|
|
|
116
116
|
username: str,
|
|
117
117
|
private_key_path: Optional[str],
|
|
118
118
|
):
|
|
119
|
+
typer.echo(f"Connecting to {username}@{ip_address}")
|
|
119
120
|
try:
|
|
120
121
|
if private_key_path:
|
|
121
122
|
os.system(f"ssh -o PreferredAuthentications=publickey -o 'IdentitiesOnly=yes' -i {private_key_path} {username}@{ip_address}")
|