lightning-sdk 0.1.56__py3-none-any.whl → 0.1.57__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.
- lightning_sdk/__init__.py +3 -2
- lightning_sdk/cli/ai_hub.py +61 -10
- lightning_sdk/cli/configure.py +110 -65
- lightning_sdk/cli/connect.py +32 -16
- lightning_sdk/cli/delete.py +81 -32
- lightning_sdk/cli/download.py +177 -90
- lightning_sdk/cli/entrypoint.py +44 -16
- lightning_sdk/cli/generate.py +48 -16
- lightning_sdk/cli/inspect.py +43 -3
- lightning_sdk/cli/list.py +130 -41
- lightning_sdk/cli/run.py +0 -6
- lightning_sdk/cli/teamspace_menu.py +1 -1
- lightning_sdk/helpers.py +20 -0
- lightning_sdk/job/job.py +1 -1
- lightning_sdk/lightning_cloud/openapi/__init__.py +5 -0
- lightning_sdk/lightning_cloud/openapi/api/data_connection_service_api.py +105 -0
- lightning_sdk/lightning_cloud/openapi/api/jobs_service_api.py +113 -0
- lightning_sdk/lightning_cloud/openapi/api/lit_logger_service_api.py +4 -4
- lightning_sdk/lightning_cloud/openapi/models/__init__.py +5 -0
- lightning_sdk/lightning_cloud/openapi/models/agents_id_body.py +105 -1
- lightning_sdk/lightning_cloud/openapi/models/deployments_id_body.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/id_visibility_body1.py +149 -0
- lightning_sdk/lightning_cloud/openapi/models/model_id_visibility_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/setup.py +149 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_assistant.py +105 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_deployment.py +29 -3
- lightning_sdk/lightning_cloud/openapi/models/v1_gcp_data_connection_setup.py +123 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_job_spec.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_setup_data_connection_response.py +123 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_update_deployment_visibility_response.py +97 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_update_metrics_stream_visibility_response.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_update_model_visibility_response.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +79 -1
- {lightning_sdk-0.1.56.dist-info → lightning_sdk-0.1.57.dist-info}/METADATA +2 -1
- {lightning_sdk-0.1.56.dist-info → lightning_sdk-0.1.57.dist-info}/RECORD +39 -34
- {lightning_sdk-0.1.56.dist-info → lightning_sdk-0.1.57.dist-info}/LICENSE +0 -0
- {lightning_sdk-0.1.56.dist-info → lightning_sdk-0.1.57.dist-info}/WHEEL +0 -0
- {lightning_sdk-0.1.56.dist-info → lightning_sdk-0.1.57.dist-info}/entry_points.txt +0 -0
- {lightning_sdk-0.1.56.dist-info → lightning_sdk-0.1.57.dist-info}/top_level.txt +0 -0
lightning_sdk/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from lightning_sdk.agents import Agent
|
|
2
2
|
from lightning_sdk.ai_hub import AIHub
|
|
3
3
|
from lightning_sdk.constants import __GLOBAL_LIGHTNING_UNIQUE_IDS_STORE__ # noqa: F401
|
|
4
|
-
from lightning_sdk.helpers import _check_version_and_prompt_upgrade
|
|
4
|
+
from lightning_sdk.helpers import _check_version_and_prompt_upgrade, _set_tqdm_envvars_noninteractive
|
|
5
5
|
from lightning_sdk.job import Job
|
|
6
6
|
from lightning_sdk.machine import Machine
|
|
7
7
|
from lightning_sdk.mmt import MMT
|
|
@@ -29,5 +29,6 @@ __all__ = [
|
|
|
29
29
|
"AIHub",
|
|
30
30
|
]
|
|
31
31
|
|
|
32
|
-
__version__ = "0.1.
|
|
32
|
+
__version__ = "0.1.57"
|
|
33
33
|
_check_version_and_prompt_upgrade(__version__)
|
|
34
|
+
_set_tqdm_envvars_noninteractive()
|
lightning_sdk/cli/ai_hub.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import click
|
|
2
4
|
|
|
3
5
|
from lightning_sdk.ai_hub import AIHub
|
|
4
6
|
from lightning_sdk.cli.studios_menu import _StudiosMenu
|
|
@@ -7,10 +9,7 @@ from lightning_sdk.cli.studios_menu import _StudiosMenu
|
|
|
7
9
|
class _AIHub(_StudiosMenu):
|
|
8
10
|
"""Interact with Lightning Studio - AI Hub."""
|
|
9
11
|
|
|
10
|
-
def
|
|
11
|
-
self._hub = AIHub()
|
|
12
|
-
|
|
13
|
-
def api_info(self, api_id: str) -> dict:
|
|
12
|
+
def api_info(self, api_id: str) -> None:
|
|
14
13
|
"""Get full API template info such as input details.
|
|
15
14
|
|
|
16
15
|
Example:
|
|
@@ -19,15 +18,15 @@ class _AIHub(_StudiosMenu):
|
|
|
19
18
|
Args:
|
|
20
19
|
api_id: The ID of the API for which information is requested.
|
|
21
20
|
"""
|
|
22
|
-
return
|
|
21
|
+
return api_info(api_id=api_id)
|
|
23
22
|
|
|
24
|
-
def list_apis(self, search: Optional[str] = None) ->
|
|
23
|
+
def list_apis(self, search: Optional[str] = None) -> None:
|
|
25
24
|
"""List API templates available in the AI Hub.
|
|
26
25
|
|
|
27
26
|
Args:
|
|
28
27
|
search: Search for API templates by name.
|
|
29
28
|
"""
|
|
30
|
-
return
|
|
29
|
+
return list_apis(search=search)
|
|
31
30
|
|
|
32
31
|
def deploy(
|
|
33
32
|
self,
|
|
@@ -36,7 +35,7 @@ class _AIHub(_StudiosMenu):
|
|
|
36
35
|
name: Optional[str] = None,
|
|
37
36
|
teamspace: Optional[str] = None,
|
|
38
37
|
org: Optional[str] = None,
|
|
39
|
-
) ->
|
|
38
|
+
) -> None:
|
|
40
39
|
"""Deploy an API template from the AI Hub.
|
|
41
40
|
|
|
42
41
|
Args:
|
|
@@ -46,4 +45,56 @@ class _AIHub(_StudiosMenu):
|
|
|
46
45
|
teamspace: Teamspace to deploy the API to. Defaults to user's default teamspace.
|
|
47
46
|
org: Organization to deploy the API to. Defaults to user's default organization.
|
|
48
47
|
"""
|
|
49
|
-
return
|
|
48
|
+
return deploy(api_id=api_id, cloud_account=cloud_account, name=name, teamspace=teamspace, org=org)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@click.group(name="aihub")
|
|
52
|
+
def aihub() -> None:
|
|
53
|
+
"""Interact with Lightning Studio - AI Hub."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# @aihub.command(name="api-info")
|
|
57
|
+
# @click.argument("api-id")
|
|
58
|
+
def api_info(api_id: str) -> None:
|
|
59
|
+
"""Get full API template info such as input details.
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
lightning aihub api_info API-ID
|
|
63
|
+
|
|
64
|
+
API-ID: The ID of the API for which information is requested.
|
|
65
|
+
"""
|
|
66
|
+
ai_hub = AIHub()
|
|
67
|
+
ai_hub.api_info(api_id)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# @aihub.command(name="list-apis")
|
|
71
|
+
# @click.option("--search", default=None, help="Search for API templates by name.")
|
|
72
|
+
def list_apis(search: Optional[str]) -> None:
|
|
73
|
+
"""List API templates available in the AI Hub."""
|
|
74
|
+
ai_hub = AIHub()
|
|
75
|
+
ai_hub.list_apis(search=search)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# @aihub.command(name="deploy")
|
|
79
|
+
# @click.argument("api-id")
|
|
80
|
+
# @click.option(
|
|
81
|
+
# "--cloud-account",
|
|
82
|
+
# default=None,
|
|
83
|
+
# help="Cloud Account to deploy the API to. Defaults to user's default cloud account.",
|
|
84
|
+
# )
|
|
85
|
+
# @click.option("--name", default=None, help="Name of the deployed API. Defaults to the name of the API template.")
|
|
86
|
+
# @click.option(
|
|
87
|
+
# "--teamspace",
|
|
88
|
+
# default=None,
|
|
89
|
+
# help="Teamspace to deploy the API to. Defaults to user's default teamspace.",
|
|
90
|
+
# )
|
|
91
|
+
# @click.option(
|
|
92
|
+
# "--org",
|
|
93
|
+
# default=None,
|
|
94
|
+
# help="Organization to deploy the API to. Defaults to user's default organization.",
|
|
95
|
+
# )
|
|
96
|
+
def deploy(
|
|
97
|
+
api_id: str, cloud_account: Optional[str], name: Optional[str], teamspace: Optional[str], org: Optional[str]
|
|
98
|
+
) -> None:
|
|
99
|
+
ai_hub = AIHub()
|
|
100
|
+
ai_hub.run(api_id, cloud_account=cloud_account, name=name, teamspace=teamspace, org=org)
|
lightning_sdk/cli/configure.py
CHANGED
|
@@ -1,14 +1,98 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import platform
|
|
2
3
|
import uuid
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Optional, Union
|
|
5
6
|
|
|
7
|
+
import click
|
|
6
8
|
from rich.console import Console
|
|
7
9
|
|
|
8
|
-
from lightning_sdk.cli.generate import
|
|
10
|
+
from lightning_sdk.cli.generate import _generate_ssh_config
|
|
11
|
+
from lightning_sdk.cli.studios_menu import _StudiosMenu
|
|
9
12
|
from lightning_sdk.lightning_cloud.login import Auth
|
|
10
13
|
|
|
11
14
|
|
|
15
|
+
class _Configure(_StudiosMenu):
|
|
16
|
+
"""Configure lightning products."""
|
|
17
|
+
|
|
18
|
+
def ssh(self, name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False) -> None:
|
|
19
|
+
"""Get SSH config entry for a studio.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
name: The name of the studio to obtain SSH config.
|
|
23
|
+
If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
|
|
24
|
+
teamspace: The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.
|
|
25
|
+
If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
|
|
26
|
+
overwrite: Whether to overwrite the SSH key and config if they already exist.
|
|
27
|
+
"""
|
|
28
|
+
ssh(name=name, teamspace=teamspace, overwrite=overwrite)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@click.group(name="configure")
|
|
32
|
+
def configure() -> None:
|
|
33
|
+
"""Configure access to resources on the Lightning AI platform."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# @configure.command(name="ssh")
|
|
37
|
+
# @click.option(
|
|
38
|
+
# "--name",
|
|
39
|
+
# default=None,
|
|
40
|
+
# help=(
|
|
41
|
+
# "The name of the studio to obtain SSH config. "
|
|
42
|
+
# "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
|
|
43
|
+
# ),
|
|
44
|
+
# )
|
|
45
|
+
# @click.option(
|
|
46
|
+
# "--teamspace",
|
|
47
|
+
# default=None,
|
|
48
|
+
# help=(
|
|
49
|
+
# "The teamspace the studio is part of. "
|
|
50
|
+
# "Should be of format <OWNER>/<TEAMSPACE_NAME>. "
|
|
51
|
+
# "If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
|
|
52
|
+
# ),
|
|
53
|
+
# )
|
|
54
|
+
# @click.option(
|
|
55
|
+
# "--overwrite",
|
|
56
|
+
# is_flag=True,
|
|
57
|
+
# flag_value=True,
|
|
58
|
+
# help="Whether to overwrite the SSH key and config if they already exist.",
|
|
59
|
+
# )
|
|
60
|
+
def ssh(name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False) -> None:
|
|
61
|
+
"""Get SSH config entry for a studio."""
|
|
62
|
+
auth = Auth()
|
|
63
|
+
auth.authenticate()
|
|
64
|
+
console = Console()
|
|
65
|
+
ssh_dir = Path.home() / ".ssh"
|
|
66
|
+
ssh_dir.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
|
|
68
|
+
key_path = ssh_dir / "lightning_rsa"
|
|
69
|
+
config_path = ssh_dir / "config"
|
|
70
|
+
|
|
71
|
+
# Check if the SSH key already exists
|
|
72
|
+
if key_path.exists() and (key_path.with_suffix(".pub")).exists() and not overwrite:
|
|
73
|
+
console.print(f"SSH key already exists at {key_path}")
|
|
74
|
+
else:
|
|
75
|
+
_download_ssh_keys(auth.api_key, ssh_home=ssh_dir, ssh_key_name="lightning_rsa", overwrite=overwrite)
|
|
76
|
+
console.print(f"SSH key generated and saved to {key_path}")
|
|
77
|
+
|
|
78
|
+
# Check if the SSH config already contains the required configuration
|
|
79
|
+
menu = _StudiosMenu()
|
|
80
|
+
studio = menu._get_studio(name=name, teamspace=teamspace)
|
|
81
|
+
config_content = _generate_ssh_config(key_path=str(key_path), user=f"s_{studio._studio.id}", host=studio.name)
|
|
82
|
+
if config_path.exists():
|
|
83
|
+
with config_path.open("r") as config_file:
|
|
84
|
+
# check if the host already exists in the config
|
|
85
|
+
if f"Host {studio.name}" in config_file.read():
|
|
86
|
+
console.print("SSH config already contains the required configuration.")
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
with config_path.open("a") as config_file:
|
|
90
|
+
config_file.write(os.linesep)
|
|
91
|
+
config_file.write(config_content)
|
|
92
|
+
config_file.write(os.linesep)
|
|
93
|
+
console.print(f"SSH config updated at {config_path}")
|
|
94
|
+
|
|
95
|
+
|
|
12
96
|
def _download_file(url: str, local_path: Path, overwrite: bool = True, chmod: Optional[int] = None) -> None:
|
|
13
97
|
"""Download a file from a URL."""
|
|
14
98
|
import requests
|
|
@@ -26,67 +110,28 @@ def _download_file(url: str, local_path: Path, overwrite: bool = True, chmod: Op
|
|
|
26
110
|
local_path.chmod(0o600)
|
|
27
111
|
|
|
28
112
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
overwrite=overwrite,
|
|
55
|
-
chmod=0o600,
|
|
56
|
-
)
|
|
57
|
-
_download_file(f"https://lightning.ai/setup/ssh-public?t={api_key}&id={key_id}", path_pub, overwrite=overwrite)
|
|
58
|
-
|
|
59
|
-
def ssh(self, overwrite: bool = False, ssh_key_name: str = "lightning_rsa") -> None:
|
|
60
|
-
"""Get SSH config entry for a studio.
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
overwrite: Whether to overwrite the SSH key and config if they already exist.
|
|
64
|
-
ssh_key_name: The name of the SSH key to generate
|
|
65
|
-
"""
|
|
66
|
-
auth = Auth()
|
|
67
|
-
auth.authenticate()
|
|
68
|
-
console = Console()
|
|
69
|
-
ssh_dir = Path.home() / ".ssh"
|
|
70
|
-
ssh_dir.mkdir(parents=True, exist_ok=True)
|
|
71
|
-
|
|
72
|
-
key_path = ssh_dir / ssh_key_name
|
|
73
|
-
config_path = ssh_dir / "config"
|
|
74
|
-
|
|
75
|
-
# Check if the SSH key already exists
|
|
76
|
-
if key_path.exists() and (key_path.with_suffix(".pub")).exists() and not overwrite:
|
|
77
|
-
console.print(f"SSH key already exists at {key_path}")
|
|
78
|
-
else:
|
|
79
|
-
self._download_ssh_keys(auth.api_key, ssh_home=ssh_dir, ssh_key_name=ssh_key_name, overwrite=overwrite)
|
|
80
|
-
console.print(f"SSH key generated and saved to {key_path}")
|
|
81
|
-
|
|
82
|
-
# Check if the SSH config already contains the required configuration
|
|
83
|
-
config_content = self._generate_ssh_config(str(key_path))
|
|
84
|
-
if config_path.exists():
|
|
85
|
-
with config_path.open("r") as config_file:
|
|
86
|
-
if config_content.strip() in config_file.read():
|
|
87
|
-
console.print("SSH config already contains the required configuration.")
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
with config_path.open("a") as config_file:
|
|
91
|
-
config_file.write(config_content)
|
|
92
|
-
console.print(f"SSH config updated at {config_path}")
|
|
113
|
+
def _download_ssh_keys(
|
|
114
|
+
api_key: str,
|
|
115
|
+
key_id: str = "",
|
|
116
|
+
ssh_home: Union[str, Path] = "",
|
|
117
|
+
ssh_key_name: str = "lightning_rsa",
|
|
118
|
+
overwrite: bool = False,
|
|
119
|
+
) -> None:
|
|
120
|
+
if not ssh_home:
|
|
121
|
+
ssh_home = Path.home() / ".ssh"
|
|
122
|
+
elif isinstance(ssh_home, str):
|
|
123
|
+
ssh_home = Path(ssh_home)
|
|
124
|
+
if not key_id:
|
|
125
|
+
key_id = str(uuid.uuid4())
|
|
126
|
+
|
|
127
|
+
path_key = ssh_home / ssh_key_name
|
|
128
|
+
path_pub = ssh_home / f"{ssh_key_name}.pub"
|
|
129
|
+
|
|
130
|
+
# todo: consider hitting the API to get the key pair directly instead of using wget
|
|
131
|
+
_download_file(
|
|
132
|
+
f"https://lightning.ai/setup/ssh-gen?t={api_key}&id={key_id}&machineName={platform.node()}",
|
|
133
|
+
path_key,
|
|
134
|
+
overwrite=overwrite,
|
|
135
|
+
chmod=0o600,
|
|
136
|
+
)
|
|
137
|
+
_download_file(f"https://lightning.ai/setup/ssh-public?t={api_key}&id={key_id}", path_pub, overwrite=overwrite)
|
lightning_sdk/cli/connect.py
CHANGED
|
@@ -2,11 +2,13 @@ import subprocess
|
|
|
2
2
|
import sys
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
from lightning_sdk.lightning_cloud.login import Auth
|
|
5
|
+
import click
|
|
7
6
|
|
|
7
|
+
from lightning_sdk.cli.configure import ssh as configure_ssh
|
|
8
|
+
from lightning_sdk.cli.studios_menu import _StudiosMenu
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
|
|
11
|
+
class _Connect:
|
|
10
12
|
"""Connect to lightning products."""
|
|
11
13
|
|
|
12
14
|
def studio(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
@@ -16,16 +18,30 @@ class _Connect(_Configure):
|
|
|
16
18
|
name: The name of the studio to connect to.
|
|
17
19
|
teamspace: The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.
|
|
18
20
|
"""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
return studio(name=name, teamspace=teamspace)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.group(name="connect")
|
|
25
|
+
def connect() -> None:
|
|
26
|
+
"""Connect to lightning products."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# @connect.command(name="studio")
|
|
30
|
+
# @click.option("--name", default=None, help="The name of the studio to connect to.")
|
|
31
|
+
# @click.option(
|
|
32
|
+
# "--teamspace",
|
|
33
|
+
# default=None,
|
|
34
|
+
# help="The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.",
|
|
35
|
+
# )
|
|
36
|
+
def studio(name: Optional[str], teamspace: Optional[str]) -> None:
|
|
37
|
+
"""Connect to a studio via SSH."""
|
|
38
|
+
configure_ssh(name=name, teamspace=teamspace, overwrite=False)
|
|
39
|
+
|
|
40
|
+
menu = _StudiosMenu()
|
|
41
|
+
studio = menu._get_studio(name=name, teamspace=teamspace)
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
subprocess.run(["ssh", studio.name])
|
|
45
|
+
except Exception as ex:
|
|
46
|
+
print(f"Failed to establish SSH connection: {ex}")
|
|
47
|
+
sys.exit(1)
|
lightning_sdk/cli/delete.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
+
import click
|
|
3
4
|
from rich.console import Console
|
|
4
5
|
|
|
5
6
|
from lightning_sdk.cli.exceptions import StudioCliError
|
|
@@ -20,15 +21,7 @@ class _Delete(_JobAndMMTAction, _TeamspacesMenu):
|
|
|
20
21
|
teamspace: The teamspace to delete the container from. Should be specified as {owner}/{name}
|
|
21
22
|
If not provided, can be selected in an interactive menu.
|
|
22
23
|
"""
|
|
23
|
-
|
|
24
|
-
resolved_teamspace = self._resolve_teamspace(teamspace=teamspace)
|
|
25
|
-
try:
|
|
26
|
-
api.delete_container(container, resolved_teamspace.name, resolved_teamspace.owner.name)
|
|
27
|
-
Console().print(f"Container {container} deleted successfully.")
|
|
28
|
-
except Exception as e:
|
|
29
|
-
raise StudioCliError(
|
|
30
|
-
f"Could not delete container {container} from project {resolved_teamspace.name}: {e}"
|
|
31
|
-
) from None
|
|
24
|
+
delete_container(container=container, teamspace=teamspace)
|
|
32
25
|
|
|
33
26
|
def job(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
34
27
|
"""Delete a job.
|
|
@@ -40,10 +33,7 @@ class _Delete(_JobAndMMTAction, _TeamspacesMenu):
|
|
|
40
33
|
If not specified can be selected interactively.
|
|
41
34
|
|
|
42
35
|
"""
|
|
43
|
-
job
|
|
44
|
-
|
|
45
|
-
job.delete()
|
|
46
|
-
Console().print(f"Successfully deleted {job.name}!")
|
|
36
|
+
job(name=name, teamspace=teamspace)
|
|
47
37
|
|
|
48
38
|
def mmt(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
49
39
|
"""Delete a multi-machine job.
|
|
@@ -55,10 +45,7 @@ class _Delete(_JobAndMMTAction, _TeamspacesMenu):
|
|
|
55
45
|
If not specified can be selected interactively.
|
|
56
46
|
|
|
57
47
|
"""
|
|
58
|
-
mmt
|
|
59
|
-
|
|
60
|
-
mmt.delete()
|
|
61
|
-
Console().print(f"Successfully deleted {mmt.name}!")
|
|
48
|
+
mmt(name=name, teamspace=teamspace)
|
|
62
49
|
|
|
63
50
|
def studio(self, name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
64
51
|
"""Delete an existing studio.
|
|
@@ -70,18 +57,80 @@ class _Delete(_JobAndMMTAction, _TeamspacesMenu):
|
|
|
70
57
|
teamspace: The teamspace the studio is part of. Should be of format <OWNER>/<TEAMSPACE_NAME>.
|
|
71
58
|
If not specified, tries to infer from the environment (e.g. when run from within a Studio.)
|
|
72
59
|
"""
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
60
|
+
studio(name=name, teamspace=teamspace)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@click.group()
|
|
64
|
+
def delete() -> None:
|
|
65
|
+
"""Delete resources on the Lightning AI platform."""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# @delete.command(name="container")
|
|
69
|
+
# @click.option("--container", help="The name of the container to delete.")
|
|
70
|
+
# @click.option("--teamspace", default=None, help=("The teamspace to delete the container from. "
|
|
71
|
+
# "Should be specified as {owner}/{name} "
|
|
72
|
+
# "If not provided, can be selected in an interactive menu."),)
|
|
73
|
+
def delete_container(container: str, teamspace: Optional[str] = None) -> None:
|
|
74
|
+
"""Delete the docker container CONTAINER."""
|
|
75
|
+
api = LitContainer()
|
|
76
|
+
menu = _TeamspacesMenu()
|
|
77
|
+
resolved_teamspace = menu._resolve_teamspace(teamspace=teamspace)
|
|
78
|
+
try:
|
|
79
|
+
api.delete_container(container, resolved_teamspace.name, resolved_teamspace.owner.name)
|
|
80
|
+
Console().print(f"Container {container} deleted successfully.")
|
|
81
|
+
except Exception as e:
|
|
82
|
+
raise StudioCliError(
|
|
83
|
+
f"Could not delete container {container} from project {resolved_teamspace.name}: {e}"
|
|
84
|
+
) from None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# @delete.command(name="job")
|
|
88
|
+
# @click.option("--name", help="The name of the job to delete.")
|
|
89
|
+
# @click.option("--teamspace", default=None, help=("The teamspace to delete the job from. "
|
|
90
|
+
# "Should be specified as {owner}/{name} "
|
|
91
|
+
# "If not provided, can be selected in an interactive menu."),)
|
|
92
|
+
def job(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
93
|
+
"""Delete a job."""
|
|
94
|
+
menu = _JobAndMMTAction()
|
|
95
|
+
job = menu.job(name=name, teamspace=teamspace)
|
|
96
|
+
|
|
97
|
+
job.delete()
|
|
98
|
+
Console().print(f"Successfully deleted {job.name}!")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# @delete.command(name="mmt")
|
|
102
|
+
# @click.option("--name", help="The name of the multi-machine job to delete.")
|
|
103
|
+
# @click.option("--teamspace", default=None, help=("The teamspace to delete the job from. "
|
|
104
|
+
# "Should be specified as {owner}/{name} "
|
|
105
|
+
# "If not provided, can be selected in an interactive menu."),)
|
|
106
|
+
def mmt(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
107
|
+
"""Delete a multi-machine job."""
|
|
108
|
+
menu = _JobAndMMTAction()
|
|
109
|
+
mmt = menu.mmt(name=name, teamspace=teamspace)
|
|
110
|
+
|
|
111
|
+
mmt.delete()
|
|
112
|
+
Console().print(f"Successfully deleted {mmt.name}!")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# @delete.command(name="studio")
|
|
116
|
+
# @click.option("--name", help="The name of the studio to delete.")
|
|
117
|
+
# @click.option("--teamspace", default=None, help=("The teamspace to delete the studio from. "
|
|
118
|
+
# "Should be specified as {owner}/{name} "
|
|
119
|
+
# "If not provided, can be selected in an interactive menu."),)
|
|
120
|
+
def studio(name: Optional[str] = None, teamspace: Optional[str] = None) -> None:
|
|
121
|
+
"""Delete an existing studio."""
|
|
122
|
+
if teamspace is not None:
|
|
123
|
+
ts_splits = teamspace.split("/")
|
|
124
|
+
if len(ts_splits) != 2:
|
|
125
|
+
raise ValueError(f"Teamspace should be of format <OWNER>/<TEAMSPACE_NAME> but got {teamspace}")
|
|
126
|
+
owner, teamspace = ts_splits
|
|
127
|
+
else:
|
|
128
|
+
owner, teamspace = None, None
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
studio = Studio(name=name, teamspace=teamspace, org=owner, user=None, create_ok=False)
|
|
132
|
+
except (RuntimeError, ValueError):
|
|
133
|
+
studio = Studio(name=name, teamspace=teamspace, org=None, user=owner, create_ok=False)
|
|
134
|
+
|
|
135
|
+
studio.delete()
|
|
136
|
+
Console().print("Studio successfully deleted")
|