lightning-sdk 2025.8.18__py3-none-any.whl → 2025.8.19.post0__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.
Files changed (31) hide show
  1. lightning_sdk/__init__.py +1 -1
  2. lightning_sdk/api/cloud_account_api.py +5 -0
  3. lightning_sdk/api/studio_api.py +14 -36
  4. lightning_sdk/api/utils.py +108 -18
  5. lightning_sdk/cli/config/get.py +16 -0
  6. lightning_sdk/cli/config/set.py +27 -0
  7. lightning_sdk/cli/studio/create.py +16 -1
  8. lightning_sdk/cli/studio/start.py +20 -2
  9. lightning_sdk/lightning_cloud/openapi/__init__.py +1 -0
  10. lightning_sdk/lightning_cloud/openapi/api/k8_s_cluster_service_api.py +113 -0
  11. lightning_sdk/lightning_cloud/openapi/models/__init__.py +1 -0
  12. lightning_sdk/lightning_cloud/openapi/models/id_codeconfig_body.py +3 -81
  13. lightning_sdk/lightning_cloud/openapi/models/orgs_id_body.py +27 -1
  14. lightning_sdk/lightning_cloud/openapi/models/project_id_storage_body.py +27 -1
  15. lightning_sdk/lightning_cloud/openapi/models/storage_complete_body.py +27 -1
  16. lightning_sdk/lightning_cloud/openapi/models/uploads_upload_id_body1.py +27 -1
  17. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_metrics.py +79 -1
  18. lightning_sdk/lightning_cloud/openapi/models/v1_list_aggregated_pod_metrics_response.py +123 -0
  19. lightning_sdk/lightning_cloud/openapi/models/v1_node_metrics.py +79 -1
  20. lightning_sdk/lightning_cloud/openapi/models/v1_organization.py +27 -1
  21. lightning_sdk/lightning_cloud/openapi/models/v1_update_cloud_space_instance_config_request.py +3 -81
  22. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +1 -105
  23. lightning_sdk/studio.py +0 -1
  24. lightning_sdk/utils/config.py +3 -0
  25. lightning_sdk/utils/resolve.py +12 -0
  26. {lightning_sdk-2025.8.18.dist-info → lightning_sdk-2025.8.19.post0.dist-info}/METADATA +1 -1
  27. {lightning_sdk-2025.8.18.dist-info → lightning_sdk-2025.8.19.post0.dist-info}/RECORD +31 -30
  28. {lightning_sdk-2025.8.18.dist-info → lightning_sdk-2025.8.19.post0.dist-info}/LICENSE +0 -0
  29. {lightning_sdk-2025.8.18.dist-info → lightning_sdk-2025.8.19.post0.dist-info}/WHEEL +0 -0
  30. {lightning_sdk-2025.8.18.dist-info → lightning_sdk-2025.8.19.post0.dist-info}/entry_points.txt +0 -0
  31. {lightning_sdk-2025.8.18.dist-info → lightning_sdk-2025.8.19.post0.dist-info}/top_level.txt +0 -0
lightning_sdk/__init__.py CHANGED
@@ -32,6 +32,6 @@ __all__ = [
32
32
  "User",
33
33
  ]
34
34
 
35
- __version__ = "2025.08.18"
35
+ __version__ = "2025.08.19.post0"
36
36
  _check_version_and_prompt_upgrade(__version__)
37
37
  _set_tqdm_envvars_noninteractive()
@@ -181,6 +181,11 @@ class CloudAccountApi:
181
181
  cloud_provider: Optional[Union["CloudProvider", str]],
182
182
  default_cloud_account: Optional[str],
183
183
  ) -> Optional[str]:
184
+ from lightning_sdk.machine import CloudProvider
185
+
186
+ if cloud_provider and not isinstance(cloud_provider, CloudProvider):
187
+ cloud_provider = CloudProvider(cloud_provider)
188
+
184
189
  if cloud_account:
185
190
  if cloud_provider:
186
191
  cloud_account_resp = self.get_cloud_account_non_org(teamspace_id, cloud_account)
@@ -1,8 +1,7 @@
1
1
  import json
2
2
  import os
3
- import tempfile
4
3
  import time
5
- import zipfile
4
+ from pathlib import Path
6
5
  from threading import Event, Thread
7
6
  from typing import Any, Dict, Generator, List, Mapping, Optional, Tuple, Union
8
7
 
@@ -12,6 +11,7 @@ from tqdm import tqdm
12
11
 
13
12
  from lightning_sdk.api.utils import (
14
13
  _create_app,
14
+ _download_studio_files,
15
15
  _DummyBody,
16
16
  _DummyResponse,
17
17
  _FileUploader,
@@ -569,46 +569,24 @@ class StudioApi:
569
569
  progress_bar: bool = True,
570
570
  ) -> None:
571
571
  """Downloads a given folder from a Studio to a target location."""
572
- # TODO: Update this endpoint to permit basic auth
572
+ # TODO: implement resumable downloads
573
573
  auth = Auth()
574
574
  auth.authenticate()
575
- token = self._client.auth_service_login(V1LoginRequest(auth.api_key)).token
576
575
 
577
- query_params = {
578
- "clusterId": cloud_account,
579
- "prefix": _sanitize_studio_remote_path(path, studio_id),
580
- "token": token,
581
- }
576
+ prefix = _sanitize_studio_remote_path(path, studio_id)
577
+ # ensure we only download as a directory and not the entire prefix
578
+ if prefix.endswith("/") is False:
579
+ prefix = prefix + "/"
582
580
 
583
- r = requests.get(
584
- f"{self._client.api_client.configuration.host}/v1/projects/{teamspace_id}/artifacts/download",
585
- params=query_params,
586
- stream=True,
581
+ _download_studio_files(
582
+ client=self._client,
583
+ teamspace_id=teamspace_id,
584
+ cluster_id=cloud_account,
585
+ prefix=prefix,
586
+ download_dir=Path(target_path),
587
+ progress_bar=progress_bar,
587
588
  )
588
589
 
589
- if progress_bar:
590
- pbar = tqdm(
591
- desc=f"Downloading {os.path.split(path)[1]}",
592
- unit="B",
593
- unit_scale=True,
594
- unit_divisor=1000,
595
- )
596
-
597
- pbar_update = pbar.update
598
- else:
599
- pbar_update = lambda x: None
600
-
601
- if target_path:
602
- os.makedirs(target_path, exist_ok=True)
603
-
604
- with tempfile.TemporaryFile() as f:
605
- for chunk in r.iter_content(chunk_size=4096 * 8):
606
- f.write(chunk)
607
- pbar_update(len(chunk))
608
-
609
- with zipfile.ZipFile(f) as z:
610
- z.extractall(target_path)
611
-
612
590
  def install_plugin(self, studio_id: str, teamspace_id: str, plugin_name: str) -> str:
613
591
  """Installs the given plugin."""
614
592
  resp: V1Plugin = self._client.cloud_space_service_install_plugin(
@@ -6,7 +6,7 @@ import re
6
6
  from concurrent.futures import ThreadPoolExecutor
7
7
  from functools import partial
8
8
  from pathlib import Path
9
- from typing import Any, Dict, List, Optional, Tuple, Union
9
+ from typing import Any, Callable, Dict, List, Optional, Tuple, TypedDict, Union
10
10
 
11
11
  import backoff
12
12
  import requests
@@ -19,6 +19,7 @@ from lightning_sdk.lightning_cloud.openapi import (
19
19
  ModelsStoreApi,
20
20
  ProjectIdStorageBody,
21
21
  StorageCompleteBody,
22
+ StorageServiceApi,
22
23
  UploadIdCompleteBody,
23
24
  UploadIdPartsBody,
24
25
  V1CompletedPart,
@@ -367,38 +368,40 @@ _DOWNLOAD_REQUEST_CHUNK_SIZE = 10 * _BYTES_PER_MB
367
368
  _DOWNLOAD_MIN_CHUNK_SIZE = 100 * _BYTES_PER_KB
368
369
 
369
370
 
371
+ class _RefreshResponse(TypedDict):
372
+ url: str
373
+ size: int
374
+
375
+
370
376
  class _FileDownloader:
371
377
  def __init__(
372
378
  self,
373
- client: LightningClient,
374
- model_id: str,
375
- version: str,
376
379
  teamspace_id: str,
377
380
  remote_path: str,
378
381
  file_path: str,
379
382
  executor: ThreadPoolExecutor,
380
383
  num_workers: int = 20,
381
384
  progress_bar: Optional[tqdm] = None,
385
+ url: Optional[str] = None,
386
+ size: Optional[int] = None,
387
+ refresh_fn: Optional[Callable[[], _RefreshResponse]] = None,
382
388
  ) -> None:
383
- self.api = ModelsStoreApi(client.api_client)
384
- self.model_id = model_id
385
- self.version = version
386
389
  self.teamspace_id = teamspace_id
387
390
  self.local_path = file_path
388
391
  self.remote_path = remote_path
389
392
  self.progress_bar = progress_bar
390
393
  self.num_workers = num_workers
391
- self._url = ""
392
- self._size = 0
394
+ self._url = url
395
+ self._size = size
393
396
  self.executor = executor
397
+ self.refresh_fn = refresh_fn
394
398
 
395
399
  @backoff.on_exception(backoff.expo, ApiException, max_tries=10)
396
400
  def refresh(self) -> None:
397
- response = self.api.models_store_get_model_file_url(
398
- project_id=self.teamspace_id, model_id=self.model_id, version=self.version, filepath=self.remote_path
399
- )
400
- self._url = response.url
401
- self._size = int(response.size)
401
+ if self.refresh_fn is not None:
402
+ response = self.refresh_fn()
403
+ self._url = response["url"]
404
+ self._size = response["size"]
402
405
 
403
406
  @property
404
407
  def url(self) -> str:
@@ -413,6 +416,11 @@ class _FileDownloader:
413
416
  return
414
417
  self.progress_bar.update(n)
415
418
 
419
+ def update_filename(self, desc: str) -> None:
420
+ if self.progress_bar is None:
421
+ return
422
+ self.progress_bar.set_description(f"{(desc[:72] + '...') if len(desc) > 75 else desc:<75.75}")
423
+
416
424
  @backoff.on_exception(backoff.expo, (requests.exceptions.HTTPError), max_tries=10)
417
425
  def _download_chunk(self, filename: str, start_end: Tuple[int]) -> None:
418
426
  start, end = start_end
@@ -447,6 +455,8 @@ class _FileDownloader:
447
455
  f.write(b"\x00" * remaining_size)
448
456
 
449
457
  def _multipart_download(self, filename: str, num_workers: int) -> None:
458
+ self.update_filename(f"Downloading {self.remote_path}")
459
+
450
460
  num_chunks = num_workers
451
461
  chunk_size = math.ceil(self.size / num_chunks)
452
462
 
@@ -464,7 +474,8 @@ class _FileDownloader:
464
474
  concurrent.futures.wait(futures)
465
475
 
466
476
  def download(self) -> None:
467
- self.refresh()
477
+ if self.url is None:
478
+ self.refresh()
468
479
 
469
480
  tmp_filename = f"{self.local_path}.download"
470
481
 
@@ -539,6 +550,15 @@ def _download_model_files(
539
550
  mininterval=1,
540
551
  )
541
552
 
553
+ def refresh_fn(filename: str) -> _RefreshResponse:
554
+ resp = api.models_store_get_model_file_url(
555
+ project_id=response.project_id,
556
+ model_id=response.model_id,
557
+ version=response.version,
558
+ filepath=filename,
559
+ )
560
+ return {"url": resp.url, "size": int(resp.size)}
561
+
542
562
  with ThreadPoolExecutor(max_workers=min(num_workers, len(response.filepaths))) as file_executor, ThreadPoolExecutor(
543
563
  max_workers=num_workers
544
564
  ) as part_executor:
@@ -549,15 +569,13 @@ def _download_model_files(
549
569
  local_file.parent.mkdir(parents=True, exist_ok=True)
550
570
 
551
571
  file_downloader = _FileDownloader(
552
- client=client,
553
- model_id=response.model_id,
554
- version=response.version,
555
572
  teamspace_id=response.project_id,
556
573
  remote_path=filepath,
557
574
  file_path=str(local_file),
558
575
  num_workers=num_workers,
559
576
  progress_bar=pbar,
560
577
  executor=part_executor,
578
+ refresh_fn=lambda f=filepath: refresh_fn(f),
561
579
  )
562
580
 
563
581
  futures.append(file_executor.submit(file_downloader.download))
@@ -568,6 +586,78 @@ def _download_model_files(
568
586
  return response.filepaths
569
587
 
570
588
 
589
+ def _download_studio_files(
590
+ client: LightningClient,
591
+ teamspace_id: str,
592
+ cluster_id: str,
593
+ prefix: str,
594
+ download_dir: Path,
595
+ progress_bar: bool,
596
+ num_workers: int = os.cpu_count() * 4,
597
+ ) -> None:
598
+ api = StorageServiceApi(client.api_client)
599
+ response = None
600
+
601
+ pbar = None
602
+ if progress_bar:
603
+ pbar = tqdm(
604
+ desc="Downloading files",
605
+ unit="B",
606
+ unit_scale=True,
607
+ unit_divisor=1000,
608
+ position=-1,
609
+ mininterval=1,
610
+ )
611
+
612
+ def refresh_fn(filename: str) -> _RefreshResponse:
613
+ resp = api.storage_service_list_project_artifacts(
614
+ project_id=teamspace_id,
615
+ cluster_id=cluster_id,
616
+ page_token="",
617
+ include_download_url=True,
618
+ prefix=prefix + filename,
619
+ page_size=1,
620
+ )
621
+ return {"url": resp.artifacts[0].url, "size": int(resp.artifacts[0].size_bytes)}
622
+
623
+ with ThreadPoolExecutor(max_workers=num_workers) as file_executor, ThreadPoolExecutor(
624
+ max_workers=num_workers
625
+ ) as part_executor:
626
+ while response is None or (response is not None and response.next_page_token != ""):
627
+ response = api.storage_service_list_project_artifacts(
628
+ project_id=teamspace_id,
629
+ cluster_id=cluster_id,
630
+ page_token=response.next_page_token if response is not None else "",
631
+ include_download_url=True,
632
+ prefix=prefix,
633
+ page_size=1000,
634
+ )
635
+
636
+ page_futures = []
637
+ for file in response.artifacts:
638
+ local_file = download_dir / file.filename
639
+ local_file.parent.mkdir(parents=True, exist_ok=True)
640
+
641
+ file_downloader = _FileDownloader(
642
+ teamspace_id=teamspace_id,
643
+ remote_path=file.filename,
644
+ file_path=str(local_file),
645
+ num_workers=num_workers,
646
+ progress_bar=pbar,
647
+ executor=part_executor,
648
+ url=file.url,
649
+ size=int(file.size_bytes),
650
+ refresh_fn=lambda f=file: refresh_fn(f.filename),
651
+ )
652
+
653
+ page_futures.append(file_executor.submit(file_downloader.download))
654
+
655
+ if page_futures:
656
+ concurrent.futures.wait(page_futures)
657
+
658
+ pbar.set_description("Download complete")
659
+
660
+
571
661
  def _create_app(
572
662
  client: CloudSpaceServiceApi,
573
663
  studio_id: str,
@@ -39,3 +39,19 @@ def get_studio() -> None:
39
39
  config = Config()
40
40
  studio = config.get_value(DefaultConfigKeys.studio)
41
41
  click.echo(studio)
42
+
43
+
44
+ @get.command("cloud-account")
45
+ def get_cloud_account() -> None:
46
+ """Get the default cloud account name from the config."""
47
+ config = Config()
48
+ cloud_account = config.get_value(DefaultConfigKeys.cloud_account)
49
+ click.echo(cloud_account)
50
+
51
+
52
+ @get.command("cloud-provider")
53
+ def get_cloud_provider() -> None:
54
+ """Get the default cloud provider name from the config."""
55
+ config = Config()
56
+ cloud_provider = config.get_value(DefaultConfigKeys.cloud_provider)
57
+ click.echo(cloud_provider)
@@ -1,6 +1,7 @@
1
1
  import click
2
2
 
3
3
  from lightning_sdk.cli.utils.resolve import resolve_teamspace_owner_name_format
4
+ from lightning_sdk.machine import CloudProvider
4
5
  from lightning_sdk.organization import Organization
5
6
  from lightning_sdk.studio import Studio
6
7
  from lightning_sdk.utils.config import Config, DefaultConfigKeys
@@ -75,3 +76,29 @@ def set_teamspace(teamspace_name: str) -> None:
75
76
  setattr(config, DefaultConfigKeys.teamspace_owner_type, "organization")
76
77
  else:
77
78
  setattr(config, DefaultConfigKeys.teamspace_owner_type, "user")
79
+
80
+
81
+ @set_value.command("cloud-account")
82
+ @click.argument("cloud_account_name")
83
+ def set_cloud_account(cloud_account_name: str) -> None:
84
+ """Set the default cloud account name in the config."""
85
+ config = Config()
86
+ setattr(config, DefaultConfigKeys.cloud_account, cloud_account_name)
87
+
88
+
89
+ @set_value.command("cloud-provider")
90
+ @click.argument("cloud_provider_name")
91
+ def set_cloud_provider(cloud_provider_name: str) -> None:
92
+ """Set the default cloud provider name in the config."""
93
+ config = Config()
94
+
95
+ try:
96
+ cloud_provider = CloudProvider(cloud_provider_name)
97
+ except ValueError:
98
+ # TODO: make this a generic CLI error
99
+ raise ValueError(
100
+ f"Could not resolve cloud provider: '{cloud_provider_name}'. "
101
+ f"Supported values are: {', '.join(m.name for m in list(CloudProvider))}"
102
+ ) from None
103
+
104
+ setattr(config, DefaultConfigKeys.cloud_provider, cloud_provider.name)
@@ -18,10 +18,16 @@ from lightning_sdk.studio import Studio
18
18
  help="The cloud provider to start the studio on. Defaults to teamspace default.",
19
19
  type=click.Choice(m.name for m in list(CloudProvider)),
20
20
  )
21
+ @click.option(
22
+ "--cloud-account",
23
+ help="The cloud account to create the studio on. Defaults to teamspace default.",
24
+ type=click.STRING,
25
+ )
21
26
  def create_studio(
22
27
  studio_name: Optional[str] = None,
23
28
  teamspace: Optional[str] = None,
24
29
  cloud_provider: Optional[str] = None,
30
+ cloud_account: Optional[str] = None,
25
31
  ) -> None:
26
32
  """Create a new Studio.
27
33
 
@@ -42,8 +48,17 @@ def create_studio(
42
48
  else:
43
49
  resolved_teamspace = None
44
50
 
51
+ if cloud_provider is not None:
52
+ cloud_provider = CloudProvider(cloud_provider)
53
+
45
54
  try:
46
- studio = Studio(studio_name, teamspace=resolved_teamspace, create_ok=True, cloud_provider=cloud_provider)
55
+ studio = Studio(
56
+ studio_name,
57
+ teamspace=resolved_teamspace,
58
+ create_ok=True,
59
+ cloud_provider=cloud_provider,
60
+ cloud_account=cloud_account,
61
+ )
47
62
  except (RuntimeError, ValueError, ApiException) as e:
48
63
  print(e)
49
64
  if studio_name:
@@ -22,9 +22,17 @@ from lightning_sdk.studio import Studio
22
22
  @click.option("--interruptible", is_flag=True, help="Start the studio on an interruptible instance.")
23
23
  @click.option(
24
24
  "--cloud-provider",
25
- help="The cloud provider to start the studio on. Defaults to teamspace default.",
25
+ help=(
26
+ "The cloud provider to start the studio on. Defaults to teamspace default. "
27
+ "Only used if --create is specified."
28
+ ),
26
29
  type=click.Choice(m.name for m in list(CloudProvider)),
27
30
  )
31
+ @click.option(
32
+ "--cloud-account",
33
+ help="The cloud account to start the studio on. Defaults to teamspace default. Only used if --create is specified.",
34
+ type=click.STRING,
35
+ )
28
36
  def start_studio(
29
37
  studio_name: Optional[str] = None,
30
38
  teamspace: Optional[str] = None,
@@ -32,6 +40,7 @@ def start_studio(
32
40
  machine: Optional[str] = None,
33
41
  interruptible: bool = False,
34
42
  cloud_provider: Optional[str] = None,
43
+ cloud_account: Optional[str] = None,
35
44
  ) -> None:
36
45
  """Start a Studio.
37
46
 
@@ -52,8 +61,17 @@ def start_studio(
52
61
  else:
53
62
  resolved_teamspace = None
54
63
 
64
+ if cloud_provider is not None:
65
+ cloud_provider = CloudProvider(cloud_provider)
66
+
55
67
  try:
56
- studio = Studio(studio_name, teamspace=resolved_teamspace, create_ok=create, cloud_provider=cloud_provider)
68
+ studio = Studio(
69
+ studio_name,
70
+ teamspace=resolved_teamspace,
71
+ create_ok=create,
72
+ cloud_provider=cloud_provider,
73
+ cloud_account=cloud_account,
74
+ )
57
75
  except (RuntimeError, ValueError, ApiException):
58
76
  if studio_name:
59
77
  raise ValueError(f"Could not start Studio: '{studio_name}'. Does the Studio exist?") from None
@@ -638,6 +638,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_like_status import V1LikeSt
638
638
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_affiliate_links_response import V1ListAffiliateLinksResponse
639
639
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_agent_job_artifacts_response import V1ListAgentJobArtifactsResponse
640
640
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_agent_jobs_response import V1ListAgentJobsResponse
641
+ from lightning_sdk.lightning_cloud.openapi.models.v1_list_aggregated_pod_metrics_response import V1ListAggregatedPodMetricsResponse
641
642
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_assistants_response import V1ListAssistantsResponse
642
643
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_blog_posts_response import V1ListBlogPostsResponse
643
644
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_cloud_space_apps_response import V1ListCloudSpaceAppsResponse
@@ -160,6 +160,119 @@ class K8SClusterServiceApi(object):
160
160
  _request_timeout=params.get('_request_timeout'),
161
161
  collection_formats=collection_formats)
162
162
 
163
+ def k8_s_cluster_service_list_aggregated_pod_metrics(self, project_id: 'str', cluster_id: 'str', **kwargs) -> 'V1ListAggregatedPodMetricsResponse': # noqa: E501
164
+ """k8_s_cluster_service_list_aggregated_pod_metrics # noqa: E501
165
+
166
+ This method makes a synchronous HTTP request by default. To make an
167
+ asynchronous HTTP request, please pass async_req=True
168
+ >>> thread = api.k8_s_cluster_service_list_aggregated_pod_metrics(project_id, cluster_id, async_req=True)
169
+ >>> result = thread.get()
170
+
171
+ :param async_req bool
172
+ :param str project_id: (required)
173
+ :param str cluster_id: (required)
174
+ :param str namespace:
175
+ :param datetime start: Date range.
176
+ :param datetime end:
177
+ :return: V1ListAggregatedPodMetricsResponse
178
+ If the method is called asynchronously,
179
+ returns the request thread.
180
+ """
181
+ kwargs['_return_http_data_only'] = True
182
+ if kwargs.get('async_req'):
183
+ return self.k8_s_cluster_service_list_aggregated_pod_metrics_with_http_info(project_id, cluster_id, **kwargs) # noqa: E501
184
+ else:
185
+ (data) = self.k8_s_cluster_service_list_aggregated_pod_metrics_with_http_info(project_id, cluster_id, **kwargs) # noqa: E501
186
+ return data
187
+
188
+ def k8_s_cluster_service_list_aggregated_pod_metrics_with_http_info(self, project_id: 'str', cluster_id: 'str', **kwargs) -> 'V1ListAggregatedPodMetricsResponse': # noqa: E501
189
+ """k8_s_cluster_service_list_aggregated_pod_metrics # noqa: E501
190
+
191
+ This method makes a synchronous HTTP request by default. To make an
192
+ asynchronous HTTP request, please pass async_req=True
193
+ >>> thread = api.k8_s_cluster_service_list_aggregated_pod_metrics_with_http_info(project_id, cluster_id, async_req=True)
194
+ >>> result = thread.get()
195
+
196
+ :param async_req bool
197
+ :param str project_id: (required)
198
+ :param str cluster_id: (required)
199
+ :param str namespace:
200
+ :param datetime start: Date range.
201
+ :param datetime end:
202
+ :return: V1ListAggregatedPodMetricsResponse
203
+ If the method is called asynchronously,
204
+ returns the request thread.
205
+ """
206
+
207
+ all_params = ['project_id', 'cluster_id', 'namespace', 'start', 'end'] # noqa: E501
208
+ all_params.append('async_req')
209
+ all_params.append('_return_http_data_only')
210
+ all_params.append('_preload_content')
211
+ all_params.append('_request_timeout')
212
+
213
+ params = locals()
214
+ for key, val in six.iteritems(params['kwargs']):
215
+ if key not in all_params:
216
+ raise TypeError(
217
+ "Got an unexpected keyword argument '%s'"
218
+ " to method k8_s_cluster_service_list_aggregated_pod_metrics" % key
219
+ )
220
+ params[key] = val
221
+ del params['kwargs']
222
+ # verify the required parameter 'project_id' is set
223
+ if ('project_id' not in params or
224
+ params['project_id'] is None):
225
+ raise ValueError("Missing the required parameter `project_id` when calling `k8_s_cluster_service_list_aggregated_pod_metrics`") # noqa: E501
226
+ # verify the required parameter 'cluster_id' is set
227
+ if ('cluster_id' not in params or
228
+ params['cluster_id'] is None):
229
+ raise ValueError("Missing the required parameter `cluster_id` when calling `k8_s_cluster_service_list_aggregated_pod_metrics`") # noqa: E501
230
+
231
+ collection_formats = {}
232
+
233
+ path_params = {}
234
+ if 'project_id' in params:
235
+ path_params['projectId'] = params['project_id'] # noqa: E501
236
+ if 'cluster_id' in params:
237
+ path_params['clusterId'] = params['cluster_id'] # noqa: E501
238
+
239
+ query_params = []
240
+ if 'namespace' in params:
241
+ query_params.append(('namespace', params['namespace'])) # noqa: E501
242
+ if 'start' in params:
243
+ query_params.append(('start', params['start'])) # noqa: E501
244
+ if 'end' in params:
245
+ query_params.append(('end', params['end'])) # noqa: E501
246
+
247
+ header_params = {}
248
+
249
+ form_params = []
250
+ local_var_files = {}
251
+
252
+ body_params = None
253
+ # HTTP header `Accept`
254
+ header_params['Accept'] = self.api_client.select_header_accept(
255
+ ['application/json']) # noqa: E501
256
+
257
+ # Authentication setting
258
+ auth_settings = [] # noqa: E501
259
+
260
+ return self.api_client.call_api(
261
+ '/v1/projects/{projectId}/clusters/{clusterId}/aggregated-metrics/pods', 'GET',
262
+ path_params,
263
+ query_params,
264
+ header_params,
265
+ body=body_params,
266
+ post_params=form_params,
267
+ files=local_var_files,
268
+ response_type='V1ListAggregatedPodMetricsResponse', # noqa: E501
269
+ auth_settings=auth_settings,
270
+ async_req=params.get('async_req'),
271
+ _return_http_data_only=params.get('_return_http_data_only'),
272
+ _preload_content=params.get('_preload_content', True),
273
+ _request_timeout=params.get('_request_timeout'),
274
+ collection_formats=collection_formats)
275
+
163
276
  def k8_s_cluster_service_list_cluster_metrics(self, project_id: 'str', cluster_id: 'str', **kwargs) -> 'V1ListClusterMetricsResponse': # noqa: E501
164
277
  """k8_s_cluster_service_list_cluster_metrics # noqa: E501
165
278
 
@@ -590,6 +590,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_like_status import V1LikeSt
590
590
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_affiliate_links_response import V1ListAffiliateLinksResponse
591
591
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_agent_job_artifacts_response import V1ListAgentJobArtifactsResponse
592
592
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_agent_jobs_response import V1ListAgentJobsResponse
593
+ from lightning_sdk.lightning_cloud.openapi.models.v1_list_aggregated_pod_metrics_response import V1ListAggregatedPodMetricsResponse
593
594
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_assistants_response import V1ListAssistantsResponse
594
595
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_blog_posts_response import V1ListBlogPostsResponse
595
596
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_cloud_space_apps_response import V1ListCloudSpaceAppsResponse