lightning-sdk 0.2.21rc0__py3-none-any.whl → 0.2.22__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 +1 -1
- lightning_sdk/api/deployment_api.py +7 -2
- lightning_sdk/api/license_api.py +1 -1
- lightning_sdk/api/llm_api.py +67 -27
- lightning_sdk/api/pipeline_api.py +48 -9
- lightning_sdk/cli/configure.py +34 -27
- lightning_sdk/cli/connect.py +2 -2
- lightning_sdk/cli/download.py +38 -2
- lightning_sdk/deployment/deployment.py +17 -3
- lightning_sdk/lightning_cloud/openapi/__init__.py +1 -0
- lightning_sdk/lightning_cloud/openapi/api/cluster_service_api.py +1 -5
- lightning_sdk/lightning_cloud/openapi/api/lit_registry_service_api.py +113 -0
- lightning_sdk/lightning_cloud/openapi/api/schedules_service_api.py +5 -1
- lightning_sdk/lightning_cloud/openapi/configuration.py +1 -1
- lightning_sdk/lightning_cloud/openapi/models/__init__.py +1 -0
- lightning_sdk/lightning_cloud/openapi/models/project_id_pipelines_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/project_id_schedules_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/schedules_id_body.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_delete_lit_registry_repository_image_artifact_version_by_digest_response.py +97 -0
- lightning_sdk/lightning_cloud/openapi/models/v1_get_project_storage_metadata_response.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_get_user_response.py +79 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_get_user_storage_breakdown_response.py +53 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_schedule.py +27 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_update_user_request.py +79 -1
- lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +1 -105
- lightning_sdk/llm/__init__.py +1 -2
- lightning_sdk/llm/llm.py +52 -1
- lightning_sdk/pipeline/__init__.py +2 -1
- lightning_sdk/pipeline/pipeline.py +23 -6
- lightning_sdk/pipeline/printer.py +102 -0
- lightning_sdk/pipeline/schedule.py +7 -0
- lightning_sdk/pipeline/types.py +3 -3
- lightning_sdk/pipeline/utils.py +1 -16
- {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/METADATA +1 -1
- {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/RECORD +39 -37
- lightning_sdk/llm/asyncllm.py +0 -48
- {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/LICENSE +0 -0
- {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/WHEEL +0 -0
- {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/entry_points.txt +0 -0
- {lightning_sdk-0.2.21rc0.dist-info → lightning_sdk-0.2.22.dist-info}/top_level.txt +0 -0
lightning_sdk/__init__.py
CHANGED
|
@@ -282,10 +282,11 @@ class DeploymentApi:
|
|
|
282
282
|
|
|
283
283
|
requires_release = False
|
|
284
284
|
requires_release |= apply_change(deployment.spec, "image", image)
|
|
285
|
+
|
|
285
286
|
requires_release |= apply_change(deployment.spec, "entrypoint", entrypoint)
|
|
286
287
|
requires_release |= apply_change(deployment.spec, "command", command)
|
|
287
288
|
requires_release |= apply_change(deployment.spec, "env", to_env(env))
|
|
288
|
-
requires_release |= apply_change(deployment.spec, "readiness_probe", to_health_check(health_check))
|
|
289
|
+
requires_release |= apply_change(deployment.spec, "readiness_probe", to_health_check(health_check, False))
|
|
289
290
|
requires_release |= apply_change(deployment.spec, "cluster_id", cloud_account)
|
|
290
291
|
requires_release |= apply_change(deployment.spec, "spot", spot)
|
|
291
292
|
requires_release |= apply_change(deployment.spec, "quantity", quantity)
|
|
@@ -524,8 +525,12 @@ def to_endpoint(
|
|
|
524
525
|
|
|
525
526
|
|
|
526
527
|
def to_health_check(
|
|
527
|
-
health_check: Optional[Union[HttpHealthCheck, ExecHealthCheck]] = None
|
|
528
|
+
health_check: Optional[Union[HttpHealthCheck, ExecHealthCheck]] = None,
|
|
529
|
+
use_default: bool = True,
|
|
528
530
|
) -> Optional[V1JobHealthCheckConfig]:
|
|
531
|
+
if health_check is None and not use_default:
|
|
532
|
+
return None
|
|
533
|
+
|
|
529
534
|
# Use Default health check if none is provided
|
|
530
535
|
if not health_check:
|
|
531
536
|
return V1JobHealthCheckConfig(
|
lightning_sdk/api/license_api.py
CHANGED
|
@@ -11,7 +11,7 @@ LICENSE_SIGNING_URL = f"{env.LIGHTNING_CLOUD_URL}?settings=licenses"
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def generate_url_user_settings(redirect_to: str = LICENSE_SIGNING_URL) -> str:
|
|
14
|
-
params = urlencode({"redirectTo": redirect_to, "
|
|
14
|
+
params = urlencode({"redirectTo": redirect_to, "okbhrt": LICENSE_CODE})
|
|
15
15
|
return f"{env.LIGHTNING_CLOUD_URL}/sign-in?{params}"
|
|
16
16
|
|
|
17
17
|
|
lightning_sdk/api/llm_api.py
CHANGED
|
@@ -2,7 +2,9 @@ import asyncio
|
|
|
2
2
|
import base64
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
-
|
|
5
|
+
import threading
|
|
6
|
+
import warnings
|
|
7
|
+
from typing import Any, AsyncGenerator, Dict, Generator, List, Optional, Union
|
|
6
8
|
|
|
7
9
|
from pip._vendor.urllib3 import HTTPResponse
|
|
8
10
|
|
|
@@ -28,35 +30,40 @@ class LLMApi:
|
|
|
28
30
|
result = self._client.assistants_service_list_assistants(user_id=user_id)
|
|
29
31
|
return result.assistants
|
|
30
32
|
|
|
33
|
+
def _parse_stream_line(self, decoded_line: str) -> Optional[V1ConversationResponseChunk]:
|
|
34
|
+
try:
|
|
35
|
+
payload = json.loads(decoded_line)
|
|
36
|
+
result_data = payload.get("result", {})
|
|
37
|
+
|
|
38
|
+
choices = []
|
|
39
|
+
for choice in result_data.get("choices", []):
|
|
40
|
+
delta = choice.get("delta", {})
|
|
41
|
+
choices.append(
|
|
42
|
+
V1ResponseChoice(
|
|
43
|
+
delta=V1ResponseChoiceDelta(**delta),
|
|
44
|
+
finish_reason=choice.get("finishReason"),
|
|
45
|
+
index=choice.get("index"),
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return V1ConversationResponseChunk(
|
|
50
|
+
choices=choices,
|
|
51
|
+
conversation_id=result_data.get("conversationId"),
|
|
52
|
+
executable=result_data.get("executable"),
|
|
53
|
+
id=result_data.get("id"),
|
|
54
|
+
throughput=result_data.get("throughput"),
|
|
55
|
+
)
|
|
56
|
+
except json.JSONDecodeError:
|
|
57
|
+
warnings.warn("Error decoding JSON:", decoded_line)
|
|
58
|
+
return None
|
|
59
|
+
|
|
31
60
|
def _stream_chat_response(self, result: HTTPResponse) -> Generator[V1ConversationResponseChunk, None, None]:
|
|
32
61
|
for line in result.stream():
|
|
33
62
|
decoded_lines = line.decode("utf-8").strip()
|
|
34
63
|
for decoded_line in decoded_lines.splitlines():
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
choices = []
|
|
40
|
-
for choice in result_data.get("choices", []):
|
|
41
|
-
delta = choice.get("delta", {})
|
|
42
|
-
choices.append(
|
|
43
|
-
V1ResponseChoice(
|
|
44
|
-
delta=V1ResponseChoiceDelta(**delta),
|
|
45
|
-
finish_reason=choice.get("finishReason"),
|
|
46
|
-
index=choice.get("index"),
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
yield V1ConversationResponseChunk(
|
|
51
|
-
choices=choices,
|
|
52
|
-
conversation_id=result_data.get("conversationId"),
|
|
53
|
-
executable=result_data.get("executable"),
|
|
54
|
-
id=result_data.get("id"),
|
|
55
|
-
throughput=result_data.get("throughput"),
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
except json.JSONDecodeError:
|
|
59
|
-
print("Error decoding JSON:", decoded_line)
|
|
64
|
+
chunk = self._parse_stream_line(decoded_line)
|
|
65
|
+
if chunk:
|
|
66
|
+
yield chunk
|
|
60
67
|
|
|
61
68
|
def _encode_image_bytes_to_data_url(self, image: str) -> str:
|
|
62
69
|
with open(image, "rb") as image_file:
|
|
@@ -160,7 +167,40 @@ class LLMApi:
|
|
|
160
167
|
result = await asyncio.to_thread(thread.get)
|
|
161
168
|
return result.result
|
|
162
169
|
|
|
163
|
-
|
|
170
|
+
conversation_thread = await asyncio.to_thread(
|
|
171
|
+
self._client.assistants_service_start_conversation,
|
|
172
|
+
body,
|
|
173
|
+
assistant_id,
|
|
174
|
+
async_req=True,
|
|
175
|
+
_preload_content=False,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
return self.stream_response(conversation_thread)
|
|
179
|
+
|
|
180
|
+
async def stream_response(self, thread: Any) -> AsyncGenerator[V1ConversationResponseChunk, None]:
|
|
181
|
+
loop = asyncio.get_event_loop()
|
|
182
|
+
response = await asyncio.to_thread(thread.get)
|
|
183
|
+
|
|
184
|
+
queue = asyncio.Queue()
|
|
185
|
+
|
|
186
|
+
def enqueue() -> None:
|
|
187
|
+
try:
|
|
188
|
+
for line in response:
|
|
189
|
+
decoded_lines = line.decode("utf-8").strip()
|
|
190
|
+
for decoded_line in decoded_lines.splitlines():
|
|
191
|
+
chunk = self._parse_stream_line(decoded_line)
|
|
192
|
+
if chunk:
|
|
193
|
+
asyncio.run_coroutine_threadsafe(queue.put(chunk), loop)
|
|
194
|
+
finally:
|
|
195
|
+
asyncio.run_coroutine_threadsafe(queue.put(None), loop)
|
|
196
|
+
|
|
197
|
+
threading.Thread(target=enqueue, daemon=True).start()
|
|
198
|
+
|
|
199
|
+
while True:
|
|
200
|
+
item = await queue.get()
|
|
201
|
+
if item is None:
|
|
202
|
+
break
|
|
203
|
+
yield item
|
|
164
204
|
|
|
165
205
|
def list_conversations(self, assistant_id: str) -> List[str]:
|
|
166
206
|
result = self._client.assistants_service_list_conversations(assistant_id)
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
from typing import List
|
|
1
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
2
2
|
|
|
3
3
|
from lightning_sdk.lightning_cloud.openapi.models import (
|
|
4
4
|
ProjectIdPipelinesBody,
|
|
5
|
+
ProjectIdSchedulesBody,
|
|
5
6
|
V1DeletePipelineResponse,
|
|
6
7
|
V1Pipeline,
|
|
7
8
|
V1PipelineStep,
|
|
9
|
+
V1ScheduleResourceType,
|
|
8
10
|
V1SharedFilesystem,
|
|
9
11
|
)
|
|
10
12
|
from lightning_sdk.lightning_cloud.openapi.rest import ApiException
|
|
11
13
|
from lightning_sdk.lightning_cloud.rest_client import LightningClient
|
|
12
14
|
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from lightning_sdk.pipeline.schedule import Schedule
|
|
17
|
+
|
|
13
18
|
|
|
14
19
|
class PipelineApi:
|
|
15
20
|
"""Internal API client for Pipeline requests (mainly http requests)."""
|
|
@@ -17,13 +22,23 @@ class PipelineApi:
|
|
|
17
22
|
def __init__(self) -> None:
|
|
18
23
|
self._client = LightningClient(retry=False, max_tries=0)
|
|
19
24
|
|
|
20
|
-
def get_pipeline_by_id(self, project_id: str,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
def get_pipeline_by_id(self, project_id: str, pipeline_id_or_name: str) -> Optional[V1Pipeline]:
|
|
26
|
+
if pipeline_id_or_name.startswith("pip_"):
|
|
27
|
+
try:
|
|
28
|
+
return self._client.pipelines_service_get_pipeline(project_id=project_id, id=pipeline_id_or_name)
|
|
29
|
+
except ApiException as ex:
|
|
30
|
+
if "not found" in str(ex):
|
|
31
|
+
return None
|
|
32
|
+
raise ex
|
|
33
|
+
else:
|
|
34
|
+
try:
|
|
35
|
+
return self._client.pipelines_service_get_pipeline_by_name(
|
|
36
|
+
project_id=project_id, name=pipeline_id_or_name
|
|
37
|
+
)
|
|
38
|
+
except ApiException as ex:
|
|
39
|
+
if "not found" in str(ex):
|
|
40
|
+
return None
|
|
41
|
+
raise ex
|
|
27
42
|
|
|
28
43
|
def create_pipeline(
|
|
29
44
|
self,
|
|
@@ -31,6 +46,8 @@ class PipelineApi:
|
|
|
31
46
|
project_id: str,
|
|
32
47
|
steps: List["V1PipelineStep"],
|
|
33
48
|
shared_filesystem: bool,
|
|
49
|
+
schedules: List["Schedule"],
|
|
50
|
+
parent_pipeline_id: Optional[str],
|
|
34
51
|
) -> V1Pipeline:
|
|
35
52
|
body = ProjectIdPipelinesBody(
|
|
36
53
|
name=name,
|
|
@@ -38,8 +55,30 @@ class PipelineApi:
|
|
|
38
55
|
shared_filesystem=V1SharedFilesystem(
|
|
39
56
|
enabled=shared_filesystem,
|
|
40
57
|
),
|
|
58
|
+
parent_pipeline_id=parent_pipeline_id or "",
|
|
41
59
|
)
|
|
42
|
-
|
|
60
|
+
|
|
61
|
+
pipeline = self._client.pipelines_service_create_pipeline(body, project_id)
|
|
62
|
+
|
|
63
|
+
# Delete the previous schedules
|
|
64
|
+
if parent_pipeline_id is not None:
|
|
65
|
+
current_schedules = self._client.schedules_service_list_schedules(project_id).schedules
|
|
66
|
+
for schedule in current_schedules:
|
|
67
|
+
self._client.schedules_service_delete_schedule(project_id, schedule.id)
|
|
68
|
+
|
|
69
|
+
if len(schedules):
|
|
70
|
+
for schedule in schedules:
|
|
71
|
+
body = ProjectIdSchedulesBody(
|
|
72
|
+
cron_expression=schedule.cron_expression,
|
|
73
|
+
display_name=schedule.name,
|
|
74
|
+
resource_id=pipeline.id,
|
|
75
|
+
parent_resource_id=parent_pipeline_id or "",
|
|
76
|
+
resource_type=V1ScheduleResourceType.PIPELINE,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
self._client.schedules_service_create_schedule(body, project_id)
|
|
80
|
+
|
|
81
|
+
return pipeline
|
|
43
82
|
|
|
44
83
|
def stop(self, pipeline: V1Pipeline) -> V1Pipeline:
|
|
45
84
|
body = pipeline
|
lightning_sdk/cli/configure.py
CHANGED
|
@@ -17,33 +17,10 @@ def configure() -> None:
|
|
|
17
17
|
"""Configure access to resources on the Lightning AI platform."""
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
help=(
|
|
25
|
-
"The name of the studio to obtain SSH config. "
|
|
26
|
-
"If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
|
|
27
|
-
),
|
|
28
|
-
)
|
|
29
|
-
@click.option(
|
|
30
|
-
"--teamspace",
|
|
31
|
-
default=None,
|
|
32
|
-
help=(
|
|
33
|
-
"The teamspace the studio is part of. "
|
|
34
|
-
"Should be of format <OWNER>/<TEAMSPACE_NAME>. "
|
|
35
|
-
"If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
|
|
36
|
-
),
|
|
37
|
-
)
|
|
38
|
-
@click.option(
|
|
39
|
-
"--overwrite",
|
|
40
|
-
is_flag=True,
|
|
41
|
-
flag_value=True,
|
|
42
|
-
default=False,
|
|
43
|
-
help="Whether to overwrite the SSH key and config if they already exist.",
|
|
44
|
-
)
|
|
45
|
-
def ssh(name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False) -> None:
|
|
46
|
-
"""Get SSH config entry for a studio."""
|
|
20
|
+
def _configure_ssh_internal(
|
|
21
|
+
name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False
|
|
22
|
+
) -> None:
|
|
23
|
+
"""Internal function to configure SSH without Click decorators."""
|
|
47
24
|
auth = Auth()
|
|
48
25
|
auth.authenticate()
|
|
49
26
|
console = Console()
|
|
@@ -78,6 +55,36 @@ def ssh(name: Optional[str] = None, teamspace: Optional[str] = None, overwrite:
|
|
|
78
55
|
console.print(f"SSH config updated at {config_path}")
|
|
79
56
|
|
|
80
57
|
|
|
58
|
+
@configure.command(name="ssh")
|
|
59
|
+
@click.option(
|
|
60
|
+
"--name",
|
|
61
|
+
default=None,
|
|
62
|
+
help=(
|
|
63
|
+
"The name of the studio to obtain SSH config. "
|
|
64
|
+
"If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
@click.option(
|
|
68
|
+
"--teamspace",
|
|
69
|
+
default=None,
|
|
70
|
+
help=(
|
|
71
|
+
"The teamspace the studio is part of. "
|
|
72
|
+
"Should be of format <OWNER>/<TEAMSPACE_NAME>. "
|
|
73
|
+
"If not specified, tries to infer from the environment (e.g. when run from within a Studio.)"
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
@click.option(
|
|
77
|
+
"--overwrite",
|
|
78
|
+
is_flag=True,
|
|
79
|
+
flag_value=True,
|
|
80
|
+
default=False,
|
|
81
|
+
help="Whether to overwrite the SSH key and config if they already exist.",
|
|
82
|
+
)
|
|
83
|
+
def ssh(name: Optional[str] = None, teamspace: Optional[str] = None, overwrite: bool = False) -> None:
|
|
84
|
+
"""Get SSH config entry for a studio."""
|
|
85
|
+
_configure_ssh_internal(name=name, teamspace=teamspace, overwrite=overwrite)
|
|
86
|
+
|
|
87
|
+
|
|
81
88
|
def _download_file(url: str, local_path: Path, overwrite: bool = True, chmod: Optional[int] = None) -> None:
|
|
82
89
|
"""Download a file from a URL."""
|
|
83
90
|
import requests
|
lightning_sdk/cli/connect.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
|
4
4
|
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
|
-
from lightning_sdk.cli.configure import
|
|
7
|
+
from lightning_sdk.cli.configure import _configure_ssh_internal
|
|
8
8
|
from lightning_sdk.cli.studios_menu import _StudiosMenu
|
|
9
9
|
|
|
10
10
|
|
|
@@ -22,7 +22,7 @@ def connect() -> None:
|
|
|
22
22
|
)
|
|
23
23
|
def studio(name: Optional[str], teamspace: Optional[str]) -> None:
|
|
24
24
|
"""Connect to a studio via SSH."""
|
|
25
|
-
|
|
25
|
+
_configure_ssh_internal(name=name, teamspace=teamspace, overwrite=False)
|
|
26
26
|
|
|
27
27
|
menu = _StudiosMenu()
|
|
28
28
|
studio = menu._get_studio(name=name, teamspace=teamspace)
|
lightning_sdk/cli/download.py
CHANGED
|
@@ -241,8 +241,8 @@ def _resolve_studio(studio: Optional[str]) -> Studio:
|
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
@download.command(name="licenses")
|
|
244
|
-
def
|
|
245
|
-
"""Download licenses for all products/packages.
|
|
244
|
+
def download_licenses() -> None:
|
|
245
|
+
"""Download licenses for all user's products/packages.
|
|
246
246
|
|
|
247
247
|
Example:
|
|
248
248
|
lightning download licenses
|
|
@@ -261,3 +261,39 @@ def licenses() -> None:
|
|
|
261
261
|
with licenses_file.open("w") as fp:
|
|
262
262
|
json.dump(licenses_short, fp, indent=4)
|
|
263
263
|
Console().print(f"Licenses downloaded to {licenses_file}", style="green")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@download.command(name="license")
|
|
267
|
+
@click.argument("name")
|
|
268
|
+
def download_license(name: str) -> None:
|
|
269
|
+
"""Download license for specific products/packages.
|
|
270
|
+
|
|
271
|
+
Example:
|
|
272
|
+
lightning download license NAME
|
|
273
|
+
|
|
274
|
+
NAME: The name of the product/package to download the license for.
|
|
275
|
+
"""
|
|
276
|
+
user = _get_authed_user()
|
|
277
|
+
api = LicenseApi()
|
|
278
|
+
licenses = api.list_user_licenses(user.id)
|
|
279
|
+
licenses_short = {ll.product_name: ll.license_key for ll in licenses if ll.is_valid}
|
|
280
|
+
|
|
281
|
+
if name not in licenses_short:
|
|
282
|
+
Console().print(f"Missing valid license for {name}", style="red")
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
user_home = Path.home()
|
|
286
|
+
lit_dir = user_home / ".lightning"
|
|
287
|
+
lit_dir.mkdir(parents=True, exist_ok=True)
|
|
288
|
+
licenses_file = lit_dir / "licenses.json"
|
|
289
|
+
|
|
290
|
+
licenses_loaded = {}
|
|
291
|
+
if licenses_file.exists():
|
|
292
|
+
with licenses_file.open("r") as fp:
|
|
293
|
+
licenses_loaded = json.load(fp)
|
|
294
|
+
|
|
295
|
+
licenses_loaded[name] = licenses_short[name]
|
|
296
|
+
|
|
297
|
+
with licenses_file.open("w") as fp:
|
|
298
|
+
json.dump(licenses_loaded, fp, indent=4)
|
|
299
|
+
Console().print(f"Updated license for {name} in {licenses_file}", style="green")
|
|
@@ -276,8 +276,8 @@ class Deployment:
|
|
|
276
276
|
cloud_account=cloud_account,
|
|
277
277
|
machine=machine,
|
|
278
278
|
image=image,
|
|
279
|
-
entrypoint=entrypoint
|
|
280
|
-
command=command
|
|
279
|
+
entrypoint=entrypoint,
|
|
280
|
+
command=command,
|
|
281
281
|
ports=ports,
|
|
282
282
|
custom_domain=custom_domain,
|
|
283
283
|
auth=auth,
|
|
@@ -340,7 +340,7 @@ class Deployment:
|
|
|
340
340
|
return None
|
|
341
341
|
|
|
342
342
|
@property
|
|
343
|
-
def
|
|
343
|
+
def health_check(self) -> Optional[Union[HttpHealthCheck, ExecHealthCheck]]:
|
|
344
344
|
"""The health check to validate the replicas are ready to receive traffic."""
|
|
345
345
|
if self._deployment:
|
|
346
346
|
self._deployment = self._deployment_api.get_deployment_by_name(self._name, self._teamspace.id)
|
|
@@ -467,6 +467,20 @@ class Deployment:
|
|
|
467
467
|
return self._deployment.spec.image
|
|
468
468
|
return None
|
|
469
469
|
|
|
470
|
+
@property
|
|
471
|
+
def entrypoint(self) -> Optional[str]:
|
|
472
|
+
if self._deployment:
|
|
473
|
+
self._deployment = self._deployment_api.get_deployment_by_name(self._name, self._teamspace.id)
|
|
474
|
+
return self._deployment.spec.entrypoint
|
|
475
|
+
return None
|
|
476
|
+
|
|
477
|
+
@property
|
|
478
|
+
def command(self) -> Optional[str]:
|
|
479
|
+
if self._deployment:
|
|
480
|
+
self._deployment = self._deployment_api.get_deployment_by_name(self._name, self._teamspace.id)
|
|
481
|
+
return self._deployment.spec.command
|
|
482
|
+
return None
|
|
483
|
+
|
|
470
484
|
@property
|
|
471
485
|
def _session(self) -> Any:
|
|
472
486
|
if self._request_session is None:
|
|
@@ -420,6 +420,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lightningwork_respon
|
|
|
420
420
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_dataset_response import V1DeleteLitDatasetResponse
|
|
421
421
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_dataset_version_response import V1DeleteLitDatasetVersionResponse
|
|
422
422
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_page_response import V1DeleteLitPageResponse
|
|
423
|
+
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_registry_repository_image_artifact_version_by_digest_response import V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse
|
|
423
424
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_repository_response import V1DeleteLitRepositoryResponse
|
|
424
425
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_logger_artifact_response import V1DeleteLoggerArtifactResponse
|
|
425
426
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_managed_endpoint_response import V1DeleteManagedEndpointResponse
|
|
@@ -2726,7 +2726,6 @@ class ClusterServiceApi(object):
|
|
|
2726
2726
|
>>> result = thread.get()
|
|
2727
2727
|
|
|
2728
2728
|
:param async_req bool
|
|
2729
|
-
:param bool include_pricing:
|
|
2730
2729
|
:param str cloud_provider:
|
|
2731
2730
|
:param str project_id:
|
|
2732
2731
|
:return: V1ListDefaultClusterAcceleratorsResponse
|
|
@@ -2749,7 +2748,6 @@ class ClusterServiceApi(object):
|
|
|
2749
2748
|
>>> result = thread.get()
|
|
2750
2749
|
|
|
2751
2750
|
:param async_req bool
|
|
2752
|
-
:param bool include_pricing:
|
|
2753
2751
|
:param str cloud_provider:
|
|
2754
2752
|
:param str project_id:
|
|
2755
2753
|
:return: V1ListDefaultClusterAcceleratorsResponse
|
|
@@ -2757,7 +2755,7 @@ class ClusterServiceApi(object):
|
|
|
2757
2755
|
returns the request thread.
|
|
2758
2756
|
"""
|
|
2759
2757
|
|
|
2760
|
-
all_params = ['
|
|
2758
|
+
all_params = ['cloud_provider', 'project_id'] # noqa: E501
|
|
2761
2759
|
all_params.append('async_req')
|
|
2762
2760
|
all_params.append('_return_http_data_only')
|
|
2763
2761
|
all_params.append('_preload_content')
|
|
@@ -2778,8 +2776,6 @@ class ClusterServiceApi(object):
|
|
|
2778
2776
|
path_params = {}
|
|
2779
2777
|
|
|
2780
2778
|
query_params = []
|
|
2781
|
-
if 'include_pricing' in params:
|
|
2782
|
-
query_params.append(('includePricing', params['include_pricing'])) # noqa: E501
|
|
2783
2779
|
if 'cloud_provider' in params:
|
|
2784
2780
|
query_params.append(('cloudProvider', params['cloud_provider'])) # noqa: E501
|
|
2785
2781
|
if 'project_id' in params:
|
|
@@ -148,6 +148,119 @@ class LitRegistryServiceApi(object):
|
|
|
148
148
|
_request_timeout=params.get('_request_timeout'),
|
|
149
149
|
collection_formats=collection_formats)
|
|
150
150
|
|
|
151
|
+
def lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest(self, project_id: 'str', lit_repo_name: 'str', full_hash_digest: 'str', **kwargs) -> 'V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse': # noqa: E501
|
|
152
|
+
"""lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest # noqa: E501
|
|
153
|
+
|
|
154
|
+
This method makes a synchronous HTTP request by default. To make an
|
|
155
|
+
asynchronous HTTP request, please pass async_req=True
|
|
156
|
+
>>> thread = api.lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest(project_id, lit_repo_name, full_hash_digest, async_req=True)
|
|
157
|
+
>>> result = thread.get()
|
|
158
|
+
|
|
159
|
+
:param async_req bool
|
|
160
|
+
:param str project_id: (required)
|
|
161
|
+
:param str lit_repo_name: (required)
|
|
162
|
+
:param str full_hash_digest: (required)
|
|
163
|
+
:param str cluster_id:
|
|
164
|
+
:return: V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse
|
|
165
|
+
If the method is called asynchronously,
|
|
166
|
+
returns the request thread.
|
|
167
|
+
"""
|
|
168
|
+
kwargs['_return_http_data_only'] = True
|
|
169
|
+
if kwargs.get('async_req'):
|
|
170
|
+
return self.lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest_with_http_info(project_id, lit_repo_name, full_hash_digest, **kwargs) # noqa: E501
|
|
171
|
+
else:
|
|
172
|
+
(data) = self.lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest_with_http_info(project_id, lit_repo_name, full_hash_digest, **kwargs) # noqa: E501
|
|
173
|
+
return data
|
|
174
|
+
|
|
175
|
+
def lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest_with_http_info(self, project_id: 'str', lit_repo_name: 'str', full_hash_digest: 'str', **kwargs) -> 'V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse': # noqa: E501
|
|
176
|
+
"""lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest # noqa: E501
|
|
177
|
+
|
|
178
|
+
This method makes a synchronous HTTP request by default. To make an
|
|
179
|
+
asynchronous HTTP request, please pass async_req=True
|
|
180
|
+
>>> thread = api.lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest_with_http_info(project_id, lit_repo_name, full_hash_digest, async_req=True)
|
|
181
|
+
>>> result = thread.get()
|
|
182
|
+
|
|
183
|
+
:param async_req bool
|
|
184
|
+
:param str project_id: (required)
|
|
185
|
+
:param str lit_repo_name: (required)
|
|
186
|
+
:param str full_hash_digest: (required)
|
|
187
|
+
:param str cluster_id:
|
|
188
|
+
:return: V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse
|
|
189
|
+
If the method is called asynchronously,
|
|
190
|
+
returns the request thread.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
all_params = ['project_id', 'lit_repo_name', 'full_hash_digest', 'cluster_id'] # noqa: E501
|
|
194
|
+
all_params.append('async_req')
|
|
195
|
+
all_params.append('_return_http_data_only')
|
|
196
|
+
all_params.append('_preload_content')
|
|
197
|
+
all_params.append('_request_timeout')
|
|
198
|
+
|
|
199
|
+
params = locals()
|
|
200
|
+
for key, val in six.iteritems(params['kwargs']):
|
|
201
|
+
if key not in all_params:
|
|
202
|
+
raise TypeError(
|
|
203
|
+
"Got an unexpected keyword argument '%s'"
|
|
204
|
+
" to method lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest" % key
|
|
205
|
+
)
|
|
206
|
+
params[key] = val
|
|
207
|
+
del params['kwargs']
|
|
208
|
+
# verify the required parameter 'project_id' is set
|
|
209
|
+
if ('project_id' not in params or
|
|
210
|
+
params['project_id'] is None):
|
|
211
|
+
raise ValueError("Missing the required parameter `project_id` when calling `lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest`") # noqa: E501
|
|
212
|
+
# verify the required parameter 'lit_repo_name' is set
|
|
213
|
+
if ('lit_repo_name' not in params or
|
|
214
|
+
params['lit_repo_name'] is None):
|
|
215
|
+
raise ValueError("Missing the required parameter `lit_repo_name` when calling `lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest`") # noqa: E501
|
|
216
|
+
# verify the required parameter 'full_hash_digest' is set
|
|
217
|
+
if ('full_hash_digest' not in params or
|
|
218
|
+
params['full_hash_digest'] is None):
|
|
219
|
+
raise ValueError("Missing the required parameter `full_hash_digest` when calling `lit_registry_service_delete_lit_registry_repository_image_artifact_version_by_digest`") # noqa: E501
|
|
220
|
+
|
|
221
|
+
collection_formats = {}
|
|
222
|
+
|
|
223
|
+
path_params = {}
|
|
224
|
+
if 'project_id' in params:
|
|
225
|
+
path_params['projectId'] = params['project_id'] # noqa: E501
|
|
226
|
+
if 'lit_repo_name' in params:
|
|
227
|
+
path_params['litRepoName'] = params['lit_repo_name'] # noqa: E501
|
|
228
|
+
if 'full_hash_digest' in params:
|
|
229
|
+
path_params['fullHashDigest'] = params['full_hash_digest'] # noqa: E501
|
|
230
|
+
|
|
231
|
+
query_params = []
|
|
232
|
+
if 'cluster_id' in params:
|
|
233
|
+
query_params.append(('clusterId', params['cluster_id'])) # noqa: E501
|
|
234
|
+
|
|
235
|
+
header_params = {}
|
|
236
|
+
|
|
237
|
+
form_params = []
|
|
238
|
+
local_var_files = {}
|
|
239
|
+
|
|
240
|
+
body_params = None
|
|
241
|
+
# HTTP header `Accept`
|
|
242
|
+
header_params['Accept'] = self.api_client.select_header_accept(
|
|
243
|
+
['application/json']) # noqa: E501
|
|
244
|
+
|
|
245
|
+
# Authentication setting
|
|
246
|
+
auth_settings = [] # noqa: E501
|
|
247
|
+
|
|
248
|
+
return self.api_client.call_api(
|
|
249
|
+
'/v1/projects/{projectId}/lit-registry/{litRepoName}/artifacts/{fullHashDigest}', 'DELETE',
|
|
250
|
+
path_params,
|
|
251
|
+
query_params,
|
|
252
|
+
header_params,
|
|
253
|
+
body=body_params,
|
|
254
|
+
post_params=form_params,
|
|
255
|
+
files=local_var_files,
|
|
256
|
+
response_type='V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse', # noqa: E501
|
|
257
|
+
auth_settings=auth_settings,
|
|
258
|
+
async_req=params.get('async_req'),
|
|
259
|
+
_return_http_data_only=params.get('_return_http_data_only'),
|
|
260
|
+
_preload_content=params.get('_preload_content', True),
|
|
261
|
+
_request_timeout=params.get('_request_timeout'),
|
|
262
|
+
collection_formats=collection_formats)
|
|
263
|
+
|
|
151
264
|
def lit_registry_service_delete_lit_repository(self, project_id: 'str', lit_repo_name: 'str', **kwargs) -> 'V1DeleteLitRepositoryResponse': # noqa: E501
|
|
152
265
|
"""lit_registry_service_delete_lit_repository # noqa: E501
|
|
153
266
|
|
|
@@ -364,6 +364,7 @@ class SchedulesServiceApi(object):
|
|
|
364
364
|
:param str page_token:
|
|
365
365
|
:param int limit:
|
|
366
366
|
:param str state:
|
|
367
|
+
:param str parent_resource_id:
|
|
367
368
|
:return: V1ListSchedulesResponse
|
|
368
369
|
If the method is called asynchronously,
|
|
369
370
|
returns the request thread.
|
|
@@ -389,12 +390,13 @@ class SchedulesServiceApi(object):
|
|
|
389
390
|
:param str page_token:
|
|
390
391
|
:param int limit:
|
|
391
392
|
:param str state:
|
|
393
|
+
:param str parent_resource_id:
|
|
392
394
|
:return: V1ListSchedulesResponse
|
|
393
395
|
If the method is called asynchronously,
|
|
394
396
|
returns the request thread.
|
|
395
397
|
"""
|
|
396
398
|
|
|
397
|
-
all_params = ['project_id', 'resource_id', 'page_token', 'limit', 'state'] # noqa: E501
|
|
399
|
+
all_params = ['project_id', 'resource_id', 'page_token', 'limit', 'state', 'parent_resource_id'] # noqa: E501
|
|
398
400
|
all_params.append('async_req')
|
|
399
401
|
all_params.append('_return_http_data_only')
|
|
400
402
|
all_params.append('_preload_content')
|
|
@@ -429,6 +431,8 @@ class SchedulesServiceApi(object):
|
|
|
429
431
|
query_params.append(('limit', params['limit'])) # noqa: E501
|
|
430
432
|
if 'state' in params:
|
|
431
433
|
query_params.append(('state', params['state'])) # noqa: E501
|
|
434
|
+
if 'parent_resource_id' in params:
|
|
435
|
+
query_params.append(('parentResourceId', params['parent_resource_id'])) # noqa: E501
|
|
432
436
|
|
|
433
437
|
header_params = {}
|
|
434
438
|
|
|
@@ -70,7 +70,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
|
|
|
70
70
|
self.password = ""
|
|
71
71
|
# Logging Settings
|
|
72
72
|
self.logger = {}
|
|
73
|
-
self.logger["package_logger"] = logging.getLogger("lightning_cloud.openapi")
|
|
73
|
+
self.logger["package_logger"] = logging.getLogger("lightning_sdk.lightning_cloud.openapi")
|
|
74
74
|
self.logger["urllib3_logger"] = logging.getLogger("urllib3")
|
|
75
75
|
# Log format
|
|
76
76
|
self.logger_format = '%(asctime)s %(levelname)s %(message)s'
|
|
@@ -375,6 +375,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lightningwork_respon
|
|
|
375
375
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_dataset_response import V1DeleteLitDatasetResponse
|
|
376
376
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_dataset_version_response import V1DeleteLitDatasetVersionResponse
|
|
377
377
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_page_response import V1DeleteLitPageResponse
|
|
378
|
+
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_registry_repository_image_artifact_version_by_digest_response import V1DeleteLitRegistryRepositoryImageArtifactVersionByDigestResponse
|
|
378
379
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lit_repository_response import V1DeleteLitRepositoryResponse
|
|
379
380
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_logger_artifact_response import V1DeleteLoggerArtifactResponse
|
|
380
381
|
from lightning_sdk.lightning_cloud.openapi.models.v1_delete_managed_endpoint_response import V1DeleteManagedEndpointResponse
|