thestage 0.6.7__py3-none-any.whl → 0.7.0__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/cli_command.py +3 -0
- thestage/cli_command_helper.py +2 -2
- thestage/config/__init__.py +1 -1
- thestage/{services → config/business}/app_config_service.py +3 -4
- thestage/{services/config_provider → config/business}/config_provider.py +6 -5
- thestage/config/{config_storage.py → business/config_storage.py} +1 -1
- thestage/{services → config/business}/validation_service.py +9 -10
- thestage/{controllers/config_controller.py → config/communication/config_command.py} +7 -7
- thestage/{services/connect → connect/business}/connect_service.py +22 -19
- thestage/{services → connect/business}/remote_server_service.py +4 -5
- thestage/connect/communication/connect_api_client.py +84 -0
- thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_key_to_user_response.py +0 -1
- thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_public_key_to_instance_response.py +1 -4
- thestage/{services/clients/thestage_api/dtos/base_controller → connect/dto}/connect_resolve_response.py +0 -1
- thestage/controllers/base_controller.py +2 -2
- thestage/debug_main.dist.py +16 -14
- thestage/{services/container → docker_container/business}/container_service.py +147 -22
- thestage/{services/container → docker_container/business}/mapper/container_mapper.py +3 -3
- thestage/docker_container/business/mapper/image_mapper.py +16 -0
- thestage/docker_container/communication/__init__.py +0 -0
- thestage/{controllers/container_controller.py → docker_container/communication/docker_command.py} +192 -29
- thestage/docker_container/communication/docker_container_api_client.py +139 -0
- thestage/docker_container/communication/image_command.py +40 -0
- thestage/docker_container/dto/__init__.py +0 -0
- thestage/docker_container/dto/container_action_request.py +11 -0
- thestage/{services/clients/thestage_api/dtos → docker_container/dto}/container_response.py +11 -4
- thestage/docker_container/dto/docker_container_create_request.py +28 -0
- thestage/docker_container/dto/docker_container_create_response.py +11 -0
- thestage/{services/clients/thestage_api/dtos/docker_container_controller → docker_container/dto}/docker_container_list_response.py +3 -5
- thestage/docker_container/dto/docker_image_list_request.py +11 -0
- thestage/docker_container/dto/docker_image_list_response.py +13 -0
- thestage/docker_container/dto/enum/__init__.py +0 -0
- thestage/docker_container/dto/image_entity.py +14 -0
- thestage/git/__init__.py +0 -0
- thestage/git/business/__init__.py +0 -0
- thestage/git/communication/__init__.py +0 -0
- thestage/{services/clients/git → git/communication}/git_client.py +4 -4
- thestage/global_dto/__init__.py +0 -0
- thestage/global_dto/enums/__init__.py +0 -0
- thestage/helpers/error_handler.py +4 -4
- thestage/helpers/logger/app_logger.py +1 -3
- thestage/i18n/en_GB/messages.po +14 -14
- thestage/inference_model/__init__.py +0 -0
- thestage/inference_model/business/__init__.py +0 -0
- thestage/inference_model/business/inference_model_service.py +281 -0
- thestage/inference_model/business/mapper/__init__.py +0 -0
- thestage/{services/project/mapper/project_inference_simulator_model_mapper.py → inference_model/business/mapper/inference_model_mapper.py} +5 -5
- thestage/inference_model/communication/__init__.py +0 -0
- thestage/inference_model/communication/inference_model_api_client.py +139 -0
- thestage/inference_model/communication/inference_model_command.py +246 -0
- thestage/inference_model/dto/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_instance_response.py +0 -1
- thestage/inference_model/dto/enum/__init__.py +0 -0
- thestage/{services/project/dto/inference_simulator_model_dto.py → inference_model/dto/inference_model.py} +1 -1
- thestage/{entities/project_inference_simulator_model.py → inference_model/dto/inference_model_entity.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/inference_simulator_model_list_for_project_response.py +2 -3
- thestage/{services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py → inference_model/dto/push_inference_simulator_model_request.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py → inference_model/dto/push_inference_simulator_model_response.py} +1 -1
- thestage/inference_simulator/__init__.py +0 -0
- thestage/inference_simulator/business/__init__.py +0 -0
- thestage/inference_simulator/business/inference_simulator_service.py +338 -0
- thestage/inference_simulator/business/mapper/__init__.py +0 -0
- thestage/{services/project/mapper/project_inference_simulator_mapper.py → inference_simulator/business/mapper/inference_simulator_mapper.py} +5 -5
- thestage/inference_simulator/communication/__init__.py +0 -0
- thestage/inference_simulator/communication/inference_simulator_api_client.py +114 -0
- thestage/inference_simulator/communication/inference_simulator_command.py +347 -0
- thestage/inference_simulator/dto/__init__.py +0 -0
- thestage/inference_simulator/dto/enum/__init__.py +0 -0
- thestage/inference_simulator/dto/get_inference_simulator_response.py +12 -0
- thestage/{services/project/dto/inference_simulator_dto.py → inference_simulator/dto/inference_simulator.py} +1 -1
- thestage/{entities/project_inference_simulator.py → inference_simulator/dto/inference_simulator_entity.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/inference_simulator_list_response.py +2 -2
- thestage/{services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py → inference_simulator/dto/start_inference_simulator_request.py} +1 -1
- thestage/inference_simulator/dto/start_inference_simulator_response.py +10 -0
- thestage/instance/__init__.py +0 -0
- thestage/instance/business/__init__.py +0 -0
- thestage/{services/instance → instance/business}/instance_service.py +26 -27
- thestage/instance/business/mapper/__init__.py +0 -0
- thestage/{services/instance/mapper/instance_mapper.py → instance/business/mapper/rented_instance_mapper.py} +3 -3
- thestage/{services/instance/mapper/selfhosted_mapper.py → instance/business/mapper/selfhosted_instance_mapper.py} +5 -7
- thestage/instance/communication/__init__.py +0 -0
- thestage/instance/communication/instance_api_client.py +150 -0
- thestage/{controllers/instance_controller.py → instance/communication/instance_command.py} +5 -5
- thestage/instance/dto/__init__.py +0 -0
- thestage/instance/dto/enum/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos → instance/dto}/instance_detected_gpus.py +1 -2
- thestage/{services/clients/thestage_api/dtos → instance/dto}/instance_rented_response.py +2 -2
- thestage/{services/clients/thestage_api/dtos → instance/dto}/selfhosted_instance_response.py +2 -3
- thestage/logging/__init__.py +0 -0
- thestage/logging/business/__init__.py +0 -0
- thestage/{services/logging → logging/business}/logging_service.py +40 -28
- thestage/logging/communication/__init__.py +0 -0
- thestage/logging/communication/logging_api_client.py +63 -0
- thestage/logging/dto/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/log_polling_response.py +2 -2
- thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/user_logs_query_response.py +2 -2
- thestage/main.py +54 -8
- thestage/project/__init__.py +0 -0
- thestage/project/business/__init__.py +0 -0
- thestage/project/business/project_service.py +480 -0
- thestage/project/communication/__init__.py +0 -0
- thestage/project/communication/project_api_client.py +46 -0
- thestage/project/communication/project_command.py +284 -0
- thestage/project/dto/__init__.py +0 -0
- thestage/services/clients/thestage_api/core/api_client_core.py +1 -1
- thestage/services/clients/thestage_api/dtos/entity_filter_request.py +1 -1
- thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +1 -1
- thestage/services/filesystem_service.py +2 -2
- thestage/services/service_factory.py +130 -43
- thestage/task/__init__.py +0 -0
- thestage/task/business/__init__.py +0 -0
- thestage/task/business/mapper/__init__.py +0 -0
- thestage/{services/project/mapper/project_task_mapper.py → task/business/mapper/task_mapper.py} +5 -5
- thestage/task/business/task_service.py +307 -0
- thestage/task/communication/__init__.py +0 -0
- thestage/task/communication/task_api_client.py +122 -0
- thestage/task/communication/task_command.py +212 -0
- thestage/task/dto/__init__.py +0 -0
- thestage/task/dto/enum/__init__.py +0 -0
- thestage/{services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py → task/dto/list_for_project_response.py} +2 -2
- thestage/{services/clients/thestage_api/dtos/project_controller/project_run_task_request.py → task/dto/run_task_request.py} +1 -1
- thestage/task/dto/run_task_response.py +13 -0
- thestage/{services/task/dto/task_dto.py → task/dto/task.py} +1 -4
- thestage/{entities/project_task.py → task/dto/task_entity.py} +1 -1
- thestage/{services/clients/thestage_api/dtos/task_controller/task_view_response.py → task/dto/view_response.py} +2 -2
- {thestage-0.6.7.dist-info → thestage-0.7.0.dist-info}/METADATA +1 -1
- thestage-0.7.0.dist-info/RECORD +226 -0
- {thestage-0.6.7.dist-info → thestage-0.7.0.dist-info}/WHEEL +1 -1
- thestage/controllers/project_controller.py +0 -1056
- thestage/services/clients/thestage_api/api_client.py +0 -751
- thestage/services/clients/thestage_api/dtos/container_param_request.py +0 -11
- thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py +0 -13
- thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +0 -13
- thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py +0 -10
- thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py +0 -12
- thestage/services/project/project_service.py +0 -1287
- thestage-0.6.7.dist-info/RECORD +0 -167
- /thestage/{entities → color_scheme}/__init__.py +0 -0
- /thestage/{entities/enums → config/business}/__init__.py +0 -0
- /thestage/{services/clients/git → config/communication}/__init__.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → config/dto}/__init__.py +0 -0
- /thestage/{services/core_files → config/dto}/config_entity.py +0 -0
- /thestage/{services/connect → config}/dto/remote_server_config.py +0 -0
- /thestage/{services/config_provider → connect}/__init__.py +0 -0
- /thestage/{services/container → connect/business}/__init__.py +0 -0
- /thestage/{services/container/mapper → connect/communication}/__init__.py +0 -0
- /thestage/{services/instance → connect/dto}/__init__.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_key_to_user_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/add_ssh_public_key_to_instance_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/is_user_has_public_ssh_key_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/ssh_key_controller → connect/dto}/is_user_has_public_ssh_key_response.py +0 -0
- /thestage/{services/instance/mapper → docker_container}/__init__.py +0 -0
- /thestage/{services/project → docker_container/business}/__init__.py +0 -0
- /thestage/{services/project → docker_container/business}/mapper/__init__.py +0 -0
- /thestage/{entities/container.py → docker_container/dto/container_entity.py} +0 -0
- /thestage/{services/clients/thestage_api/dtos/docker_container_controller → docker_container/dto}/docker_container_list_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → docker_container/dto}/docker_container_mapping.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → docker_container/dto/enum}/container_pending_action.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → docker_container/dto/enum}/container_status.py +0 -0
- /thestage/{services/logging/exception → exceptions}/log_polling_exception.py +0 -0
- /thestage/git/{ProgressPrinter.py → business/ProgressPrinter.py} +0 -0
- /thestage/{entities → global_dto}/enums/order_direction_type.py +0 -0
- /thestage/{entities → global_dto}/enums/shell_type.py +0 -0
- /thestage/{entities → global_dto}/enums/tail_output_type.py +0 -0
- /thestage/{entities → global_dto}/enums/yes_no_response.py +0 -0
- /thestage/{entities → global_dto}/file_item.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_instance_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_sagemaker_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_sagemaker_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → inference_model/dto/enum}/inference_model_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/inference_simulator_model_list_for_project_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → inference_model/dto}/inference_simulator_model_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → inference_simulator/dto/enum}/inference_simulator_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/get_inference_simulator_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/inference_simulator_list_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → inference_simulator/dto}/inference_simulator_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/cpu_type.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/gpu_name.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/instance_rented_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/provider_name.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → instance/dto/enum}/selfhosted_status.py +0 -0
- /thestage/{entities → instance/dto}/rented_instance.py +0 -0
- /thestage/{entities → instance/dto}/self_hosted_instance.py +0 -0
- /thestage/{services/logging → logging}/byte_print_style.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/docker_container_log_stream_request.py +0 -0
- /thestage/{services/logging → logging}/dto/log_message.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/log_polling_request.py +0 -0
- /thestage/{services/logging → logging}/dto/log_type.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/task_log_stream_request.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/logging_controller → logging/dto}/user_logs_query_request.py +0 -0
- /thestage/{services/logging → logging}/logging_constants.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py → project/dto/get_deploy_ssh_key_request.py} +0 -0
- /thestage/{services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_response.py → project/dto/get_deploy_ssh_key_response.py} +0 -0
- /thestage/{services/project → project}/dto/project_config.py +0 -0
- /thestage/{services/clients/thestage_api/dtos → project/dto}/project_response.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → task/dto/enum}/task_execution_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/enums → task/dto/enum}/task_status.py +0 -0
- /thestage/{services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py → task/dto/list_for_project_request.py} +0 -0
- /thestage/{services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py → task/dto/status_localized_map_response.py} +0 -0
- {thestage-0.6.7.dist-info → thestage-0.7.0.dist-info}/entry_points.txt +0 -0
- {thestage-0.6.7.dist-info → thestage-0.7.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -6,37 +6,47 @@ from rich import print
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
8
|
from thestage.color_scheme.color_scheme import ColorScheme
|
|
9
|
-
from thestage.
|
|
10
|
-
from thestage.
|
|
11
|
-
from thestage.
|
|
12
|
-
from thestage.
|
|
13
|
-
from thestage.
|
|
9
|
+
from thestage.connect.communication.connect_api_client import ConnectApiClient
|
|
10
|
+
from thestage.docker_container.business.mapper.image_mapper import ImageMapper
|
|
11
|
+
from thestage.docker_container.communication.docker_container_api_client import DockerContainerApiClient
|
|
12
|
+
from thestage.docker_container.dto.container_entity import DockerContainerEntity
|
|
13
|
+
from thestage.docker_container.dto.container_action_request import DockerContainerActionRequest
|
|
14
|
+
from thestage.docker_container.dto.docker_container_create_request import DockerContainerCreateRequest, \
|
|
15
|
+
DockerContainerMappings
|
|
16
|
+
from thestage.docker_container.dto.enum.container_pending_action import DockerContainerAction
|
|
17
|
+
from thestage.docker_container.dto.enum.container_status import DockerContainerStatus
|
|
18
|
+
from thestage.docker_container.dto.image_entity import DockerImageEntity
|
|
19
|
+
from thestage.global_dto.enums.shell_type import ShellType
|
|
20
|
+
from thestage.project.dto.project_config import ProjectConfig
|
|
14
21
|
from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
|
|
15
|
-
from thestage.
|
|
22
|
+
from thestage.docker_container.business.mapper.container_mapper import ContainerMapper
|
|
16
23
|
from thestage.services.filesystem_service import FileSystemService
|
|
17
|
-
from thestage.
|
|
24
|
+
from thestage.connect.business.remote_server_service import RemoteServerService
|
|
18
25
|
from thestage.i18n.translation import __
|
|
19
26
|
from thestage.services.abstract_service import AbstractService
|
|
20
|
-
from thestage.
|
|
27
|
+
from thestage.docker_container.dto.container_response import DockerContainerDto, DockerImageDto
|
|
21
28
|
from thestage.helpers.error_handler import error_handler
|
|
22
|
-
from thestage.
|
|
23
|
-
from thestage.services.config_provider.config_provider import ConfigProvider
|
|
29
|
+
from thestage.config.business.config_provider import ConfigProvider
|
|
24
30
|
|
|
25
31
|
|
|
26
32
|
class ContainerService(AbstractService):
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
__docker_container_api_client: DockerContainerApiClient = None
|
|
29
35
|
__config_provider: ConfigProvider = None
|
|
36
|
+
__connect_api_client: ConnectApiClient = None
|
|
30
37
|
|
|
31
38
|
def __init__(
|
|
32
39
|
self,
|
|
33
|
-
|
|
40
|
+
docker_container_api_client: DockerContainerApiClient,
|
|
34
41
|
config_provider: ConfigProvider,
|
|
35
42
|
remote_server_service: RemoteServerService,
|
|
36
43
|
file_system_service: FileSystemService,
|
|
44
|
+
connect_api_client: ConnectApiClient,
|
|
45
|
+
|
|
37
46
|
):
|
|
38
47
|
self.__config_provider = config_provider
|
|
39
|
-
self.
|
|
48
|
+
self.__connect_api_client = connect_api_client
|
|
49
|
+
self.__docker_container_api_client = docker_container_api_client
|
|
40
50
|
self.__remote_server_service = remote_server_service
|
|
41
51
|
self.__file_system_service = file_system_service
|
|
42
52
|
|
|
@@ -50,7 +60,7 @@ class ContainerService(AbstractService):
|
|
|
50
60
|
project_slug: Optional[str],
|
|
51
61
|
statuses: List[str],
|
|
52
62
|
):
|
|
53
|
-
container_status_map = self.
|
|
63
|
+
container_status_map = self.__docker_container_api_client.get_container_business_status_map()
|
|
54
64
|
|
|
55
65
|
if not statuses:
|
|
56
66
|
statuses = ({key: container_status_map[key] for key in [
|
|
@@ -103,7 +113,7 @@ class ContainerService(AbstractService):
|
|
|
103
113
|
project_slug: Optional[str] = None,
|
|
104
114
|
) -> PaginatedEntityList[DockerContainerDto]:
|
|
105
115
|
|
|
106
|
-
list = self.
|
|
116
|
+
list = self.__docker_container_api_client.get_container_list(
|
|
107
117
|
statuses=statuses,
|
|
108
118
|
page=page,
|
|
109
119
|
limit=row,
|
|
@@ -113,6 +123,7 @@ class ContainerService(AbstractService):
|
|
|
113
123
|
|
|
114
124
|
return list
|
|
115
125
|
|
|
126
|
+
|
|
116
127
|
# TODO delete this proxy method
|
|
117
128
|
@error_handler()
|
|
118
129
|
def get_container(
|
|
@@ -120,7 +131,7 @@ class ContainerService(AbstractService):
|
|
|
120
131
|
container_public_id: Optional[str] = None,
|
|
121
132
|
container_slug: Optional[str] = None,
|
|
122
133
|
) -> Optional[DockerContainerDto]:
|
|
123
|
-
return self.
|
|
134
|
+
return self.__docker_container_api_client.get_container(
|
|
124
135
|
container_public_id=container_public_id,
|
|
125
136
|
container_slug=container_slug,
|
|
126
137
|
)
|
|
@@ -287,7 +298,7 @@ class ContainerService(AbstractService):
|
|
|
287
298
|
typer.echo('Container identifier (container_id_or_name) is required')
|
|
288
299
|
raise typer.Exit(1)
|
|
289
300
|
|
|
290
|
-
resolved_options = self.
|
|
301
|
+
resolved_options = self.__connect_api_client.resolve_user_input(entity_identifier=container_identifier)
|
|
291
302
|
container_public_id = None
|
|
292
303
|
valid_container_count = 0
|
|
293
304
|
for container_item in resolved_options.dockerContainerMatchData:
|
|
@@ -302,7 +313,7 @@ class ContainerService(AbstractService):
|
|
|
302
313
|
typer.echo(f"Failed to resolve the container by provided identifier, as total of {valid_container_count} containers are valid options")
|
|
303
314
|
raise typer.Exit(1)
|
|
304
315
|
|
|
305
|
-
container: Optional[DockerContainerDto] = self.
|
|
316
|
+
container: Optional[DockerContainerDto] = self.__docker_container_api_client.get_container(
|
|
306
317
|
container_public_id=container_public_id,
|
|
307
318
|
)
|
|
308
319
|
|
|
@@ -366,7 +377,7 @@ class ContainerService(AbstractService):
|
|
|
366
377
|
typer.echo('Container identifier (container_id_or_name) is required')
|
|
367
378
|
raise typer.Exit(1)
|
|
368
379
|
|
|
369
|
-
resolved_options = self.
|
|
380
|
+
resolved_options = self.__connect_api_client.resolve_user_input(entity_identifier=container_identifier)
|
|
370
381
|
container_public_id = None
|
|
371
382
|
valid_container_count = 0
|
|
372
383
|
for container_item in resolved_options.dockerContainerMatchData:
|
|
@@ -381,7 +392,7 @@ class ContainerService(AbstractService):
|
|
|
381
392
|
typer.echo(f"Failed to resolve the container by provided identifier, as total of {valid_container_count} containers are valid options")
|
|
382
393
|
raise typer.Exit(1)
|
|
383
394
|
|
|
384
|
-
container: Optional[DockerContainerDto] = self.
|
|
395
|
+
container: Optional[DockerContainerDto] = self.__docker_container_api_client.get_container(
|
|
385
396
|
container_public_id=container_public_id,
|
|
386
397
|
)
|
|
387
398
|
|
|
@@ -441,13 +452,127 @@ class ContainerService(AbstractService):
|
|
|
441
452
|
if action in [DockerContainerAction.STOP, DockerContainerAction.RESTART]:
|
|
442
453
|
self.check_if_container_running(container=container)
|
|
443
454
|
|
|
444
|
-
request_params =
|
|
455
|
+
request_params = DockerContainerActionRequest(
|
|
445
456
|
dockerContainerPublicId=container.public_id,
|
|
446
457
|
action=action,
|
|
447
458
|
)
|
|
448
|
-
result = self.
|
|
459
|
+
result = self.__docker_container_api_client.container_action(
|
|
449
460
|
request_param=request_params,
|
|
450
461
|
)
|
|
451
462
|
|
|
452
463
|
if result.is_success:
|
|
453
464
|
typer.echo(f'Docker container action scheduled: {action.value}')
|
|
465
|
+
|
|
466
|
+
@error_handler()
|
|
467
|
+
def create_docker_container(
|
|
468
|
+
self,
|
|
469
|
+
project_public_id: Optional[str],
|
|
470
|
+
project_slug: Optional[str],
|
|
471
|
+
container_slug: str,
|
|
472
|
+
rented_instance_public_id: Optional[str],
|
|
473
|
+
rented_instance_slug: Optional[str],
|
|
474
|
+
self_hosted_instance_public_id: Optional[str],
|
|
475
|
+
self_hosted_instance_slug: Optional[str],
|
|
476
|
+
image_name: str,
|
|
477
|
+
cpu_number: Optional[int],
|
|
478
|
+
gpu_number: Optional[int],
|
|
479
|
+
volume_mappings: Optional[Dict[str, str]],
|
|
480
|
+
):
|
|
481
|
+
if not project_public_id and not project_slug:
|
|
482
|
+
project_config: ProjectConfig = self.__config_provider.read_project_config()
|
|
483
|
+
if not project_config:
|
|
484
|
+
typer.echo("Provide the project unique ID or name, or run this command from within an initialized project directory")
|
|
485
|
+
raise typer.Exit(1)
|
|
486
|
+
project_public_id = project_config.public_id
|
|
487
|
+
|
|
488
|
+
docker_images_paginated = self.get_image_list()
|
|
489
|
+
if not docker_images_paginated or not docker_images_paginated.entities:
|
|
490
|
+
typer.echo("No Docker images available")
|
|
491
|
+
raise typer.Exit(1)
|
|
492
|
+
|
|
493
|
+
selected_image = None
|
|
494
|
+
selection_pool = docker_images_paginated.entities
|
|
495
|
+
|
|
496
|
+
if image_name is not None:
|
|
497
|
+
matches = [img for img in selection_pool if img.image == image_name]
|
|
498
|
+
|
|
499
|
+
if len(matches) == 1:
|
|
500
|
+
selected_image = matches[0]
|
|
501
|
+
elif len(matches) > 1:
|
|
502
|
+
typer.echo(f"Multiple tags found for repository '{image_name}':")
|
|
503
|
+
selection_pool = matches
|
|
504
|
+
else:
|
|
505
|
+
typer.echo(f"Image '{image_name}' not found. Select from available images:")
|
|
506
|
+
|
|
507
|
+
if selected_image is None:
|
|
508
|
+
for idx, img in enumerate(selection_pool, start=1):
|
|
509
|
+
typer.echo(f"{idx}) {img.image}:{img.tag}")
|
|
510
|
+
|
|
511
|
+
choice_str = typer.prompt("Choose which image to use")
|
|
512
|
+
|
|
513
|
+
try:
|
|
514
|
+
choice_index = int(choice_str)
|
|
515
|
+
except ValueError:
|
|
516
|
+
typer.echo("Error: Invalid input. Enter a number.")
|
|
517
|
+
raise typer.Exit(1)
|
|
518
|
+
|
|
519
|
+
if not (1 <= choice_index <= len(selection_pool)):
|
|
520
|
+
typer.echo("Error: Choice out of range.")
|
|
521
|
+
raise typer.Exit(1)
|
|
522
|
+
|
|
523
|
+
selected_image = selection_pool[choice_index - 1]
|
|
524
|
+
|
|
525
|
+
request_params = DockerContainerCreateRequest(
|
|
526
|
+
instance_rented_public_id=rented_instance_public_id,
|
|
527
|
+
instance_rented_slug=rented_instance_slug,
|
|
528
|
+
selfhosted_instance_public_id=self_hosted_instance_public_id,
|
|
529
|
+
selfhosted_instance_slug=self_hosted_instance_slug,
|
|
530
|
+
project_public_id=project_public_id,
|
|
531
|
+
project_slug=project_slug,
|
|
532
|
+
container_slug=container_slug,
|
|
533
|
+
docker_image_id=selected_image.id,
|
|
534
|
+
assigned_cpus=cpu_number,
|
|
535
|
+
is_unlimited_cpus=cpu_number is None,
|
|
536
|
+
assigned_gpus=gpu_number,
|
|
537
|
+
is_unlimited_gpus=gpu_number is None,
|
|
538
|
+
mappings=DockerContainerMappings(directory_mappings=volume_mappings)
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
result = self.__docker_container_api_client.create_container(
|
|
542
|
+
request_params
|
|
543
|
+
)
|
|
544
|
+
if result.is_success:
|
|
545
|
+
typer.echo(f'Docker container creation scheduled.')
|
|
546
|
+
|
|
547
|
+
@error_handler()
|
|
548
|
+
def print_docker_image_list(
|
|
549
|
+
self,
|
|
550
|
+
row: int,
|
|
551
|
+
page: int,
|
|
552
|
+
):
|
|
553
|
+
typer.echo("Listing available Docker images:")
|
|
554
|
+
|
|
555
|
+
self.print(
|
|
556
|
+
func_get_data=self.get_image_list,
|
|
557
|
+
func_special_params={},
|
|
558
|
+
mapper=ImageMapper(),
|
|
559
|
+
headers=list(map(lambda x: x.alias, DockerImageEntity.model_fields.values())),
|
|
560
|
+
row=row,
|
|
561
|
+
page=page,
|
|
562
|
+
max_col_width=[50, 20],
|
|
563
|
+
show_index="never",
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
@error_handler()
|
|
567
|
+
def get_image_list(
|
|
568
|
+
self,
|
|
569
|
+
row: int = 5,
|
|
570
|
+
page: int = 1,
|
|
571
|
+
) -> PaginatedEntityList[DockerImageDto]:
|
|
572
|
+
|
|
573
|
+
list = self.__docker_container_api_client.get_docker_image_list(
|
|
574
|
+
page=page,
|
|
575
|
+
limit=row,
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
return list
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from typing import Optional
|
|
1
|
+
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from thestage.
|
|
4
|
-
from thestage.
|
|
3
|
+
from thestage.docker_container.dto.container_response import DockerContainerDto
|
|
4
|
+
from thestage.docker_container.dto.container_entity import DockerContainerEntity
|
|
5
5
|
from thestage.services.abstract_mapper import AbstractMapper
|
|
6
6
|
|
|
7
7
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from thestage.docker_container.dto.container_response import DockerImageDto
|
|
4
|
+
from thestage.docker_container.dto.image_entity import DockerImageEntity
|
|
5
|
+
from thestage.services.abstract_mapper import AbstractMapper
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ImageMapper(AbstractMapper):
|
|
9
|
+
def build_entity(self, item: DockerImageDto) -> Optional[DockerImageEntity]:
|
|
10
|
+
if not item:
|
|
11
|
+
return None
|
|
12
|
+
|
|
13
|
+
return DockerImageEntity(
|
|
14
|
+
image=item.image or '',
|
|
15
|
+
tag=item.tag or '',
|
|
16
|
+
)
|
|
File without changes
|
thestage/{controllers/container_controller.py → docker_container/communication/docker_command.py}
RENAMED
|
@@ -1,27 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
import re
|
|
3
1
|
from pathlib import Path
|
|
4
2
|
from typing import Optional, List
|
|
5
|
-
|
|
3
|
+
|
|
4
|
+
import typer
|
|
6
5
|
|
|
7
6
|
from thestage.cli_command import CliCommand
|
|
8
7
|
from thestage.cli_command_helper import get_command_metadata, check_command_permission
|
|
9
|
-
from thestage.color_scheme.color_scheme import ColorScheme
|
|
10
|
-
from thestage.services.clients.thestage_api.api_client import TheStageApiClient
|
|
11
|
-
from thestage.services.clients.thestage_api.dtos.enums.container_pending_action import DockerContainerAction
|
|
12
|
-
from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
|
|
13
|
-
from thestage.i18n.translation import __
|
|
14
|
-
from thestage.services.container.container_service import ContainerService
|
|
15
|
-
from thestage.helpers.logger.app_logger import app_logger
|
|
16
8
|
from thestage.controllers.utils_controller import validate_config_and_get_service_factory, get_current_directory
|
|
17
|
-
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
from thestage.
|
|
9
|
+
from thestage.docker_container.business.container_service import ContainerService
|
|
10
|
+
from thestage.docker_container.dto.container_response import DockerContainerDto
|
|
11
|
+
from thestage.docker_container.dto.enum.container_pending_action import DockerContainerAction
|
|
12
|
+
from thestage.helpers.logger.app_logger import app_logger
|
|
13
|
+
from thestage.i18n.translation import __
|
|
14
|
+
from thestage.logging.business.logging_service import LoggingService
|
|
21
15
|
|
|
22
16
|
app = typer.Typer(no_args_is_help=True, help=__("Manage containers"))
|
|
23
17
|
|
|
24
|
-
|
|
25
18
|
@app.command(name='ls', help=__("List containers"), **get_command_metadata(CliCommand.CONTAINER_LS))
|
|
26
19
|
def list_containers(
|
|
27
20
|
row: int = typer.Option(
|
|
@@ -65,7 +58,7 @@ def list_containers(
|
|
|
65
58
|
check_command_permission(command_name)
|
|
66
59
|
|
|
67
60
|
if sum(v is not None for v in [project_public_id, project_slug]) > 1:
|
|
68
|
-
typer.echo("
|
|
61
|
+
typer.echo("Provide a single identifier for project - ID or name.")
|
|
69
62
|
raise typer.Exit(1)
|
|
70
63
|
|
|
71
64
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -104,7 +97,7 @@ def container_info(
|
|
|
104
97
|
check_command_permission(command_name)
|
|
105
98
|
|
|
106
99
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
107
|
-
typer.echo("
|
|
100
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
108
101
|
raise typer.Exit(1)
|
|
109
102
|
|
|
110
103
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -194,7 +187,7 @@ def container_connect(
|
|
|
194
187
|
check_command_permission(command_name)
|
|
195
188
|
|
|
196
189
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
197
|
-
typer.echo("
|
|
190
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
198
191
|
raise typer.Exit(1)
|
|
199
192
|
|
|
200
193
|
if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
|
|
@@ -240,7 +233,7 @@ def upload_file(
|
|
|
240
233
|
username_param=username,
|
|
241
234
|
)
|
|
242
235
|
|
|
243
|
-
app_logger.info(f'
|
|
236
|
+
app_logger.info(f'File upload completed')
|
|
244
237
|
raise typer.Exit(0)
|
|
245
238
|
|
|
246
239
|
|
|
@@ -269,7 +262,7 @@ def download_file(
|
|
|
269
262
|
username_param=username,
|
|
270
263
|
)
|
|
271
264
|
|
|
272
|
-
app_logger.info(f'
|
|
265
|
+
app_logger.info(f'File download completed')
|
|
273
266
|
raise typer.Exit(0)
|
|
274
267
|
|
|
275
268
|
|
|
@@ -295,7 +288,7 @@ def start_container(
|
|
|
295
288
|
check_command_permission(command_name)
|
|
296
289
|
|
|
297
290
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
298
|
-
typer.echo("
|
|
291
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
299
292
|
raise typer.Exit(1)
|
|
300
293
|
|
|
301
294
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -307,7 +300,140 @@ def start_container(
|
|
|
307
300
|
action=DockerContainerAction.START
|
|
308
301
|
)
|
|
309
302
|
|
|
310
|
-
app_logger.info(f'
|
|
303
|
+
app_logger.info(f'Container is starting')
|
|
304
|
+
raise typer.Exit(0)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@app.command(name="create", no_args_is_help=True, help=__("Create container"), **get_command_metadata(CliCommand.CONTAINER_CREATE))
|
|
308
|
+
def create_container(
|
|
309
|
+
project_public_id: Optional[str] = typer.Option(
|
|
310
|
+
None,
|
|
311
|
+
'--project-id',
|
|
312
|
+
'-pid',
|
|
313
|
+
help=__("Project ID. By default, project info is taken from the current directory"),
|
|
314
|
+
is_eager=False,
|
|
315
|
+
),
|
|
316
|
+
project_slug: Optional[str] = typer.Option(
|
|
317
|
+
None,
|
|
318
|
+
'--project-name',
|
|
319
|
+
'-pn',
|
|
320
|
+
help=__("Project name. By default, project info is taken from the current directory"),
|
|
321
|
+
is_eager=False,
|
|
322
|
+
),
|
|
323
|
+
working_directory: Optional[str] = typer.Option(
|
|
324
|
+
None,
|
|
325
|
+
"--working-directory",
|
|
326
|
+
"-wd",
|
|
327
|
+
help=__("Full path to working directory"),
|
|
328
|
+
show_default=False,
|
|
329
|
+
is_eager=False,
|
|
330
|
+
),
|
|
331
|
+
container_slug: Optional[str] = typer.Option(
|
|
332
|
+
None,
|
|
333
|
+
'--container-name',
|
|
334
|
+
'-cn',
|
|
335
|
+
help=__("Container name"),
|
|
336
|
+
is_eager=False,
|
|
337
|
+
),
|
|
338
|
+
rented_instance_public_id: Optional[str] = typer.Option(
|
|
339
|
+
None,
|
|
340
|
+
'--rented-instance-id',
|
|
341
|
+
'-rid',
|
|
342
|
+
help=__("Rented instance ID on which container will run"),
|
|
343
|
+
is_eager=False,
|
|
344
|
+
),
|
|
345
|
+
rented_instance_slug: Optional[str] = typer.Option(
|
|
346
|
+
None,
|
|
347
|
+
'--rented-instance-name',
|
|
348
|
+
'-rn',
|
|
349
|
+
help=__("Rented instance name on which container will run"),
|
|
350
|
+
is_eager=False,
|
|
351
|
+
),
|
|
352
|
+
self_hosted_instance_public_id: Optional[str] = typer.Option(
|
|
353
|
+
None,
|
|
354
|
+
'--self-hosted-instance-id',
|
|
355
|
+
'-sid',
|
|
356
|
+
help=__("Self-hosted instance ID on which container will run"),
|
|
357
|
+
is_eager=False,
|
|
358
|
+
),
|
|
359
|
+
self_hosted_instance_slug: Optional[str] = typer.Option(
|
|
360
|
+
None,
|
|
361
|
+
'--self-hosted-instance-name',
|
|
362
|
+
'-sn',
|
|
363
|
+
help=__("Self-hosted instance name on which container will run"),
|
|
364
|
+
is_eager=False,
|
|
365
|
+
),
|
|
366
|
+
image_name: Optional[str] = typer.Option(
|
|
367
|
+
None,
|
|
368
|
+
'--image',
|
|
369
|
+
'-i',
|
|
370
|
+
help=__("Docker image name. If not provided, you will be prompted to select from available images"),
|
|
371
|
+
is_eager=False,
|
|
372
|
+
),
|
|
373
|
+
gpu_number: Optional[int] = typer.Option(
|
|
374
|
+
None,
|
|
375
|
+
'--gpu-number',
|
|
376
|
+
'-gpun',
|
|
377
|
+
help=__("Number of assigned GPUs for container. No GPU limit by default"),
|
|
378
|
+
is_eager=False,
|
|
379
|
+
),
|
|
380
|
+
cpu_number: Optional[int] = typer.Option(
|
|
381
|
+
None,
|
|
382
|
+
'--cpu-number',
|
|
383
|
+
'-cpun',
|
|
384
|
+
help=__("Number of assigned CPUs for container. No CPU limit by default"),
|
|
385
|
+
is_eager=False,
|
|
386
|
+
),
|
|
387
|
+
volume_mounts: Optional[List[str]] = typer.Option(
|
|
388
|
+
None,
|
|
389
|
+
'--volume',
|
|
390
|
+
'-v',
|
|
391
|
+
help=__("Volume mounts. Can be used multiple times. Format: /host_dir:/container_dir"),
|
|
392
|
+
is_eager=False,
|
|
393
|
+
),
|
|
394
|
+
):
|
|
395
|
+
command_name = CliCommand.CONTAINER_CREATE
|
|
396
|
+
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
397
|
+
check_command_permission(command_name)
|
|
398
|
+
|
|
399
|
+
if sum(v is not None for v in [project_public_id, project_slug]) > 1:
|
|
400
|
+
typer.echo("Provide a single identifier for project - ID or name.")
|
|
401
|
+
raise typer.Exit(1)
|
|
402
|
+
|
|
403
|
+
if sum(v is not None for v in [rented_instance_public_id, rented_instance_slug, self_hosted_instance_public_id, self_hosted_instance_slug]) != 1:
|
|
404
|
+
typer.echo("Provide exactly one identifier (ID or Name) for either a rented or self-hosted instance.")
|
|
405
|
+
raise typer.Exit(1)
|
|
406
|
+
|
|
407
|
+
if not container_slug:
|
|
408
|
+
container_slug = typer.prompt("Enter container name")
|
|
409
|
+
|
|
410
|
+
volume_mappings_dict = {}
|
|
411
|
+
if volume_mounts:
|
|
412
|
+
for mount in volume_mounts:
|
|
413
|
+
if ":" not in mount:
|
|
414
|
+
typer.echo(f"Invalid volume format: {mount}. Expected host:container")
|
|
415
|
+
raise typer.Exit(1)
|
|
416
|
+
host_path, container_path = mount.split(":", 1)
|
|
417
|
+
volume_mappings_dict[host_path] = container_path
|
|
418
|
+
|
|
419
|
+
service_factory = validate_config_and_get_service_factory(working_directory=working_directory)
|
|
420
|
+
container_service: ContainerService = service_factory.get_container_service()
|
|
421
|
+
|
|
422
|
+
container_service.create_docker_container(
|
|
423
|
+
project_public_id=project_public_id,
|
|
424
|
+
project_slug=project_slug,
|
|
425
|
+
container_slug=container_slug,
|
|
426
|
+
rented_instance_public_id=rented_instance_public_id,
|
|
427
|
+
rented_instance_slug=rented_instance_slug,
|
|
428
|
+
self_hosted_instance_public_id=self_hosted_instance_public_id,
|
|
429
|
+
self_hosted_instance_slug=self_hosted_instance_slug,
|
|
430
|
+
image_name=image_name,
|
|
431
|
+
cpu_number=cpu_number,
|
|
432
|
+
gpu_number=gpu_number,
|
|
433
|
+
volume_mappings=volume_mappings_dict
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
app_logger.info(f'Container is creating')
|
|
311
437
|
raise typer.Exit(0)
|
|
312
438
|
|
|
313
439
|
|
|
@@ -333,7 +459,7 @@ def stop_container(
|
|
|
333
459
|
check_command_permission(command_name)
|
|
334
460
|
|
|
335
461
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
336
|
-
typer.echo("
|
|
462
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
337
463
|
raise typer.Exit(1)
|
|
338
464
|
|
|
339
465
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -345,10 +471,47 @@ def stop_container(
|
|
|
345
471
|
action=DockerContainerAction.STOP
|
|
346
472
|
)
|
|
347
473
|
|
|
348
|
-
app_logger.info(f'
|
|
474
|
+
app_logger.info(f'Container is stopping')
|
|
349
475
|
raise typer.Exit(0)
|
|
350
476
|
|
|
351
477
|
|
|
478
|
+
@app.command(name="delete", no_args_is_help=True, help=__("Delete container"), **get_command_metadata(CliCommand.CONTAINER_DELETE))
|
|
479
|
+
def delete_container(
|
|
480
|
+
container_public_id: str = typer.Option(
|
|
481
|
+
None,
|
|
482
|
+
'--container-id',
|
|
483
|
+
'-cid',
|
|
484
|
+
help=__("Container ID"),
|
|
485
|
+
is_eager=False,
|
|
486
|
+
),
|
|
487
|
+
container_slug: str = typer.Option(
|
|
488
|
+
None,
|
|
489
|
+
'--container-name',
|
|
490
|
+
'-cn',
|
|
491
|
+
help=__("Container name"),
|
|
492
|
+
is_eager=False,
|
|
493
|
+
),
|
|
494
|
+
):
|
|
495
|
+
command_name = CliCommand.CONTAINER_DELETE
|
|
496
|
+
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
497
|
+
check_command_permission(command_name)
|
|
498
|
+
|
|
499
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
500
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
501
|
+
raise typer.Exit(1)
|
|
502
|
+
|
|
503
|
+
service_factory = validate_config_and_get_service_factory()
|
|
504
|
+
container_service: ContainerService = service_factory.get_container_service()
|
|
505
|
+
|
|
506
|
+
container_service.request_docker_container_action(
|
|
507
|
+
container_public_id=container_public_id,
|
|
508
|
+
container_slug=container_slug,
|
|
509
|
+
action=DockerContainerAction.DELETE
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
app_logger.info(f'Container is deleting')
|
|
513
|
+
raise typer.Exit(0)
|
|
514
|
+
|
|
352
515
|
@app.command(name="restart", no_args_is_help=True, help=__("Restart container"), **get_command_metadata(CliCommand.CONTAINER_RESTART))
|
|
353
516
|
def restart_container(
|
|
354
517
|
container_public_id: str = typer.Option(
|
|
@@ -371,7 +534,7 @@ def restart_container(
|
|
|
371
534
|
check_command_permission(command_name)
|
|
372
535
|
|
|
373
536
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
374
|
-
typer.echo("
|
|
537
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
375
538
|
raise typer.Exit(1)
|
|
376
539
|
|
|
377
540
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -383,7 +546,7 @@ def restart_container(
|
|
|
383
546
|
action=DockerContainerAction.RESTART
|
|
384
547
|
)
|
|
385
548
|
|
|
386
|
-
app_logger.info(f'
|
|
549
|
+
app_logger.info(f'Container is restarting')
|
|
387
550
|
raise typer.Exit(0)
|
|
388
551
|
|
|
389
552
|
|
|
@@ -416,7 +579,7 @@ def container_logs(
|
|
|
416
579
|
check_command_permission(command_name)
|
|
417
580
|
|
|
418
581
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
419
|
-
typer.echo("
|
|
582
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
420
583
|
raise typer.Exit(1)
|
|
421
584
|
|
|
422
585
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -430,5 +593,5 @@ def container_logs(
|
|
|
430
593
|
else:
|
|
431
594
|
logging_service.print_last_container_logs(container_public_id=container_public_id, container_slug=container_slug, logs_number=logs_number)
|
|
432
595
|
|
|
433
|
-
app_logger.info(f'Container
|
|
434
|
-
raise typer.Exit(0)
|
|
596
|
+
app_logger.info(f'Container log streaming completed')
|
|
597
|
+
raise typer.Exit(0)
|