thestage 0.6.6__py3-none-any.whl → 0.6.8__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_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 +25 -22
- 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 +1 -1
- thestage/controllers/base_controller.py +2 -2
- thestage/debug_main.dist.py +16 -14
- thestage/{services/container → docker_container/business}/container_service.py +120 -40
- thestage/{services/container → docker_container/business}/mapper/container_mapper.py +3 -3
- thestage/docker_container/communication/__init__.py +0 -0
- thestage/{controllers/container_controller.py → docker_container/communication/docker_command.py} +27 -86
- thestage/docker_container/communication/docker_container_api_client.py +99 -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 +4 -4
- thestage/{services/clients/thestage_api/dtos/docker_container_controller → docker_container/dto}/docker_container_list_response.py +3 -5
- thestage/docker_container/dto/enum/__init__.py +0 -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 +5 -5
- thestage/global_dto/__init__.py +0 -0
- thestage/global_dto/enums/__init__.py +0 -0
- thestage/helpers/error_handler.py +5 -5
- 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_request.py +0 -2
- thestage/{services/clients/thestage_api/dtos/inference_controller → inference_model/dto}/deploy_inference_model_to_instance_response.py +2 -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} +2 -2
- 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/{services/clients/thestage_api/dtos/inference_controller → inference_simulator/dto}/get_inference_simulator_request.py +1 -1
- 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} +9 -9
- 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 +45 -36
- 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 +48 -9
- 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/project → project}/dto/project_config.py +1 -2
- 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 +304 -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.6.dist-info → thestage-0.6.8.dist-info}/METADATA +2 -1
- thestage-0.6.8.dist-info/RECORD +219 -0
- {thestage-0.6.6.dist-info → thestage-0.6.8.dist-info}/WHEEL +1 -1
- thestage/controllers/project_controller.py +0 -1058
- thestage/services/clients/thestage_api/api_client.py +0 -753
- 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 -10
- 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 -1283
- thestage-0.6.6.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_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}/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/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.6.dist-info → thestage-0.6.8.dist-info}/entry_points.txt +0 -0
- {thestage-0.6.6.dist-info → thestage-0.6.8.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -1,38 +1,47 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import List, Tuple, Optional, Dict
|
|
4
|
+
from rich import print
|
|
3
5
|
|
|
4
6
|
import typer
|
|
5
|
-
|
|
6
|
-
from thestage.
|
|
7
|
-
from thestage.
|
|
8
|
-
from thestage.
|
|
9
|
-
from thestage.
|
|
7
|
+
|
|
8
|
+
from thestage.color_scheme.color_scheme import ColorScheme
|
|
9
|
+
from thestage.connect.communication.connect_api_client import ConnectApiClient
|
|
10
|
+
from thestage.docker_container.communication.docker_container_api_client import DockerContainerApiClient
|
|
11
|
+
from thestage.docker_container.dto.container_entity import DockerContainerEntity
|
|
12
|
+
from thestage.docker_container.dto.container_action_request import DockerContainerActionRequest
|
|
13
|
+
from thestage.docker_container.dto.enum.container_pending_action import DockerContainerAction
|
|
14
|
+
from thestage.docker_container.dto.enum.container_status import DockerContainerStatus
|
|
15
|
+
from thestage.global_dto.enums.shell_type import ShellType
|
|
10
16
|
from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
|
|
11
|
-
from thestage.
|
|
17
|
+
from thestage.docker_container.business.mapper.container_mapper import ContainerMapper
|
|
12
18
|
from thestage.services.filesystem_service import FileSystemService
|
|
13
|
-
from thestage.
|
|
19
|
+
from thestage.connect.business.remote_server_service import RemoteServerService
|
|
14
20
|
from thestage.i18n.translation import __
|
|
15
21
|
from thestage.services.abstract_service import AbstractService
|
|
16
|
-
from thestage.
|
|
22
|
+
from thestage.docker_container.dto.container_response import DockerContainerDto
|
|
17
23
|
from thestage.helpers.error_handler import error_handler
|
|
18
|
-
from thestage.
|
|
19
|
-
from thestage.services.config_provider.config_provider import ConfigProvider
|
|
24
|
+
from thestage.config.business.config_provider import ConfigProvider
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
class ContainerService(AbstractService):
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
__docker_container_api_client: DockerContainerApiClient = None
|
|
25
30
|
__config_provider: ConfigProvider = None
|
|
31
|
+
__connect_api_client: ConnectApiClient = None
|
|
26
32
|
|
|
27
33
|
def __init__(
|
|
28
34
|
self,
|
|
29
|
-
|
|
35
|
+
docker_container_api_client: DockerContainerApiClient,
|
|
30
36
|
config_provider: ConfigProvider,
|
|
31
37
|
remote_server_service: RemoteServerService,
|
|
32
38
|
file_system_service: FileSystemService,
|
|
39
|
+
connect_api_client: ConnectApiClient,
|
|
40
|
+
|
|
33
41
|
):
|
|
34
42
|
self.__config_provider = config_provider
|
|
35
|
-
self.
|
|
43
|
+
self.__connect_api_client = connect_api_client
|
|
44
|
+
self.__docker_container_api_client = docker_container_api_client
|
|
36
45
|
self.__remote_server_service = remote_server_service
|
|
37
46
|
self.__file_system_service = file_system_service
|
|
38
47
|
|
|
@@ -46,7 +55,7 @@ class ContainerService(AbstractService):
|
|
|
46
55
|
project_slug: Optional[str],
|
|
47
56
|
statuses: List[str],
|
|
48
57
|
):
|
|
49
|
-
container_status_map = self.
|
|
58
|
+
container_status_map = self.__docker_container_api_client.get_container_business_status_map()
|
|
50
59
|
|
|
51
60
|
if not statuses:
|
|
52
61
|
statuses = ({key: container_status_map[key] for key in [
|
|
@@ -99,7 +108,7 @@ class ContainerService(AbstractService):
|
|
|
99
108
|
project_slug: Optional[str] = None,
|
|
100
109
|
) -> PaginatedEntityList[DockerContainerDto]:
|
|
101
110
|
|
|
102
|
-
list = self.
|
|
111
|
+
list = self.__docker_container_api_client.get_container_list(
|
|
103
112
|
statuses=statuses,
|
|
104
113
|
page=page,
|
|
105
114
|
limit=row,
|
|
@@ -116,7 +125,7 @@ class ContainerService(AbstractService):
|
|
|
116
125
|
container_public_id: Optional[str] = None,
|
|
117
126
|
container_slug: Optional[str] = None,
|
|
118
127
|
) -> Optional[DockerContainerDto]:
|
|
119
|
-
return self.
|
|
128
|
+
return self.__docker_container_api_client.get_container(
|
|
120
129
|
container_public_id=container_public_id,
|
|
121
130
|
container_slug=container_slug,
|
|
122
131
|
)
|
|
@@ -150,7 +159,7 @@ class ContainerService(AbstractService):
|
|
|
150
159
|
if private_key_path:
|
|
151
160
|
typer.echo(f'Using configured private key for {ip_address}: {private_key_path}')
|
|
152
161
|
else:
|
|
153
|
-
typer.echo(f'Using SSH agent to connect to {ip_address}')
|
|
162
|
+
typer.echo(f'Using SSH agent to connect to {ip_address} as {username}')
|
|
154
163
|
else:
|
|
155
164
|
self.__config_provider.update_remote_server_config_entry(ip_address, Path(private_key_path))
|
|
156
165
|
typer.echo(f'Updated private key path for {ip_address}: {private_key_path}')
|
|
@@ -267,22 +276,49 @@ class ContainerService(AbstractService):
|
|
|
267
276
|
@error_handler()
|
|
268
277
|
def put_file_to_container(
|
|
269
278
|
self,
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
destination_path: Optional[str] = None,
|
|
274
|
-
username_param: Optional[str] = None,
|
|
279
|
+
source_path: str,
|
|
280
|
+
destination: str,
|
|
281
|
+
username_param: Optional[str],
|
|
275
282
|
):
|
|
276
|
-
|
|
277
|
-
|
|
283
|
+
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", destination)
|
|
284
|
+
if container_args is None:
|
|
285
|
+
typer.echo(__('Container name and source file path are required as the second argument'))
|
|
286
|
+
typer.echo(__('Example: container_name:/path/to/file'))
|
|
278
287
|
raise typer.Exit(1)
|
|
288
|
+
container_identifier = container_args.groups()[0]
|
|
289
|
+
destination_path = container_args.groups()[1].rstrip("/")
|
|
279
290
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
291
|
+
if not container_identifier:
|
|
292
|
+
typer.echo('Container identifier (container_id_or_name) is required')
|
|
293
|
+
raise typer.Exit(1)
|
|
294
|
+
|
|
295
|
+
resolved_options = self.__connect_api_client.resolve_user_input(entity_identifier=container_identifier)
|
|
296
|
+
container_public_id = None
|
|
297
|
+
valid_container_count = 0
|
|
298
|
+
for container_item in resolved_options.dockerContainerMatchData:
|
|
299
|
+
message = f"Found a container with matching {container_item.matchedField} in status: '{container_item.frontendStatus.status_translation}' (ID: {container_item.publicId})"
|
|
300
|
+
line_color = ColorScheme.SUCCESS.value if container_item.canDownloadUploadOnContainer else 'default'
|
|
301
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
302
|
+
if container_item.canDownloadUploadOnContainer:
|
|
303
|
+
valid_container_count += 1
|
|
304
|
+
container_public_id = container_item.publicId
|
|
305
|
+
|
|
306
|
+
if valid_container_count != 1:
|
|
307
|
+
typer.echo(f"Failed to resolve the container by provided identifier, as total of {valid_container_count} containers are valid options")
|
|
308
|
+
raise typer.Exit(1)
|
|
309
|
+
|
|
310
|
+
container: Optional[DockerContainerDto] = self.__docker_container_api_client.get_container(
|
|
311
|
+
container_public_id=container_public_id,
|
|
284
312
|
)
|
|
285
313
|
|
|
314
|
+
if not container:
|
|
315
|
+
typer.echo(f"Unexpected error: container '{container_public_id}' not found")
|
|
316
|
+
raise typer.Exit(1)
|
|
317
|
+
|
|
318
|
+
if not self.__file_system_service.check_if_path_exist(file=source_path):
|
|
319
|
+
typer.echo(__("File not found at specified path"))
|
|
320
|
+
raise typer.Exit(1)
|
|
321
|
+
|
|
286
322
|
if not container.mappings or not container.mappings.directory_mappings:
|
|
287
323
|
typer.echo(__("Mapping folders not found"))
|
|
288
324
|
raise typer.Exit(1)
|
|
@@ -296,10 +332,18 @@ class ContainerService(AbstractService):
|
|
|
296
332
|
typer.echo(__("Cannot find matching container volume mapping for specified file path"))
|
|
297
333
|
raise typer.Exit(1)
|
|
298
334
|
|
|
335
|
+
username, ip_address, private_key_path = self.get_server_auth(
|
|
336
|
+
container=container,
|
|
337
|
+
username_param=username_param,
|
|
338
|
+
private_key_path_override=None
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
copy_only_folder_contents = source_path.endswith("/")
|
|
342
|
+
|
|
299
343
|
self.__remote_server_service.upload_data_to_container(
|
|
300
344
|
ip_address=ip_address,
|
|
301
345
|
username=username,
|
|
302
|
-
src_path=
|
|
346
|
+
src_path=source_path,
|
|
303
347
|
dest_path=destination_path,
|
|
304
348
|
instance_path=instance_path,
|
|
305
349
|
container_path=container_path,
|
|
@@ -310,31 +354,67 @@ class ContainerService(AbstractService):
|
|
|
310
354
|
@error_handler()
|
|
311
355
|
def get_file_from_container(
|
|
312
356
|
self,
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
copy_only_folder_contents: bool,
|
|
316
|
-
destination_path: Optional[str] = None,
|
|
357
|
+
source: str,
|
|
358
|
+
destination_path: str,
|
|
317
359
|
username_param: Optional[str] = None,
|
|
318
360
|
):
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
361
|
+
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", source)
|
|
362
|
+
|
|
363
|
+
if container_args is None:
|
|
364
|
+
typer.echo(__('Container name and source directory path are required as the first argument'))
|
|
365
|
+
typer.echo(__('Example: container_name:/path/to/file'))
|
|
366
|
+
raise typer.Exit(1)
|
|
367
|
+
container_identifier = container_args.groups()[0]
|
|
368
|
+
source_path = container_args.groups()[1]
|
|
369
|
+
|
|
370
|
+
if not container_identifier:
|
|
371
|
+
typer.echo('Container identifier (container_id_or_name) is required')
|
|
372
|
+
raise typer.Exit(1)
|
|
373
|
+
|
|
374
|
+
resolved_options = self.__connect_api_client.resolve_user_input(entity_identifier=container_identifier)
|
|
375
|
+
container_public_id = None
|
|
376
|
+
valid_container_count = 0
|
|
377
|
+
for container_item in resolved_options.dockerContainerMatchData:
|
|
378
|
+
message = f"Found a container with matching {container_item.matchedField} in status: '{container_item.frontendStatus.status_translation}' (ID: {container_item.publicId})"
|
|
379
|
+
line_color = ColorScheme.SUCCESS.value if container_item.canDownloadUploadOnContainer else 'default'
|
|
380
|
+
print(f"[{line_color}]{message}[{line_color}]")
|
|
381
|
+
if container_item.canDownloadUploadOnContainer:
|
|
382
|
+
valid_container_count += 1
|
|
383
|
+
container_public_id = container_item.publicId
|
|
384
|
+
|
|
385
|
+
if valid_container_count != 1:
|
|
386
|
+
typer.echo(f"Failed to resolve the container by provided identifier, as total of {valid_container_count} containers are valid options")
|
|
387
|
+
raise typer.Exit(1)
|
|
388
|
+
|
|
389
|
+
container: Optional[DockerContainerDto] = self.__docker_container_api_client.get_container(
|
|
390
|
+
container_public_id=container_public_id,
|
|
323
391
|
)
|
|
324
392
|
|
|
393
|
+
if not container:
|
|
394
|
+
typer.echo(f"Unexpected error: container '{container_public_id}' not found")
|
|
395
|
+
raise typer.Exit(1)
|
|
396
|
+
|
|
325
397
|
if not container.mappings or not container.mappings.directory_mappings:
|
|
326
398
|
typer.echo(__("Mapping folders not found"))
|
|
327
399
|
raise typer.Exit(1)
|
|
328
400
|
|
|
329
401
|
instance_path, container_path = self._get_new_path_from_mapping(
|
|
330
402
|
directory_mapping=container.mappings.directory_mappings,
|
|
331
|
-
destination_path=
|
|
403
|
+
destination_path=source_path,
|
|
332
404
|
)
|
|
333
405
|
|
|
334
406
|
if not instance_path and not container_path:
|
|
335
407
|
typer.echo(__("Cannot find matching container volume mapping for specified file path"))
|
|
336
408
|
raise typer.Exit(1)
|
|
337
409
|
|
|
410
|
+
username, ip_address, private_key_path = self.get_server_auth(
|
|
411
|
+
container=container,
|
|
412
|
+
username_param=username_param,
|
|
413
|
+
private_key_path_override=None,
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
copy_only_folder_contents=source_path.endswith("/")
|
|
417
|
+
|
|
338
418
|
self.__remote_server_service.download_data_from_container(
|
|
339
419
|
ip_address=ip_address,
|
|
340
420
|
username=username,
|
|
@@ -366,11 +446,11 @@ class ContainerService(AbstractService):
|
|
|
366
446
|
if action in [DockerContainerAction.STOP, DockerContainerAction.RESTART]:
|
|
367
447
|
self.check_if_container_running(container=container)
|
|
368
448
|
|
|
369
|
-
request_params =
|
|
449
|
+
request_params = DockerContainerActionRequest(
|
|
370
450
|
dockerContainerPublicId=container.public_id,
|
|
371
451
|
action=action,
|
|
372
452
|
)
|
|
373
|
-
result = self.
|
|
453
|
+
result = self.__docker_container_api_client.container_action(
|
|
374
454
|
request_param=request_params,
|
|
375
455
|
)
|
|
376
456
|
|
|
@@ -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
|
|
|
File without changes
|
thestage/{controllers/container_controller.py → docker_container/communication/docker_command.py}
RENAMED
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
import re
|
|
3
1
|
from pathlib import Path
|
|
4
2
|
from typing import Optional, List
|
|
5
3
|
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
6
|
from thestage.cli_command import CliCommand
|
|
7
7
|
from thestage.cli_command_helper import get_command_metadata, check_command_permission
|
|
8
|
-
from thestage.services.clients.thestage_api.dtos.enums.container_pending_action import DockerContainerAction
|
|
9
|
-
from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
|
|
10
|
-
from thestage.i18n.translation import __
|
|
11
|
-
from thestage.services.container.container_service import ContainerService
|
|
12
|
-
from thestage.helpers.logger.app_logger import app_logger
|
|
13
8
|
from thestage.controllers.utils_controller import validate_config_and_get_service_factory, get_current_directory
|
|
14
|
-
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
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
|
|
18
15
|
|
|
19
16
|
app = typer.Typer(no_args_is_help=True, help=__("Manage containers"))
|
|
20
17
|
|
|
@@ -62,7 +59,7 @@ def list_containers(
|
|
|
62
59
|
check_command_permission(command_name)
|
|
63
60
|
|
|
64
61
|
if sum(v is not None for v in [project_public_id, project_slug]) > 1:
|
|
65
|
-
typer.echo("
|
|
62
|
+
typer.echo("Provide a single identifier for project - ID or name.")
|
|
66
63
|
raise typer.Exit(1)
|
|
67
64
|
|
|
68
65
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -101,7 +98,7 @@ def container_info(
|
|
|
101
98
|
check_command_permission(command_name)
|
|
102
99
|
|
|
103
100
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
104
|
-
typer.echo("
|
|
101
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
105
102
|
raise typer.Exit(1)
|
|
106
103
|
|
|
107
104
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -191,7 +188,7 @@ def container_connect(
|
|
|
191
188
|
check_command_permission(command_name)
|
|
192
189
|
|
|
193
190
|
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
194
|
-
typer.echo("
|
|
191
|
+
typer.echo("Provide a single identifier for container - ID or name.")
|
|
195
192
|
raise typer.Exit(1)
|
|
196
193
|
|
|
197
194
|
if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
|
|
@@ -215,7 +212,7 @@ def container_connect(
|
|
|
215
212
|
@app.command(name="upload", no_args_is_help=True, help=__("Upload file to container"), **get_command_metadata(CliCommand.CONTAINER_UPLOAD))
|
|
216
213
|
def upload_file(
|
|
217
214
|
source_path: str = typer.Argument(help=__("Source file path"),),
|
|
218
|
-
destination: Optional[str] = typer.Argument(help=__("Destination directory path in container. Format:
|
|
215
|
+
destination: Optional[str] = typer.Argument(help=__("Destination directory path in container. Format: container_id_or_name:/path/to/file"),),
|
|
219
216
|
username: Optional[str] = typer.Option(
|
|
220
217
|
None,
|
|
221
218
|
'--username',
|
|
@@ -228,50 +225,22 @@ def upload_file(
|
|
|
228
225
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
229
226
|
check_command_permission(command_name)
|
|
230
227
|
|
|
231
|
-
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", destination)
|
|
232
|
-
|
|
233
|
-
if container_args is None:
|
|
234
|
-
typer.echo(__('Container name and source file path are required as the second argument'))
|
|
235
|
-
typer.echo(__('Example: container_uid:/path/to/file'))
|
|
236
|
-
raise typer.Exit(1)
|
|
237
|
-
container_slug = container_args.groups()[0]
|
|
238
|
-
destination_path = container_args.groups()[1].rstrip("/")
|
|
239
|
-
|
|
240
|
-
if not container_slug:
|
|
241
|
-
typer.echo(__('Container name is required'))
|
|
242
|
-
raise typer.Exit(1)
|
|
243
|
-
|
|
244
228
|
service_factory = validate_config_and_get_service_factory()
|
|
245
229
|
container_service: ContainerService = service_factory.get_container_service()
|
|
246
230
|
|
|
247
|
-
|
|
248
|
-
|
|
231
|
+
container_service.put_file_to_container(
|
|
232
|
+
source_path=source_path,
|
|
233
|
+
destination=destination,
|
|
234
|
+
username_param=username,
|
|
249
235
|
)
|
|
250
236
|
|
|
251
|
-
|
|
252
|
-
container_service.check_if_container_running(
|
|
253
|
-
container=container
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
typer.echo(f"Uploading file(s) to container '{container_slug}'")
|
|
257
|
-
|
|
258
|
-
container_service.put_file_to_container(
|
|
259
|
-
container=container,
|
|
260
|
-
src_path=source_path,
|
|
261
|
-
destination_path=destination_path,
|
|
262
|
-
username_param=username,
|
|
263
|
-
copy_only_folder_contents=source_path.endswith("/")
|
|
264
|
-
)
|
|
265
|
-
else:
|
|
266
|
-
typer.echo(__("Container not found: %container_item%", {'container_item': container_slug}))
|
|
267
|
-
|
|
268
|
-
app_logger.info(f'End send files to container')
|
|
237
|
+
app_logger.info(f'File upload completed')
|
|
269
238
|
raise typer.Exit(0)
|
|
270
239
|
|
|
271
240
|
|
|
272
241
|
@app.command(name="download", no_args_is_help=True, help=__("Download file from container"), **get_command_metadata(CliCommand.CONTAINER_DOWNLOAD))
|
|
273
242
|
def download_file(
|
|
274
|
-
|
|
243
|
+
source: str = typer.Argument(help=__("Source file path in container. Format: container_name:/path/to/file"),),
|
|
275
244
|
destination_path: str = typer.Argument(help=__("Destination directory path on local machine"),),
|
|
276
245
|
username: Optional[str] = typer.Option(
|
|
277
246
|
None,
|
|
@@ -285,44 +254,16 @@ def download_file(
|
|
|
285
254
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
286
255
|
check_command_permission(command_name)
|
|
287
256
|
|
|
288
|
-
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", source_path)
|
|
289
|
-
|
|
290
|
-
if container_args is None:
|
|
291
|
-
typer.echo(__('Container name and source directory path are required as the first argument'))
|
|
292
|
-
typer.echo(__('Example: container-uid:/path/to/file'))
|
|
293
|
-
raise typer.Exit(1)
|
|
294
|
-
container_slug = container_args.groups()[0]
|
|
295
|
-
source_path = container_args.groups()[1]
|
|
296
|
-
|
|
297
|
-
if not container_slug:
|
|
298
|
-
typer.echo(__('Container name is required'))
|
|
299
|
-
raise typer.Exit(1)
|
|
300
|
-
|
|
301
257
|
service_factory = validate_config_and_get_service_factory()
|
|
302
258
|
container_service: ContainerService = service_factory.get_container_service()
|
|
303
259
|
|
|
304
|
-
|
|
305
|
-
|
|
260
|
+
container_service.get_file_from_container(
|
|
261
|
+
source=source,
|
|
262
|
+
destination_path=destination_path.rstrip("/"),
|
|
263
|
+
username_param=username,
|
|
306
264
|
)
|
|
307
265
|
|
|
308
|
-
|
|
309
|
-
container_service.check_if_container_running(
|
|
310
|
-
container=container
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
typer.echo(f"Downloading files from container: '{container_slug}'")
|
|
314
|
-
|
|
315
|
-
container_service.get_file_from_container(
|
|
316
|
-
container=container,
|
|
317
|
-
src_path=source_path,
|
|
318
|
-
destination_path=destination_path.rstrip("/"),
|
|
319
|
-
username_param=username,
|
|
320
|
-
copy_only_folder_contents=source_path.endswith("/"),
|
|
321
|
-
)
|
|
322
|
-
else:
|
|
323
|
-
typer.echo(f"Container not found: {container_slug}")
|
|
324
|
-
|
|
325
|
-
app_logger.info(f'End download files from container')
|
|
266
|
+
app_logger.info(f'File download completed')
|
|
326
267
|
raise typer.Exit(0)
|
|
327
268
|
|
|
328
269
|
|
|
@@ -360,7 +301,7 @@ def start_container(
|
|
|
360
301
|
action=DockerContainerAction.START
|
|
361
302
|
)
|
|
362
303
|
|
|
363
|
-
app_logger.info(f'
|
|
304
|
+
app_logger.info(f'Container start completed')
|
|
364
305
|
raise typer.Exit(0)
|
|
365
306
|
|
|
366
307
|
|
|
@@ -398,7 +339,7 @@ def stop_container(
|
|
|
398
339
|
action=DockerContainerAction.STOP
|
|
399
340
|
)
|
|
400
341
|
|
|
401
|
-
app_logger.info(f'
|
|
342
|
+
app_logger.info(f'Container stop completed')
|
|
402
343
|
raise typer.Exit(0)
|
|
403
344
|
|
|
404
345
|
|
|
@@ -436,7 +377,7 @@ def restart_container(
|
|
|
436
377
|
action=DockerContainerAction.RESTART
|
|
437
378
|
)
|
|
438
379
|
|
|
439
|
-
app_logger.info(f'
|
|
380
|
+
app_logger.info(f'Container restart completed')
|
|
440
381
|
raise typer.Exit(0)
|
|
441
382
|
|
|
442
383
|
|
|
@@ -483,5 +424,5 @@ def container_logs(
|
|
|
483
424
|
else:
|
|
484
425
|
logging_service.print_last_container_logs(container_public_id=container_public_id, container_slug=container_slug, logs_number=logs_number)
|
|
485
426
|
|
|
486
|
-
app_logger.info(f'Container
|
|
427
|
+
app_logger.info(f'Container log streaming completed')
|
|
487
428
|
raise typer.Exit(0)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from typing import Optional, List, Dict
|
|
2
|
+
|
|
3
|
+
from thestage.config.business.config_provider import ConfigProvider
|
|
4
|
+
from thestage.global_dto.enums.order_direction_type import OrderDirectionType
|
|
5
|
+
from thestage.services.clients.thestage_api.core.api_client_core import TheStageApiClientCore
|
|
6
|
+
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
|
|
7
|
+
from thestage.services.clients.thestage_api.dtos.entity_filter_request import EntityFilterRequest
|
|
8
|
+
from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
|
|
9
|
+
|
|
10
|
+
from thestage.docker_container.dto.container_action_request import DockerContainerActionRequest
|
|
11
|
+
from thestage.docker_container.dto.container_response import (
|
|
12
|
+
DockerContainerDto,
|
|
13
|
+
DockerContainerViewResponse,
|
|
14
|
+
ContainerBusinessStatusMapperResponse
|
|
15
|
+
)
|
|
16
|
+
from thestage.docker_container.dto.docker_container_list_request import DockerContainerListRequest
|
|
17
|
+
from thestage.docker_container.dto.docker_container_list_response import DockerContainerListResponse
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DockerContainerApiClient(TheStageApiClientCore):
|
|
21
|
+
def __init__(self, config_provider: ConfigProvider):
|
|
22
|
+
super().__init__(url=config_provider.get_config().main.thestage_api_url)
|
|
23
|
+
self.__config_provider = config_provider
|
|
24
|
+
|
|
25
|
+
def get_container_list(
|
|
26
|
+
self,
|
|
27
|
+
project_public_id: Optional[str] = None,
|
|
28
|
+
project_slug: Optional[str] = None,
|
|
29
|
+
statuses: List[str] = [],
|
|
30
|
+
page: int = 1,
|
|
31
|
+
limit: int = 10,
|
|
32
|
+
) -> PaginatedEntityList[DockerContainerDto]:
|
|
33
|
+
request = DockerContainerListRequest(
|
|
34
|
+
statuses=statuses,
|
|
35
|
+
projectPublicId=project_public_id,
|
|
36
|
+
projectSlug=project_slug,
|
|
37
|
+
entityFilterRequest=EntityFilterRequest(
|
|
38
|
+
orderByField="createdAt",
|
|
39
|
+
orderByDirection=OrderDirectionType.DESC,
|
|
40
|
+
page=page,
|
|
41
|
+
limit=limit,
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
response = self._request(
|
|
46
|
+
method='POST',
|
|
47
|
+
url='/user-api/v2/docker-container/list',
|
|
48
|
+
data=request.model_dump(),
|
|
49
|
+
token=self.__config_provider.get_config().main.thestage_auth_token
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
result = DockerContainerListResponse.model_validate(response) if response else None
|
|
53
|
+
# return result.paginatedList.entities, result.paginatedList.pagination_data.total_pages if result and result.is_success else None
|
|
54
|
+
return result.paginatedList if result and result.is_success else None
|
|
55
|
+
|
|
56
|
+
def get_container(
|
|
57
|
+
self,
|
|
58
|
+
container_slug: Optional[str] = None,
|
|
59
|
+
container_public_id: Optional[str] = None,
|
|
60
|
+
) -> Optional[DockerContainerDto]:
|
|
61
|
+
data = {
|
|
62
|
+
"dockerContainerPublicId": container_public_id,
|
|
63
|
+
"dockerContainerSlug": container_slug,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
response = self._request(
|
|
67
|
+
method='POST',
|
|
68
|
+
url='/user-api/v2/docker-container/view',
|
|
69
|
+
data=data,
|
|
70
|
+
token=self.__config_provider.get_config().main.thestage_auth_token,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return DockerContainerViewResponse.model_validate(response).docker_container if response else None
|
|
74
|
+
|
|
75
|
+
def container_action(
|
|
76
|
+
self,
|
|
77
|
+
request_param: DockerContainerActionRequest,
|
|
78
|
+
) -> TheStageBaseResponse:
|
|
79
|
+
|
|
80
|
+
response = self._request(
|
|
81
|
+
method='POST',
|
|
82
|
+
url='/user-api/v2/docker-container/action',
|
|
83
|
+
data=request_param.model_dump(by_alias=True),
|
|
84
|
+
token=self.__config_provider.get_config().main.thestage_auth_token,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
result = TheStageBaseResponse.model_validate(response) if response else None
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
def get_container_business_status_map(self) -> Optional[Dict[str, str]]:
|
|
91
|
+
response = self._request(
|
|
92
|
+
method='POST',
|
|
93
|
+
url='/user-api/v1/docker-container/status-localized-mapping',
|
|
94
|
+
data=None,
|
|
95
|
+
token=self.__config_provider.get_config().main.thestage_auth_token,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
data = ContainerBusinessStatusMapperResponse.model_validate(response) if response else None
|
|
99
|
+
return data.docker_container_status_map if data else None
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import Field, BaseModel, ConfigDict
|
|
4
|
+
|
|
5
|
+
from thestage.docker_container.dto.enum.container_pending_action import DockerContainerAction
|
|
6
|
+
|
|
7
|
+
class DockerContainerActionRequest(BaseModel):
|
|
8
|
+
model_config = ConfigDict(use_enum_values=True)
|
|
9
|
+
|
|
10
|
+
dockerContainerPublicId: Optional[str] = Field(None, alias='dockerContainerPublicId')
|
|
11
|
+
action: DockerContainerAction = Field(None, alias='action')
|
|
@@ -2,11 +2,11 @@ from typing import Optional, List, Dict
|
|
|
2
2
|
|
|
3
3
|
from pydantic import Field, BaseModel, ConfigDict
|
|
4
4
|
|
|
5
|
-
from thestage.
|
|
5
|
+
from thestage.docker_container.dto.docker_container_mapping import DockerContainerMappingDto
|
|
6
6
|
from thestage.services.clients.thestage_api.dtos.frontend_status import FrontendStatusDto
|
|
7
|
-
from thestage.
|
|
8
|
-
from thestage.
|
|
9
|
-
from thestage.
|
|
7
|
+
from thestage.instance.dto.instance_rented_response import InstanceRentedDto
|
|
8
|
+
from thestage.project.dto.project_response import ProjectDto
|
|
9
|
+
from thestage.instance.dto.selfhosted_instance_response import SelfHostedInstanceDto
|
|
10
10
|
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse, TheStageBasePaginatedResponse
|
|
11
11
|
from thestage.services.clients.thestage_api.dtos.pagination_data import PaginationData
|
|
12
12
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from pydantic import Field, ConfigDict, BaseModel
|
|
1
|
+
from pydantic import Field, ConfigDict
|
|
4
2
|
|
|
5
3
|
from thestage.services.clients.thestage_api.dtos.base_response import TheStageBaseResponse
|
|
6
|
-
from thestage.
|
|
4
|
+
from thestage.docker_container.dto.container_response import DockerContainerDto
|
|
7
5
|
from thestage.services.clients.thestage_api.dtos.paginated_entity_list import PaginatedEntityList
|
|
8
|
-
|
|
6
|
+
|
|
9
7
|
|
|
10
8
|
class DockerContainerListResponse(TheStageBaseResponse):
|
|
11
9
|
model_config = ConfigDict(use_enum_values=True)
|
|
File without changes
|
thestage/git/__init__.py
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|