thestage 0.6.5__tar.gz → 0.6.7__tar.gz
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-0.6.5 → thestage-0.6.7}/PKG-INFO +4 -2
- {thestage-0.6.5 → thestage-0.6.7}/pyproject.toml +2 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/__init__.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/color_scheme/color_scheme.py +1 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/base_controller.py +4 -3
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/config_controller.py +16 -4
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/container_controller.py +151 -106
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/instance_controller.py +35 -9
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/project_controller.py +335 -89
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/container.py +5 -3
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/project_inference_simulator.py +2 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/project_inference_simulator_model.py +2 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/project_task.py +2 -3
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/rented_instance.py +2 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/self_hosted_instance.py +2 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/helpers/error_handler.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/main.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/git/git_client.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/api_client.py +142 -109
- thestage-0.6.7/thestage/services/clients/thestage_api/dtos/base_controller/connect_resolve_response.py +22 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/container_param_request.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/container_response.py +1 -21
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_request.py +2 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_request.py +5 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_instance_response.py +2 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_request.py +1 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_request.py +2 -1
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_request.py → thestage-0.6.7/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_request.py +3 -2
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_for_project_response.py → thestage-0.6.7/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_list_response.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_request.py +2 -1
- thestage-0.6.7/thestage/services/clients/thestage_api/dtos/instance_rented_response.py +38 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_request.py +3 -3
- thestage-0.6.7/thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_request.py +13 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_request.py +1 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_request.py +2 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_request.py +2 -4
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_run_task_response.py +3 -0
- thestage-0.6.7/thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py +16 -0
- thestage-0.6.7/thestage/services/clients/thestage_api/dtos/project_response.py +20 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/selfhosted_instance_response.py +2 -20
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_response.py +1 -1
- thestage-0.6.7/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_request.py +10 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_response.py +1 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_request.py +4 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/task_controller/task_view_response.py +0 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/config_provider/config_provider.py +2 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/connect/connect_service.py +77 -74
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/container/container_service.py +120 -41
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/container/mapper/container_mapper.py +2 -1
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/instance/instance_service.py +13 -20
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/instance/mapper/instance_mapper.py +1 -3
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/instance/mapper/selfhosted_mapper.py +3 -4
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/logging/logging_service.py +45 -48
- thestage-0.6.7/thestage/services/project/dto/inference_simulator_dto.py +14 -0
- thestage-0.6.7/thestage/services/project/dto/inference_simulator_model_dto.py +13 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/dto/project_config.py +2 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/mapper/project_inference_simulator_mapper.py +1 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/mapper/project_inference_simulator_model_mapper.py +2 -2
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/mapper/project_task_mapper.py +2 -3
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/project_service.py +174 -140
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/remote_server_service.py +1 -0
- thestage-0.6.7/thestage/services/task/dto/task_dto.py +20 -0
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/cloud_provider_region.py +0 -19
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/docker_container_assigned_device.py +0 -10
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/currency_type.py +0 -10
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/daemon_status.py +0 -9
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/disk_type.py +0 -7
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/drive_type.py +0 -7
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/instance_type.py +0 -7
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/location_region.py +0 -11
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/enums/power_status.py +0 -10
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/instance_rented_response.py +0 -71
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_request.py +0 -21
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/price_definition.py +0 -14
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_request.py +0 -14
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/project_response.py +0 -32
- thestage-0.6.5/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_request.py +0 -8
- thestage-0.6.5/thestage/services/project/dto/inference_simulator_dto.py +0 -23
- thestage-0.6.5/thestage/services/project/dto/inference_simulator_model_dto.py +0 -21
- thestage-0.6.5/thestage/services/task/dto/task_dto.py +0 -40
- {thestage-0.6.5 → thestage-0.6.7}/LICENSE.txt +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/README.md +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/.env +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/__main__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/cli_command.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/cli_command_helper.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/config/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/config/config_storage.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/config/env_base.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/controllers/utils_controller.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/debug_main.dist.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/enums/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/enums/order_direction_type.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/enums/shell_type.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/enums/tail_output_type.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/enums/yes_no_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/entities/file_item.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/auth_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/base_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/business_logic_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/config_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/file_system_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/git_access_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/exceptions/remote_server_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/git/ProgressPrinter.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/helpers/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/helpers/exception_hook.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/helpers/logger/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/helpers/logger/app_logger.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/helpers/ssh_util.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/i18n/en_GB/messages.po +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/i18n/translation.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/.env +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/abstract_mapper.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/abstract_service.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/app_config_service.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/git/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/core/api_client_core.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/core/http_client_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/base_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/docker_container_controller/docker_container_list_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/docker_container_mapping.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/entity_filter_request.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/container_pending_action.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/container_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/cpu_type.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/gpu_name.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/inference_model_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/inference_simulator_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/instance_rented_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/provider_name.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/selfhosted_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/task_execution_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/enums/task_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/frontend_status.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/deploy_inference_model_to_sagemaker_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/get_inference_simulator_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_controller/inference_simulator_model_list_for_project_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_simulator_model_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/inference_simulator_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/installed_service.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/instance_detected_gpus.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/logging_controller/docker_container_log_stream_request.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/logging_controller/log_polling_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/logging_controller/task_log_stream_request.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/logging_controller/user_logs_query_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/paginated_entity_list.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/pagination_data.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_get_deploy_ssh_key_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_push_inference_simulator_model_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/project_controller/project_start_inference_simulator_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/sftp_path_helper.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_key_to_user_request.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/add_ssh_public_key_to_instance_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/ssh_key_controller/is_user_has_public_ssh_key_request.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/task_controller/task_list_for_project_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/task_controller/task_status_localized_map_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/user_controller/user_profile.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/clients/thestage_api/dtos/validate_token_response.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/config_provider/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/connect/dto/remote_server_config.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/container/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/container/mapper/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/core_files/config_entity.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/filesystem_service.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/instance/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/instance/mapper/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/logging/byte_print_style.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/logging/dto/log_message.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/logging/dto/log_type.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/logging/exception/log_polling_exception.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/logging/logging_constants.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/project/mapper/__init__.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/service_factory.py +0 -0
- {thestage-0.6.5 → thestage-0.6.7}/thestage/services/validation_service.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: thestage
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary:
|
|
5
|
+
License-File: LICENSE.txt
|
|
5
6
|
Author: TheStage AI team
|
|
6
7
|
Author-email: hello@thestage.ai
|
|
7
8
|
Requires-Python: >=3.9,<=3.13
|
|
@@ -20,6 +21,7 @@ Requires-Dist: pydantic (>=2.4.2,<3.0.0)
|
|
|
20
21
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
21
22
|
Requires-Dist: python-gettext-translations (>=1.1.0,<2.0.0)
|
|
22
23
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
24
|
+
Requires-Dist: rich (>=14.2.0,<15.0.0)
|
|
23
25
|
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
|
24
26
|
Requires-Dist: typer[all] (>=0.15.2,<0.16.0)
|
|
25
27
|
Description-Content-Type: text/markdown
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "thestage"
|
|
3
3
|
|
|
4
|
-
version = "0.6.
|
|
4
|
+
version = "0.6.7"
|
|
5
5
|
|
|
6
6
|
description = ""
|
|
7
7
|
authors = ["TheStage AI team <hello@thestage.ai>"]
|
|
@@ -34,6 +34,7 @@ paramiko = "^3.5.1"
|
|
|
34
34
|
aioconsole = "^0.8.0"
|
|
35
35
|
httpx = "^0.27.2"
|
|
36
36
|
boto3 = "^1.35.80"
|
|
37
|
+
rich = "^14.2.0"
|
|
37
38
|
|
|
38
39
|
[tool.poetry.dev-dependencies]
|
|
39
40
|
pytest = "^7.4.3"
|
|
@@ -27,8 +27,9 @@ def version():
|
|
|
27
27
|
|
|
28
28
|
@app.command(name="connect", no_args_is_help=True, help=__("Connect to server instance or container or task"), **get_command_metadata(CliCommand.CONNECT))
|
|
29
29
|
def connect(
|
|
30
|
-
|
|
31
|
-
help=
|
|
30
|
+
entity_identifier: Optional[str] = typer.Argument(
|
|
31
|
+
help="Name or ID of server instance or container or task",
|
|
32
|
+
),
|
|
32
33
|
username: Optional[str] = typer.Option(
|
|
33
34
|
None,
|
|
34
35
|
'--username',
|
|
@@ -57,7 +58,7 @@ def connect(
|
|
|
57
58
|
connect_service: ConnectService = service_factory.get_connect_service()
|
|
58
59
|
|
|
59
60
|
connect_service.connect_to_entity(
|
|
60
|
-
|
|
61
|
+
input_entity_identifier=entity_identifier,
|
|
61
62
|
username=username,
|
|
62
63
|
private_key_path=private_ssh_key_path
|
|
63
64
|
)
|
|
@@ -85,13 +85,20 @@ def config_clear():
|
|
|
85
85
|
@app.command(name='upload-ssh-key', no_args_is_help=True, help=__("Send your public SSH key to the platform and / or rented server instance"), **get_command_metadata(CliCommand.CONFIG_UPLOAD_SSH_KEY))
|
|
86
86
|
def upload_ssh_key(
|
|
87
87
|
ssh_public_key: str = typer.Argument(
|
|
88
|
-
help=__("Path to your public SSH key file or your public SSH key contents"),
|
|
88
|
+
help=__("Path to your public SSH key file or your public SSH key contents. OpenSSH key format is required."),
|
|
89
|
+
),
|
|
90
|
+
instance_rented_public_id: str = typer.Option(
|
|
91
|
+
None,
|
|
92
|
+
"--instance-rented-id",
|
|
93
|
+
"-rid",
|
|
94
|
+
help=__("ID of your rented instance to add the key to (optional)"),
|
|
95
|
+
is_eager=False,
|
|
89
96
|
),
|
|
90
97
|
instance_rented_slug: str = typer.Option(
|
|
91
98
|
None,
|
|
92
|
-
"--instance-
|
|
93
|
-
"-
|
|
94
|
-
help=__("
|
|
99
|
+
"--instance-rented-name",
|
|
100
|
+
"-rn",
|
|
101
|
+
help=__("Name of your rented instance to add the key to (optional)"),
|
|
95
102
|
is_eager=False,
|
|
96
103
|
)
|
|
97
104
|
):
|
|
@@ -99,6 +106,10 @@ def upload_ssh_key(
|
|
|
99
106
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
100
107
|
check_command_permission(command_name)
|
|
101
108
|
|
|
109
|
+
if sum(v is not None for v in [instance_rented_public_id, instance_rented_slug]) > 1:
|
|
110
|
+
typer.echo("Please provide a single identifier for rented instance - ID or name.")
|
|
111
|
+
raise typer.Exit(1)
|
|
112
|
+
|
|
102
113
|
service_factory = ServiceFactory()
|
|
103
114
|
connect_service: ConnectService = service_factory.get_connect_service()
|
|
104
115
|
|
|
@@ -131,6 +142,7 @@ def upload_ssh_key(
|
|
|
131
142
|
|
|
132
143
|
connect_service.upload_ssh_key(
|
|
133
144
|
public_key_contents=ssh_key_contents,
|
|
145
|
+
instance_public_id=instance_rented_public_id,
|
|
134
146
|
instance_slug=instance_rented_slug,
|
|
135
147
|
)
|
|
136
148
|
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import re
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Optional, List
|
|
5
|
+
from rich import print
|
|
5
6
|
|
|
6
7
|
from thestage.cli_command import CliCommand
|
|
7
8
|
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
|
|
8
11
|
from thestage.services.clients.thestage_api.dtos.enums.container_pending_action import DockerContainerAction
|
|
9
12
|
from thestage.services.clients.thestage_api.dtos.container_response import DockerContainerDto
|
|
10
13
|
from thestage.i18n.translation import __
|
|
@@ -35,11 +38,18 @@ def list_containers(
|
|
|
35
38
|
help=__("Set starting page for displaying output"),
|
|
36
39
|
is_eager=False,
|
|
37
40
|
),
|
|
38
|
-
|
|
41
|
+
project_public_id: str = typer.Option(
|
|
39
42
|
None,
|
|
40
|
-
'--project-
|
|
41
|
-
'-
|
|
42
|
-
help=__("Filter containers by project
|
|
43
|
+
'--project-id',
|
|
44
|
+
'-pid',
|
|
45
|
+
help=__("Filter containers by project, using the project's ID"),
|
|
46
|
+
is_eager=False,
|
|
47
|
+
),
|
|
48
|
+
project_slug: str = typer.Option(
|
|
49
|
+
None,
|
|
50
|
+
'--project-name',
|
|
51
|
+
'-pn',
|
|
52
|
+
help=__("Filter containers by project, using the project's name"),
|
|
43
53
|
is_eager=False,
|
|
44
54
|
),
|
|
45
55
|
statuses: List[str] = typer.Option(
|
|
@@ -54,12 +64,17 @@ def list_containers(
|
|
|
54
64
|
app_logger.info(f'Running {command_name}')
|
|
55
65
|
check_command_permission(command_name)
|
|
56
66
|
|
|
67
|
+
if sum(v is not None for v in [project_public_id, project_slug]) > 1:
|
|
68
|
+
typer.echo("Please provide a single identifier for project - ID or name.")
|
|
69
|
+
raise typer.Exit(1)
|
|
70
|
+
|
|
57
71
|
service_factory = validate_config_and_get_service_factory()
|
|
58
72
|
container_service: ContainerService = service_factory.get_container_service()
|
|
59
73
|
container_service.print_container_list(
|
|
60
74
|
row=row,
|
|
61
75
|
page=page,
|
|
62
|
-
|
|
76
|
+
project_public_id=project_public_id,
|
|
77
|
+
project_slug=project_slug,
|
|
63
78
|
statuses=statuses,
|
|
64
79
|
)
|
|
65
80
|
|
|
@@ -69,45 +84,61 @@ def list_containers(
|
|
|
69
84
|
|
|
70
85
|
@app.command(name="info", no_args_is_help=True, help=__("Get container info"), **get_command_metadata(CliCommand.CONTAINER_INFO))
|
|
71
86
|
def container_info(
|
|
72
|
-
|
|
87
|
+
container_public_id: str = typer.Option(
|
|
88
|
+
None,
|
|
89
|
+
'--container-id',
|
|
90
|
+
'-cid',
|
|
91
|
+
help=__("Container ID"),
|
|
92
|
+
is_eager=False,
|
|
93
|
+
),
|
|
94
|
+
container_slug: str = typer.Option(
|
|
95
|
+
None,
|
|
96
|
+
'--container-name',
|
|
97
|
+
'-cn',
|
|
98
|
+
help=__("Container name"),
|
|
99
|
+
is_eager=False,
|
|
100
|
+
),
|
|
73
101
|
):
|
|
74
102
|
command_name = CliCommand.CONTAINER_INFO
|
|
75
103
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
76
104
|
check_command_permission(command_name)
|
|
77
105
|
|
|
78
|
-
if not
|
|
79
|
-
typer.echo(
|
|
106
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
107
|
+
typer.echo("Please provide a single identifier for container - ID or name.")
|
|
80
108
|
raise typer.Exit(1)
|
|
81
109
|
|
|
82
110
|
service_factory = validate_config_and_get_service_factory()
|
|
83
111
|
container_service: ContainerService = service_factory.get_container_service()
|
|
84
112
|
|
|
85
113
|
container: Optional[DockerContainerDto] = container_service.get_container(
|
|
86
|
-
|
|
114
|
+
container_public_id=container_public_id,
|
|
115
|
+
container_slug=container_slug,
|
|
87
116
|
)
|
|
88
117
|
|
|
89
118
|
if not container:
|
|
90
|
-
typer.echo(
|
|
119
|
+
typer.echo("Container not found")
|
|
91
120
|
raise typer.Exit(1)
|
|
92
121
|
|
|
93
122
|
typer.echo(__("STATUS: %status%", {'status': str(container.frontend_status.status_translation if container and container.frontend_status else 'UNKNOWN')}))
|
|
94
|
-
typer.echo(__("
|
|
95
|
-
typer.echo(__("
|
|
123
|
+
typer.echo(__("ID: %slug%", {'slug': str(container.public_id)}))
|
|
124
|
+
typer.echo(__("NAME: %title%", {'title': str(container.slug)}))
|
|
96
125
|
typer.echo(__("IMAGE: %image%", {'image': str(container.docker_image)}))
|
|
97
126
|
|
|
127
|
+
typer.echo(f"CONTAINER INSTANCE:")
|
|
128
|
+
|
|
98
129
|
if container.instance_rented:
|
|
130
|
+
typer.echo(f" TYPE: RENTED")
|
|
131
|
+
typer.echo(f" ID: {container.instance_rented.public_id}")
|
|
132
|
+
typer.echo(f" NAME: {container.instance_rented.slug}")
|
|
99
133
|
typer.echo(
|
|
100
|
-
__("RENTED
|
|
101
|
-
)
|
|
102
|
-
typer.echo(
|
|
103
|
-
__("RENTED SERVER INSTANCE STATUS: %instance_status%",
|
|
134
|
+
__("RENTED INSTANCE STATUS: %instance_status%",
|
|
104
135
|
{'instance_status': str(container.instance_rented.frontend_status.status_translation if container.instance_rented.frontend_status else 'UNKNOWN')})
|
|
105
136
|
)
|
|
106
137
|
|
|
107
138
|
if container.selfhosted_instance:
|
|
108
|
-
typer.echo(
|
|
109
|
-
|
|
110
|
-
)
|
|
139
|
+
typer.echo(f" TYPE: SELF-HOSTED")
|
|
140
|
+
typer.echo(f" ID: {container.selfhosted_instance.public_id}")
|
|
141
|
+
typer.echo(f" NAME: {container.selfhosted_instance.slug}")
|
|
111
142
|
typer.echo(
|
|
112
143
|
__("SELF-HOSTED INSTANCE STATUS: %instance_status%",
|
|
113
144
|
{'instance_status': str(container.selfhosted_instance.frontend_status.status_translation if container.selfhosted_instance.frontend_status else 'UNKNOWN')})
|
|
@@ -129,7 +160,20 @@ def container_info(
|
|
|
129
160
|
|
|
130
161
|
@app.command(name="connect", no_args_is_help=True, help=__("Connect to container"), **get_command_metadata(CliCommand.CONTAINER_CONNECT))
|
|
131
162
|
def container_connect(
|
|
132
|
-
|
|
163
|
+
container_public_id: str = typer.Option(
|
|
164
|
+
None,
|
|
165
|
+
'--container-id',
|
|
166
|
+
'-cid',
|
|
167
|
+
help=__("Container ID"),
|
|
168
|
+
is_eager=False,
|
|
169
|
+
),
|
|
170
|
+
container_slug: str = typer.Option(
|
|
171
|
+
None,
|
|
172
|
+
'--container-name',
|
|
173
|
+
'-cn',
|
|
174
|
+
help=__("Container name"),
|
|
175
|
+
is_eager=False,
|
|
176
|
+
),
|
|
133
177
|
username: Optional[str] = typer.Option(
|
|
134
178
|
None,
|
|
135
179
|
'--username',
|
|
@@ -149,8 +193,8 @@ def container_connect(
|
|
|
149
193
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
150
194
|
check_command_permission(command_name)
|
|
151
195
|
|
|
152
|
-
if not
|
|
153
|
-
typer.echo(
|
|
196
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
197
|
+
typer.echo("Please provide a single identifier for container - ID or name.")
|
|
154
198
|
raise typer.Exit(1)
|
|
155
199
|
|
|
156
200
|
if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
|
|
@@ -161,7 +205,8 @@ def container_connect(
|
|
|
161
205
|
container_service: ContainerService = service_factory.get_container_service()
|
|
162
206
|
|
|
163
207
|
container_service.connect_to_container(
|
|
164
|
-
|
|
208
|
+
container_public_id=container_public_id,
|
|
209
|
+
container_slug=container_slug,
|
|
165
210
|
username=username,
|
|
166
211
|
input_ssh_key_path=private_ssh_key_path,
|
|
167
212
|
)
|
|
@@ -173,7 +218,7 @@ def container_connect(
|
|
|
173
218
|
@app.command(name="upload", no_args_is_help=True, help=__("Upload file to container"), **get_command_metadata(CliCommand.CONTAINER_UPLOAD))
|
|
174
219
|
def upload_file(
|
|
175
220
|
source_path: str = typer.Argument(help=__("Source file path"),),
|
|
176
|
-
destination: Optional[str] = typer.Argument(help=__("Destination directory path in container. Format:
|
|
221
|
+
destination: Optional[str] = typer.Argument(help=__("Destination directory path in container. Format: container_id_or_name:/path/to/file"),),
|
|
177
222
|
username: Optional[str] = typer.Option(
|
|
178
223
|
None,
|
|
179
224
|
'--username',
|
|
@@ -186,50 +231,22 @@ def upload_file(
|
|
|
186
231
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
187
232
|
check_command_permission(command_name)
|
|
188
233
|
|
|
189
|
-
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", destination)
|
|
190
|
-
|
|
191
|
-
if container_args is None:
|
|
192
|
-
typer.echo(__('Container unique ID and source file path are required as the second argument'))
|
|
193
|
-
typer.echo(__('Example: container_uid:/path/to/file'))
|
|
194
|
-
raise typer.Exit(1)
|
|
195
|
-
container_slug = container_args.groups()[0]
|
|
196
|
-
destination_path = container_args.groups()[1].rstrip("/")
|
|
197
|
-
|
|
198
|
-
if not container_slug:
|
|
199
|
-
typer.echo(__('Container unique ID is required'))
|
|
200
|
-
raise typer.Exit(1)
|
|
201
|
-
|
|
202
234
|
service_factory = validate_config_and_get_service_factory()
|
|
203
235
|
container_service: ContainerService = service_factory.get_container_service()
|
|
204
236
|
|
|
205
|
-
|
|
206
|
-
|
|
237
|
+
container_service.put_file_to_container(
|
|
238
|
+
source_path=source_path,
|
|
239
|
+
destination=destination,
|
|
240
|
+
username_param=username,
|
|
207
241
|
)
|
|
208
242
|
|
|
209
|
-
if container:
|
|
210
|
-
container_service.check_if_container_running(
|
|
211
|
-
container=container
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
typer.echo(__("Uploading file(s) to container '%container-slug%'", {'container-slug': container_slug}))
|
|
215
|
-
|
|
216
|
-
container_service.put_file_to_container(
|
|
217
|
-
container=container,
|
|
218
|
-
src_path=source_path,
|
|
219
|
-
destination_path=destination_path,
|
|
220
|
-
username_param=username,
|
|
221
|
-
copy_only_folder_contents=source_path.endswith("/")
|
|
222
|
-
)
|
|
223
|
-
else:
|
|
224
|
-
typer.echo(__("Container not found: %container_item%", {'container_item': container_slug}))
|
|
225
|
-
|
|
226
243
|
app_logger.info(f'End send files to container')
|
|
227
244
|
raise typer.Exit(0)
|
|
228
245
|
|
|
229
246
|
|
|
230
247
|
@app.command(name="download", no_args_is_help=True, help=__("Download file from container"), **get_command_metadata(CliCommand.CONTAINER_DOWNLOAD))
|
|
231
248
|
def download_file(
|
|
232
|
-
|
|
249
|
+
source: str = typer.Argument(help=__("Source file path in container. Format: container_name:/path/to/file"),),
|
|
233
250
|
destination_path: str = typer.Argument(help=__("Destination directory path on local machine"),),
|
|
234
251
|
username: Optional[str] = typer.Option(
|
|
235
252
|
None,
|
|
@@ -243,64 +260,50 @@ def download_file(
|
|
|
243
260
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
244
261
|
check_command_permission(command_name)
|
|
245
262
|
|
|
246
|
-
container_args = re.match(r"^([\w\W]+?):([\w\W]+)$", source_path)
|
|
247
|
-
|
|
248
|
-
if container_args is None:
|
|
249
|
-
typer.echo(__('Container unique ID and source directory path are required as the first argument'))
|
|
250
|
-
typer.echo(__('Example: container-uid:/path/to/file'))
|
|
251
|
-
raise typer.Exit(1)
|
|
252
|
-
container_slug = container_args.groups()[0]
|
|
253
|
-
source_path = container_args.groups()[1]
|
|
254
|
-
|
|
255
|
-
if not container_slug:
|
|
256
|
-
typer.echo(__('Container unique ID is required'))
|
|
257
|
-
raise typer.Exit(1)
|
|
258
|
-
|
|
259
263
|
service_factory = validate_config_and_get_service_factory()
|
|
260
264
|
container_service: ContainerService = service_factory.get_container_service()
|
|
261
265
|
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
container_service.get_file_from_container(
|
|
267
|
+
source=source,
|
|
268
|
+
destination_path=destination_path.rstrip("/"),
|
|
269
|
+
username_param=username,
|
|
264
270
|
)
|
|
265
271
|
|
|
266
|
-
if container:
|
|
267
|
-
container_service.check_if_container_running(
|
|
268
|
-
container=container
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
typer.echo(__("Downloading files from container: '%container-slug%'", {'container-slug': container_slug}))
|
|
272
|
-
|
|
273
|
-
container_service.get_file_from_container(
|
|
274
|
-
container=container,
|
|
275
|
-
src_path=source_path,
|
|
276
|
-
destination_path=destination_path.rstrip("/"),
|
|
277
|
-
username_param=username,
|
|
278
|
-
copy_only_folder_contents=source_path.endswith("/"),
|
|
279
|
-
)
|
|
280
|
-
else:
|
|
281
|
-
typer.echo(__("Container not found: %container_item%", {'container_item': container_slug}))
|
|
282
|
-
|
|
283
272
|
app_logger.info(f'End download files from container')
|
|
284
273
|
raise typer.Exit(0)
|
|
285
274
|
|
|
286
275
|
|
|
287
276
|
@app.command(name="start", no_args_is_help=True, help=__("Start container"), **get_command_metadata(CliCommand.CONTAINER_START))
|
|
288
277
|
def start_container(
|
|
289
|
-
|
|
278
|
+
container_public_id: str = typer.Option(
|
|
279
|
+
None,
|
|
280
|
+
'--container-id',
|
|
281
|
+
'-cid',
|
|
282
|
+
help=__("Container ID"),
|
|
283
|
+
is_eager=False,
|
|
284
|
+
),
|
|
285
|
+
container_slug: str = typer.Option(
|
|
286
|
+
None,
|
|
287
|
+
'--container-name',
|
|
288
|
+
'-cn',
|
|
289
|
+
help=__("Container name"),
|
|
290
|
+
is_eager=False,
|
|
291
|
+
),
|
|
290
292
|
):
|
|
291
293
|
command_name = CliCommand.CONTAINER_START
|
|
292
294
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
293
295
|
check_command_permission(command_name)
|
|
294
296
|
|
|
295
|
-
if not
|
|
296
|
-
typer.echo(
|
|
297
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
298
|
+
typer.echo("Please provide a single identifier for container - ID or name.")
|
|
297
299
|
raise typer.Exit(1)
|
|
298
300
|
|
|
299
301
|
service_factory = validate_config_and_get_service_factory()
|
|
300
302
|
container_service: ContainerService = service_factory.get_container_service()
|
|
301
303
|
|
|
302
304
|
container_service.request_docker_container_action(
|
|
303
|
-
|
|
305
|
+
container_public_id=container_public_id,
|
|
306
|
+
container_slug=container_slug,
|
|
304
307
|
action=DockerContainerAction.START
|
|
305
308
|
)
|
|
306
309
|
|
|
@@ -310,21 +313,35 @@ def start_container(
|
|
|
310
313
|
|
|
311
314
|
@app.command(name="stop", no_args_is_help=True, help=__("Stop container"), **get_command_metadata(CliCommand.CONTAINER_STOP))
|
|
312
315
|
def stop_container(
|
|
313
|
-
|
|
316
|
+
container_public_id: str = typer.Option(
|
|
317
|
+
None,
|
|
318
|
+
'--container-id',
|
|
319
|
+
'-cid',
|
|
320
|
+
help=__("Container ID"),
|
|
321
|
+
is_eager=False,
|
|
322
|
+
),
|
|
323
|
+
container_slug: str = typer.Option(
|
|
324
|
+
None,
|
|
325
|
+
'--container-name',
|
|
326
|
+
'-cn',
|
|
327
|
+
help=__("Container name"),
|
|
328
|
+
is_eager=False,
|
|
329
|
+
),
|
|
314
330
|
):
|
|
315
331
|
command_name = CliCommand.CONTAINER_STOP
|
|
316
332
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
317
333
|
check_command_permission(command_name)
|
|
318
334
|
|
|
319
|
-
if not
|
|
320
|
-
typer.echo(
|
|
335
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
336
|
+
typer.echo("Please provide a single identifier for container - ID or name.")
|
|
321
337
|
raise typer.Exit(1)
|
|
322
338
|
|
|
323
339
|
service_factory = validate_config_and_get_service_factory()
|
|
324
340
|
container_service: ContainerService = service_factory.get_container_service()
|
|
325
341
|
|
|
326
342
|
container_service.request_docker_container_action(
|
|
327
|
-
|
|
343
|
+
container_public_id=container_public_id,
|
|
344
|
+
container_slug=container_slug,
|
|
328
345
|
action=DockerContainerAction.STOP
|
|
329
346
|
)
|
|
330
347
|
|
|
@@ -334,21 +351,35 @@ def stop_container(
|
|
|
334
351
|
|
|
335
352
|
@app.command(name="restart", no_args_is_help=True, help=__("Restart container"), **get_command_metadata(CliCommand.CONTAINER_RESTART))
|
|
336
353
|
def restart_container(
|
|
337
|
-
|
|
354
|
+
container_public_id: str = typer.Option(
|
|
355
|
+
None,
|
|
356
|
+
'--container-id',
|
|
357
|
+
'-cid',
|
|
358
|
+
help=__("Container ID"),
|
|
359
|
+
is_eager=False,
|
|
360
|
+
),
|
|
361
|
+
container_slug: str = typer.Option(
|
|
362
|
+
None,
|
|
363
|
+
'--container-name',
|
|
364
|
+
'-cn',
|
|
365
|
+
help=__("Container name"),
|
|
366
|
+
is_eager=False,
|
|
367
|
+
),
|
|
338
368
|
):
|
|
339
369
|
command_name = CliCommand.CONTAINER_RESTART
|
|
340
370
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
341
371
|
check_command_permission(command_name)
|
|
342
372
|
|
|
343
|
-
if not
|
|
344
|
-
typer.echo(
|
|
373
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
374
|
+
typer.echo("Please provide a single identifier for container - ID or name.")
|
|
345
375
|
raise typer.Exit(1)
|
|
346
376
|
|
|
347
377
|
service_factory = validate_config_and_get_service_factory()
|
|
348
378
|
container_service: ContainerService = service_factory.get_container_service()
|
|
349
379
|
|
|
350
380
|
container_service.request_docker_container_action(
|
|
351
|
-
|
|
381
|
+
container_public_id=container_public_id,
|
|
382
|
+
container_slug=container_slug,
|
|
352
383
|
action=DockerContainerAction.RESTART
|
|
353
384
|
)
|
|
354
385
|
|
|
@@ -358,7 +389,20 @@ def restart_container(
|
|
|
358
389
|
|
|
359
390
|
@app.command(name="logs", no_args_is_help=True, help=__("Stream real-time Docker container logs or view last logs for a container"), **get_command_metadata(CliCommand.CONTAINER_LOGS))
|
|
360
391
|
def container_logs(
|
|
361
|
-
|
|
392
|
+
container_public_id: str = typer.Option(
|
|
393
|
+
None,
|
|
394
|
+
'--container-id',
|
|
395
|
+
'-cid',
|
|
396
|
+
help=__("Container ID"),
|
|
397
|
+
is_eager=False,
|
|
398
|
+
),
|
|
399
|
+
container_slug: str = typer.Option(
|
|
400
|
+
None,
|
|
401
|
+
'--container-name',
|
|
402
|
+
'-cn',
|
|
403
|
+
help=__("Container name"),
|
|
404
|
+
is_eager=False,
|
|
405
|
+
),
|
|
362
406
|
logs_number: Optional[int] = typer.Option(
|
|
363
407
|
None,
|
|
364
408
|
'--number',
|
|
@@ -371,8 +415,8 @@ def container_logs(
|
|
|
371
415
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
372
416
|
check_command_permission(command_name)
|
|
373
417
|
|
|
374
|
-
if not
|
|
375
|
-
typer.echo(
|
|
418
|
+
if sum(v is not None for v in [container_public_id, container_slug]) != 1:
|
|
419
|
+
typer.echo("Please provide a single identifier for container - ID or name.")
|
|
376
420
|
raise typer.Exit(1)
|
|
377
421
|
|
|
378
422
|
service_factory = validate_config_and_get_service_factory()
|
|
@@ -380,10 +424,11 @@ def container_logs(
|
|
|
380
424
|
|
|
381
425
|
if logs_number is None:
|
|
382
426
|
logging_service.stream_container_logs_with_controls(
|
|
383
|
-
|
|
427
|
+
container_public_id=container_public_id,
|
|
428
|
+
container_slug=container_slug,
|
|
384
429
|
)
|
|
385
430
|
else:
|
|
386
|
-
logging_service.print_last_container_logs(
|
|
431
|
+
logging_service.print_last_container_logs(container_public_id=container_public_id, container_slug=container_slug, logs_number=logs_number)
|
|
387
432
|
|
|
388
433
|
app_logger.info(f'Container logs - end')
|
|
389
434
|
raise typer.Exit(0)
|
|
@@ -64,8 +64,19 @@ def rented_list(
|
|
|
64
64
|
|
|
65
65
|
@rented.command(name="connect", no_args_is_help=True, help=__("Connect to rented server instance"), **get_command_metadata(CliCommand.INSTANCE_RENTED_CONNECT))
|
|
66
66
|
def instance_connect(
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
public_id: Optional[str] = typer.Option(
|
|
68
|
+
None,
|
|
69
|
+
'--rented-instance-id',
|
|
70
|
+
'-rid',
|
|
71
|
+
help="Rented instance ID",
|
|
72
|
+
is_eager=False,
|
|
73
|
+
),
|
|
74
|
+
slug: Optional[str] = typer.Option(
|
|
75
|
+
None,
|
|
76
|
+
'--rented-instance-name',
|
|
77
|
+
'-rn',
|
|
78
|
+
help="Rented instance name",
|
|
79
|
+
is_eager=False,
|
|
69
80
|
),
|
|
70
81
|
private_ssh_key_path: str = typer.Option(
|
|
71
82
|
None,
|
|
@@ -79,8 +90,8 @@ def instance_connect(
|
|
|
79
90
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
80
91
|
check_command_permission(command_name)
|
|
81
92
|
|
|
82
|
-
if not
|
|
83
|
-
typer.echo(
|
|
93
|
+
if sum(v is not None for v in [public_id, slug]) != 1:
|
|
94
|
+
typer.echo("Please provide a single identifier for rented instance - ID or name.")
|
|
84
95
|
raise typer.Exit(1)
|
|
85
96
|
|
|
86
97
|
if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
|
|
@@ -91,7 +102,8 @@ def instance_connect(
|
|
|
91
102
|
instance_service: InstanceService = service_factory.get_instance_service()
|
|
92
103
|
|
|
93
104
|
instance_service.connect_to_rented_instance(
|
|
94
|
-
|
|
105
|
+
instance_rented_public_id=public_id,
|
|
106
|
+
instance_rented_slug=slug,
|
|
95
107
|
input_ssh_key_path=private_ssh_key_path
|
|
96
108
|
)
|
|
97
109
|
|
|
@@ -142,7 +154,20 @@ def self_hosted_list(
|
|
|
142
154
|
|
|
143
155
|
@self_hosted.command(name="connect", no_args_is_help=True, help=__("Connect to self-hosted instance"), **get_command_metadata(CliCommand.INSTANCE_SELF_HOSTED_CONNECT))
|
|
144
156
|
def self_hosted_connect(
|
|
145
|
-
|
|
157
|
+
public_id: Optional[str] = typer.Option(
|
|
158
|
+
None,
|
|
159
|
+
'--self-hosted-instance-id',
|
|
160
|
+
'-sid',
|
|
161
|
+
help="Self-hosted instance ID",
|
|
162
|
+
is_eager=False,
|
|
163
|
+
),
|
|
164
|
+
slug: Optional[str] = typer.Option(
|
|
165
|
+
None,
|
|
166
|
+
'--self-hosted-instance-name',
|
|
167
|
+
'-sn',
|
|
168
|
+
help="Self-hosted instance name",
|
|
169
|
+
is_eager=False,
|
|
170
|
+
),
|
|
146
171
|
username: Optional[str] = typer.Option(
|
|
147
172
|
None,
|
|
148
173
|
'--username',
|
|
@@ -162,8 +187,8 @@ def self_hosted_connect(
|
|
|
162
187
|
app_logger.info(f'Running {command_name} from {get_current_directory()}')
|
|
163
188
|
check_command_permission(command_name)
|
|
164
189
|
|
|
165
|
-
if not
|
|
166
|
-
typer.echo(
|
|
190
|
+
if sum(v is not None for v in [public_id, slug]) != 1:
|
|
191
|
+
typer.echo("Please provide a single identifier for self-hosted instance - ID or name.")
|
|
167
192
|
raise typer.Exit(1)
|
|
168
193
|
|
|
169
194
|
if private_ssh_key_path and not Path(private_ssh_key_path).is_file():
|
|
@@ -174,7 +199,8 @@ def self_hosted_connect(
|
|
|
174
199
|
instance_service: InstanceService = service_factory.get_instance_service()
|
|
175
200
|
|
|
176
201
|
instance_service.connect_to_selfhosted_instance(
|
|
177
|
-
|
|
202
|
+
selfhosted_instance_public_id=public_id,
|
|
203
|
+
selfhosted_instance_slug=slug,
|
|
178
204
|
username=username,
|
|
179
205
|
input_ssh_key_path=private_ssh_key_path
|
|
180
206
|
)
|