lightning-sdk 2025.10.14__py3-none-any.whl → 2025.10.23__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 (76) hide show
  1. lightning_sdk/__init__.py +6 -3
  2. lightning_sdk/api/base_studio_api.py +13 -9
  3. lightning_sdk/api/job_api.py +4 -1
  4. lightning_sdk/api/license_api.py +26 -59
  5. lightning_sdk/api/studio_api.py +7 -2
  6. lightning_sdk/base_studio.py +30 -17
  7. lightning_sdk/cli/base_studio/list.py +1 -3
  8. lightning_sdk/cli/entrypoint.py +11 -34
  9. lightning_sdk/cli/groups.py +7 -0
  10. lightning_sdk/cli/license/__init__.py +14 -0
  11. lightning_sdk/cli/license/get.py +15 -0
  12. lightning_sdk/cli/license/list.py +45 -0
  13. lightning_sdk/cli/license/set.py +13 -0
  14. lightning_sdk/cli/studio/connect.py +42 -92
  15. lightning_sdk/cli/studio/create.py +23 -1
  16. lightning_sdk/cli/studio/start.py +12 -2
  17. lightning_sdk/cli/utils/get_base_studio.py +24 -0
  18. lightning_sdk/cli/utils/handle_machine_and_gpus_args.py +69 -0
  19. lightning_sdk/cli/utils/logging.py +121 -0
  20. lightning_sdk/cli/utils/ssh_connection.py +1 -1
  21. lightning_sdk/constants.py +1 -0
  22. lightning_sdk/helpers.py +53 -34
  23. lightning_sdk/job/base.py +7 -0
  24. lightning_sdk/job/job.py +8 -0
  25. lightning_sdk/job/v1.py +3 -0
  26. lightning_sdk/job/v2.py +4 -0
  27. lightning_sdk/lightning_cloud/login.py +260 -10
  28. lightning_sdk/lightning_cloud/openapi/__init__.py +16 -3
  29. lightning_sdk/lightning_cloud/openapi/api/auth_service_api.py +279 -0
  30. lightning_sdk/lightning_cloud/openapi/api/k8_s_cluster_service_api.py +117 -0
  31. lightning_sdk/lightning_cloud/openapi/api/product_license_service_api.py +108 -108
  32. lightning_sdk/lightning_cloud/openapi/models/__init__.py +16 -3
  33. lightning_sdk/lightning_cloud/openapi/models/create_machine_request_represents_the_request_to_create_a_machine.py +27 -1
  34. lightning_sdk/lightning_cloud/openapi/models/externalv1_cloud_space_instance_status.py +27 -1
  35. lightning_sdk/lightning_cloud/openapi/models/id_fork_body1.py +27 -1
  36. lightning_sdk/lightning_cloud/openapi/models/license_key_validate_body.py +123 -0
  37. lightning_sdk/lightning_cloud/openapi/models/update1.py +27 -1
  38. lightning_sdk/lightning_cloud/openapi/models/v1_create_license_request.py +175 -0
  39. lightning_sdk/lightning_cloud/openapi/models/v1_data_connection.py +27 -1
  40. lightning_sdk/lightning_cloud/openapi/models/v1_delete_license_response.py +97 -0
  41. lightning_sdk/lightning_cloud/openapi/models/v1_external_cluster_spec.py +27 -1
  42. lightning_sdk/lightning_cloud/openapi/models/v1_external_search_user.py +27 -1
  43. lightning_sdk/lightning_cloud/openapi/models/v1_filesystem_metric.py +201 -0
  44. lightning_sdk/lightning_cloud/openapi/models/v1_get_cloud_space_transfer_estimate_response.py +29 -3
  45. lightning_sdk/lightning_cloud/openapi/models/v1_incident.py +27 -1
  46. lightning_sdk/lightning_cloud/openapi/models/v1_incident_detail.py +149 -0
  47. lightning_sdk/lightning_cloud/openapi/models/v1_incident_event.py +27 -1
  48. lightning_sdk/lightning_cloud/openapi/models/v1_license.py +227 -0
  49. lightning_sdk/lightning_cloud/openapi/models/v1_list_filesystem_metrics_response.py +123 -0
  50. lightning_sdk/lightning_cloud/openapi/models/{v1_list_product_licenses_response.py → v1_list_license_response.py} +16 -16
  51. lightning_sdk/lightning_cloud/openapi/models/v1_list_platform_notifications_response.py +123 -0
  52. lightning_sdk/lightning_cloud/openapi/models/v1_machine.py +27 -1
  53. lightning_sdk/lightning_cloud/openapi/models/v1_platform_notification.py +279 -0
  54. lightning_sdk/lightning_cloud/openapi/models/v1_reset_api_key_request.py +97 -0
  55. lightning_sdk/lightning_cloud/openapi/models/v1_reset_api_key_response.py +123 -0
  56. lightning_sdk/lightning_cloud/openapi/models/v1_slack_notifier.py +53 -1
  57. lightning_sdk/lightning_cloud/openapi/models/v1_token_login_request.py +123 -0
  58. lightning_sdk/lightning_cloud/openapi/models/v1_token_login_response.py +123 -0
  59. lightning_sdk/lightning_cloud/openapi/models/v1_token_owner_type.py +104 -0
  60. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +139 -191
  61. lightning_sdk/lightning_cloud/openapi/models/{v1_product_license_check_response.py → v1_validate_license_response.py} +21 -21
  62. lightning_sdk/lightning_cloud/rest_client.py +48 -45
  63. lightning_sdk/machine.py +5 -0
  64. lightning_sdk/pipeline/steps.py +1 -0
  65. lightning_sdk/studio.py +55 -13
  66. lightning_sdk/utils/config.py +18 -3
  67. lightning_sdk/utils/license.py +13 -0
  68. lightning_sdk/utils/resolve.py +6 -1
  69. {lightning_sdk-2025.10.14.dist-info → lightning_sdk-2025.10.23.dist-info}/METADATA +1 -1
  70. {lightning_sdk-2025.10.14.dist-info → lightning_sdk-2025.10.23.dist-info}/RECORD +74 -54
  71. lightning_sdk/lightning_cloud/openapi/models/v1_product_license.py +0 -435
  72. lightning_sdk/services/license.py +0 -363
  73. {lightning_sdk-2025.10.14.dist-info → lightning_sdk-2025.10.23.dist-info}/LICENSE +0 -0
  74. {lightning_sdk-2025.10.14.dist-info → lightning_sdk-2025.10.23.dist-info}/WHEEL +0 -0
  75. {lightning_sdk-2025.10.14.dist-info → lightning_sdk-2025.10.23.dist-info}/entry_points.txt +0 -0
  76. {lightning_sdk-2025.10.14.dist-info → lightning_sdk-2025.10.23.dist-info}/top_level.txt +0 -0
lightning_sdk/job/base.py CHANGED
@@ -90,6 +90,7 @@ class _BaseJob(ABC):
90
90
  path_mappings: Optional[Dict[str, str]] = None,
91
91
  max_runtime: Optional[int] = None,
92
92
  cluster: Optional[str] = None, # deprecated in favor of cloud_account
93
+ reuse_snapshot: bool = True,
93
94
  ) -> "_BaseJob":
94
95
  """Run async workloads using a docker image or a compute environment from your studio.
95
96
 
@@ -134,6 +135,8 @@ class _BaseJob(ABC):
134
135
  Irrelevant for most machines, required for some of the top-end machines on GCP.
135
136
  If in doubt, set it. Won't have an effect on machines not requiring it.
136
137
  Defaults to 3h
138
+ reuse_snapshot: Whether the job should reuse a Studio snapshot when multiple jobs for the same Studio are
139
+ submitted. Turning this off may result in longer job startup times. Defaults to True.
137
140
  """
138
141
  from lightning_sdk.lightning_cloud.openapi.rest import ApiException
139
142
  from lightning_sdk.studio import Studio
@@ -231,6 +234,7 @@ class _BaseJob(ABC):
231
234
  entrypoint=entrypoint,
232
235
  path_mappings=path_mappings,
233
236
  max_runtime=max_runtime,
237
+ reuse_snapshot=reuse_snapshot,
234
238
  )
235
239
 
236
240
  @abstractmethod
@@ -251,6 +255,7 @@ class _BaseJob(ABC):
251
255
  entrypoint: str = "sh -c",
252
256
  path_mappings: Optional[Dict[str, str]] = None,
253
257
  max_runtime: Optional[int] = None,
258
+ reuse_snapshot: bool = True,
254
259
  ) -> "_BaseJob":
255
260
  """Submit a new job to the Lightning AI platform.
256
261
 
@@ -290,6 +295,8 @@ class _BaseJob(ABC):
290
295
  Irrelevant for most machines, required for some of the top-end machines on GCP.
291
296
  If in doubt, set it. Won't have an effect on machines not requiring it.
292
297
  Defaults to 3h
298
+ reuse_snapshot: Whether the job should reuse a Studio snapshot when multiple jobs for the same Studio are
299
+ submitted. Turning this off may result in longer job startup times. Defaults to True.
293
300
  """
294
301
 
295
302
  @abstractmethod
lightning_sdk/job/job.py CHANGED
@@ -97,6 +97,7 @@ class Job(_BaseJob):
97
97
  artifacts_local: Optional[str] = None, # deprecated in terms of path_mappings
98
98
  artifacts_remote: Optional[str] = None, # deprecated in terms of path_mappings
99
99
  cluster: Optional[str] = None, # deprecated in favor of cloud_account
100
+ reuse_snapshot: bool = True,
100
101
  ) -> "Job":
101
102
  """Run async workloads using a docker image or a compute environment from your studio.
102
103
 
@@ -140,6 +141,8 @@ class Job(_BaseJob):
140
141
  Irrelevant for most machines, required for some of the top-end machines on GCP.
141
142
  If in doubt, set it. Won't have an effect on machines not requiring it.
142
143
  Defaults to 3h
144
+ reuse_snapshot: Whether the job should reuse a Studio snapshot when multiple jobs for the same Studio are
145
+ submitted. Turning this off may result in longer job startup times. Defaults to True.
143
146
  """
144
147
  ret_val = super().run(
145
148
  name=name,
@@ -162,6 +165,7 @@ class Job(_BaseJob):
162
165
  path_mappings=path_mappings,
163
166
  max_runtime=max_runtime,
164
167
  cluster=cluster,
168
+ reuse_snapshot=reuse_snapshot,
165
169
  )
166
170
  # required for typing with "Job"
167
171
  assert isinstance(ret_val, cls)
@@ -186,6 +190,7 @@ class Job(_BaseJob):
186
190
  artifacts_local: Optional[str] = None, # deprecated in terms of path_mappings
187
191
  artifacts_remote: Optional[str] = None, # deprecated in terms of path_mappings
188
192
  max_runtime: Optional[int] = None,
193
+ reuse_snapshot: bool = True,
189
194
  ) -> "Job":
190
195
  """Submit a new job to the Lightning AI platform.
191
196
 
@@ -224,6 +229,8 @@ class Job(_BaseJob):
224
229
  Irrelevant for most machines, required for some of the top-end machines on GCP.
225
230
  If in doubt, set it. Won't have an effect on machines not requiring it.
226
231
  Defaults to 3h
232
+ reuse_snapshot: Whether the job should reuse a Studio snapshot when multiple jobs for the same Studio are
233
+ submitted. Turning this off may result in longer job startup times. Defaults to True.
227
234
  """
228
235
  self._job = self._internal_job._submit(
229
236
  machine=machine,
@@ -241,6 +248,7 @@ class Job(_BaseJob):
241
248
  artifacts_local=artifacts_local,
242
249
  artifacts_remote=artifacts_remote,
243
250
  max_runtime=max_runtime,
251
+ reuse_snapshot=reuse_snapshot,
244
252
  )
245
253
  return self
246
254
 
lightning_sdk/job/v1.py CHANGED
@@ -54,6 +54,7 @@ class _JobV1(_BaseJob):
54
54
  cloud_provider: Optional[str] = None,
55
55
  interruptible: bool = False,
56
56
  cluster: Optional[str] = None, # deprecated in favor of cloud_account
57
+ reuse_snapshot: bool = True,
57
58
  ) -> "_BaseJob":
58
59
  """Start a new async workload from your studio.
59
60
 
@@ -89,6 +90,7 @@ class _JobV1(_BaseJob):
89
90
  cluster=cluster,
90
91
  path_mappings=None,
91
92
  max_runtime=None,
93
+ reuse_snapshot=reuse_snapshot,
92
94
  )
93
95
 
94
96
  def _submit(
@@ -108,6 +110,7 @@ class _JobV1(_BaseJob):
108
110
  entrypoint: str = "sh -c",
109
111
  path_mappings: Optional[Dict[str, str]] = None,
110
112
  max_runtime: Optional[int] = None,
113
+ reuse_snapshot: bool = True,
111
114
  ) -> "_JobV1":
112
115
  """Submit a job to run on a machine.
113
116
 
lightning_sdk/job/v2.py CHANGED
@@ -53,6 +53,7 @@ class _JobV2(_BaseJob):
53
53
  max_runtime: Optional[int] = None,
54
54
  artifacts_local: Optional[str] = None, # deprecated in favor of path_mappings
55
55
  artifacts_remote: Optional[str] = None, # deprecated in favor of path_mappings
56
+ reuse_snapshot: bool = True,
56
57
  ) -> "_JobV2":
57
58
  """Submit a new job to the Lightning AI platform.
58
59
 
@@ -87,6 +88,8 @@ class _JobV2(_BaseJob):
87
88
  Irrelevant for most machines, required for some of the top-end machines on GCP.
88
89
  If in doubt, set it. Won't have an effect on machines not requiring it.
89
90
  Defaults to 3h
91
+ reuse_snapshot: Whether the job should reuse a Studio snapshot when multiple jobs for the same Studio are
92
+ submitted. Turning this off may result in longer job startup times. Defaults to True.
90
93
  """
91
94
  # Command is required if Studio is provided to know what to run
92
95
  # Image is mutually exclusive with Studio
@@ -129,6 +132,7 @@ class _JobV2(_BaseJob):
129
132
  entrypoint=entrypoint,
130
133
  path_mappings=path_mappings,
131
134
  max_runtime=max_runtime,
135
+ reuse_snapshot=reuse_snapshot,
132
136
  )
133
137
  self._job = submitted
134
138
  self._name = submitted.name
@@ -5,7 +5,7 @@ import logging
5
5
  import os
6
6
  import pathlib
7
7
  from dataclasses import dataclass
8
- from typing import Optional
8
+ from typing import Optional, Literal
9
9
  from urllib.parse import urlencode
10
10
 
11
11
  import webbrowser
@@ -22,14 +22,21 @@ from lightning_sdk.lightning_cloud.openapi.api import \
22
22
  AuthServiceApi
23
23
  from lightning_sdk.lightning_cloud.openapi.models.v1_guest_login_request import \
24
24
  V1GuestLoginRequest
25
+ from lightning_sdk.lightning_cloud.openapi.models.v1_token_login_request import \
26
+ V1TokenLoginRequest
27
+ from lightning_sdk.lightning_cloud.openapi.models.v1_refresh_request import \
28
+ V1RefreshRequest
25
29
 
26
30
  logger = logging.getLogger(__name__)
27
31
 
32
+ # Authentication override types
33
+ AuthOverride = Literal["auth_token", "api_key", "guest"]
28
34
 
29
35
  class Keys(Enum):
30
36
  # USERNAME = "LIGHTNING_USERNAME"
31
37
  USER_ID = "LIGHTNING_USER_ID"
32
38
  API_KEY = "LIGHTNING_API_KEY"
39
+ AUTH_TOKEN = "LIGHTNING_AUTH_TOKEN"
33
40
 
34
41
  @property
35
42
  def suffix(self):
@@ -41,15 +48,18 @@ class Auth:
41
48
  # username: Optional[str] = None
42
49
  user_id: Optional[str] = None
43
50
  api_key: Optional[str] = None
51
+ auth_token: Optional[str] = None
44
52
 
45
53
  secrets_file = pathlib.Path(env.LIGHTNING_CREDENTIAL_PATH)
46
54
 
47
55
  def __post_init__(self):
48
56
  for key in Keys:
49
- setattr(self, key.suffix, os.environ.get(key.value, None))
57
+ # Only set from environment if not already set
58
+ if getattr(self, key.suffix) is None:
59
+ setattr(self, key.suffix, os.environ.get(key.value, None))
50
60
 
51
61
  # used by authenticate method
52
- self._with_env_var = bool(self.api_key)
62
+ self._with_env_var = bool(self.api_key or self.auth_token)
53
63
 
54
64
  def load(self) -> bool:
55
65
  """Load credentials from disk and update properties with credentials.
@@ -71,6 +81,7 @@ class Auth:
71
81
  token: str = "",
72
82
  user_id: str = "",
73
83
  api_key: str = "",
84
+ auth_token: str = "",
74
85
  # username: str = "",
75
86
  ) -> None:
76
87
  """save credentials to disk."""
@@ -81,6 +92,7 @@ class Auth:
81
92
  # f"{Keys.USERNAME.suffix}": username,
82
93
  f"{Keys.USER_ID.suffix}": user_id,
83
94
  f"{Keys.API_KEY.suffix}": api_key,
95
+ f"{Keys.AUTH_TOKEN.suffix}": auth_token,
84
96
  },
85
97
  f,
86
98
  )
@@ -88,6 +100,7 @@ class Auth:
88
100
  # self.username = username
89
101
  self.user_id = user_id
90
102
  self.api_key = api_key
103
+ self.auth_token = auth_token
91
104
  logger.debug("credentials saved successfully")
92
105
 
93
106
  @classmethod
@@ -99,15 +112,78 @@ class Auth:
99
112
  os.environ.pop(key.value, None)
100
113
  logger.debug("credentials removed successfully")
101
114
 
102
- @property
103
- def auth_header(self) -> Optional[str]:
104
- """authentication header used by lightning-cloud client."""
105
- if self.api_key:
115
+ def get_auth_header(self, override: Optional[AuthOverride] = None) -> Optional[str]:
116
+ """Get authentication header with optional override.
117
+
118
+ By default, uses the automatic priority selection (auth_token > api_key).
119
+ You can override this for specific cases where you need a different auth method.
120
+
121
+ Parameters
122
+ ----------
123
+ override : AuthOverride, optional
124
+ Override the default authentication method:
125
+ - "auth_token": Force use of JWT auth token (Bearer)
126
+ - "api_key": Force use of API key (Basic)
127
+ - "guest": Force use of guest credentials (Basic)
128
+ - None: Use automatic selection (default)
129
+
130
+ Returns
131
+ -------
132
+ Optional[str]
133
+ The authorization header for the specified method.
134
+
135
+ Raises
136
+ ------
137
+ ValueError
138
+ If the specified override is not available or invalid.
139
+ """
140
+ if override == "auth_token":
141
+ if not self.auth_token:
142
+ raise ValueError(
143
+ "Auth token override requested but no JWT token available. "
144
+ "Please use token_login() method first."
145
+ )
146
+ return f"Bearer {self.auth_token}"
147
+
148
+ elif override == "api_key":
149
+ if not self.api_key or not self.user_id:
150
+ raise ValueError(
151
+ "API key override requested but no API key or user ID available. "
152
+ "Please set LIGHTNING_API_KEY and LIGHTNING_USER_ID environment variables "
153
+ "or use authenticate() method."
154
+ )
155
+ token = f"{self.user_id}:{self.api_key}"
156
+ return f"Basic {base64.b64encode(token.encode('ascii')).decode('ascii')}" # noqa E501
157
+
158
+ elif override == "guest":
159
+ if not self.api_key or not self.user_id:
160
+ raise ValueError(
161
+ "Guest override requested but no guest credentials available. "
162
+ "Please call guest_login() method first."
163
+ )
106
164
  token = f"{self.user_id}:{self.api_key}"
107
165
  return f"Basic {base64.b64encode(token.encode('ascii')).decode('ascii')}" # noqa E501
108
- raise AttributeError(
109
- "Authentication Failed, no authentication header available. "
110
- "This is most likely a bug in the LightningCloud Framework")
166
+
167
+ elif override is None:
168
+ # Use the original automatic selection logic (default behavior)
169
+ if self.auth_token:
170
+ return f"Bearer {self.auth_token}"
171
+ elif self.api_key:
172
+ token = f"{self.user_id}:{self.api_key}"
173
+ return f"Basic {base64.b64encode(token.encode('ascii')).decode('ascii')}" # noqa E501
174
+ else:
175
+ raise ValueError(
176
+ "No authentication credentials available. Please authenticate first using "
177
+ "token_login(), guest_login(), or authenticate() methods."
178
+ )
179
+
180
+ else:
181
+ raise ValueError(f"Invalid authentication override: {override}")
182
+
183
+ @property
184
+ def auth_header(self) -> Optional[str]:
185
+ """authentication header used by lightning-cloud client (automatic selection)."""
186
+ return self.get_auth_header()
111
187
 
112
188
  def _run_server(self) -> None:
113
189
  """start a server to complete authentication."""
@@ -130,6 +206,8 @@ class Auth:
130
206
  self._run_server()
131
207
  return self.auth_header
132
208
 
209
+ elif self.auth_token:
210
+ return self.auth_header
133
211
  elif self.user_id and self.api_key:
134
212
  return self.auth_header
135
213
 
@@ -192,6 +270,178 @@ class Auth:
192
270
 
193
271
  return self.auth_header
194
272
 
273
+ def token_login(self, token_key: str, save_token: bool = True) -> Optional[str]:
274
+ """Performs token-based authentication.
275
+
276
+ This method sends a request to the token login endpoint to authenticate
277
+ using an auth token key, optionally saves the returned JWT token, and
278
+ returns the authorization header.
279
+
280
+ Parameters
281
+ ----------
282
+ token_key : str
283
+ The auth token key to use for authentication.
284
+ save_token : bool, optional
285
+ Whether to save the JWT token for future use. Defaults to True.
286
+ If False, the token is only used for the current session.
287
+
288
+ Returns
289
+ -------
290
+ Optional[str]
291
+ The authorization header to use for subsequent requests.
292
+
293
+ Raises
294
+ ------
295
+ RuntimeError
296
+ If the token login request fails.
297
+ ValueError
298
+ If the response from the server is invalid.
299
+ """
300
+ config = Configuration()
301
+ config.host = env.LIGHTNING_CLOUD_URL
302
+ api_client = ApiClient(configuration=config)
303
+ auth_api = AuthServiceApi(api_client)
304
+
305
+ logger.debug(f"Attempting token login to {config.host}")
306
+
307
+ try:
308
+ body = V1TokenLoginRequest(token_key=token_key)
309
+ response = auth_api.auth_service_token_login(body)
310
+
311
+ except requests.RequestException as e:
312
+ logger.error(f"Token login request failed: {e}")
313
+ raise RuntimeError(
314
+ "Failed to connect to the token login endpoint. "
315
+ "Please check your network connection and the server status."
316
+ ) from e
317
+
318
+ # Extract the JWT token from the response
319
+ jwt_token = getattr(response, "token", None)
320
+
321
+ if not jwt_token:
322
+ logger.error(
323
+ f"No token received from token login response: {response}"
324
+ )
325
+ raise ValueError(
326
+ "The token login response did not contain a valid JWT token."
327
+ )
328
+
329
+ # Set the JWT token in memory
330
+ self.auth_token = jwt_token
331
+
332
+ # Optionally save the JWT token to disk
333
+ if save_token:
334
+ self.save(auth_token=jwt_token)
335
+ logger.info("Successfully authenticated using auth token and saved to disk.")
336
+ else:
337
+ logger.info("Successfully authenticated using auth token (not saved to disk).")
338
+
339
+ return self.auth_header
340
+
341
+ def refresh_token(self, duration: int = 43200) -> Optional[str]:
342
+ """Refreshes the current JWT token.
343
+
344
+ This method sends a request to the refresh endpoint to get a new JWT token
345
+ with the specified duration, saves the new token, and returns the updated
346
+ authorization header.
347
+
348
+ Parameters
349
+ ----------
350
+ duration : int, optional
351
+ Duration in seconds for the new token. Can range from 900 seconds (15 minutes)
352
+ up to a maximum of 129,600 seconds (36 hours), with a default of 43,200 seconds (12 hours).
353
+
354
+ Returns
355
+ -------
356
+ Optional[str]
357
+ The updated authorization header with the new JWT token.
358
+
359
+ Raises
360
+ ------
361
+ RuntimeError
362
+ If the refresh request fails.
363
+ ValueError
364
+ If no valid JWT token is available to refresh, or if the response is invalid.
365
+ """
366
+ if not self.auth_token:
367
+ raise ValueError(
368
+ "No JWT token available to refresh. Please authenticate first using "
369
+ "token_login() or authenticate() methods."
370
+ )
371
+
372
+ config = Configuration()
373
+ config.host = env.LIGHTNING_CLOUD_URL
374
+ # Set the current auth token as the authorization header
375
+ config.api_key_prefix['Authorization'] = 'Bearer'
376
+ config.api_key['Authorization'] = self.auth_token
377
+
378
+ api_client = ApiClient(configuration=config)
379
+ auth_api = AuthServiceApi(api_client)
380
+
381
+ logger.debug(f"Attempting to refresh JWT token with duration {duration} seconds")
382
+
383
+ try:
384
+ body = V1RefreshRequest(duration=str(duration))
385
+ response = auth_api.auth_service_refresh(body)
386
+
387
+ except requests.RequestException as e:
388
+ logger.error(f"Token refresh request failed: {e}")
389
+ raise RuntimeError(
390
+ "Failed to connect to the refresh endpoint. "
391
+ "Please check your network connection and the server status."
392
+ ) from e
393
+
394
+ # Extract the new JWT token from the response
395
+ new_jwt_token = getattr(response, "token", None)
396
+
397
+ if not new_jwt_token:
398
+ logger.error(
399
+ f"No token received from refresh response: {response}"
400
+ )
401
+ raise ValueError(
402
+ "The refresh response did not contain a valid JWT token."
403
+ )
404
+
405
+ # Save the new JWT token
406
+ self.save(auth_token=new_jwt_token)
407
+ logger.info("Successfully refreshed JWT token.")
408
+
409
+ return self.auth_header
410
+
411
+ def create_api_client(self, override: Optional[AuthOverride] = None) -> 'ApiClient':
412
+ """Create an API client with optional authentication override.
413
+
414
+ This is a convenience method for creating API clients that use a specific
415
+ authentication method instead of the default automatic selection.
416
+
417
+ Parameters
418
+ ----------
419
+ override : AuthOverride, optional
420
+ Override the default authentication method for this API client.
421
+ See get_auth_header() for available options.
422
+
423
+ Returns
424
+ -------
425
+ ApiClient
426
+ Configured API client with the specified authentication method.
427
+ """
428
+ from lightning_sdk.lightning_cloud.openapi import ApiClient, Configuration
429
+
430
+ config = Configuration()
431
+ config.host = env.LIGHTNING_CLOUD_URL
432
+
433
+ # Get the auth header for the specified override
434
+ auth_header = self.get_auth_header(override)
435
+
436
+ # Create the API client
437
+ client = ApiClient(configuration=config)
438
+
439
+ # Set the Authorization header directly in default_headers
440
+ if auth_header:
441
+ client.set_default_header('Authorization', auth_header)
442
+
443
+ return client
444
+
195
445
 
196
446
  class AuthServer:
197
447
 
@@ -166,6 +166,7 @@ from lightning_sdk.lightning_cloud.openapi.models.jobs_id_body1 import JobsIdBod
166
166
  from lightning_sdk.lightning_cloud.openapi.models.jobs_id_body2 import JobsIdBody2
167
167
  from lightning_sdk.lightning_cloud.openapi.models.jobs_id_body3 import JobsIdBody3
168
168
  from lightning_sdk.lightning_cloud.openapi.models.kubernetestemplates_id_body import KubernetestemplatesIdBody
169
+ from lightning_sdk.lightning_cloud.openapi.models.license_key_validate_body import LicenseKeyValidateBody
169
170
  from lightning_sdk.lightning_cloud.openapi.models.litdatasets_dataset_id_body import LitdatasetsDatasetIdBody
170
171
  from lightning_sdk.lightning_cloud.openapi.models.litloggermetrics_id_body import LitloggermetricsIdBody
171
172
  from lightning_sdk.lightning_cloud.openapi.models.litpages_id_body import LitpagesIdBody
@@ -394,6 +395,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_create_deployment_request i
394
395
  from lightning_sdk.lightning_cloud.openapi.models.v1_create_deployment_template_request import V1CreateDeploymentTemplateRequest
395
396
  from lightning_sdk.lightning_cloud.openapi.models.v1_create_git_credentials_request import V1CreateGitCredentialsRequest
396
397
  from lightning_sdk.lightning_cloud.openapi.models.v1_create_job_request import V1CreateJobRequest
398
+ from lightning_sdk.lightning_cloud.openapi.models.v1_create_license_request import V1CreateLicenseRequest
397
399
  from lightning_sdk.lightning_cloud.openapi.models.v1_create_lit_dataset_multi_part_upload_response import V1CreateLitDatasetMultiPartUploadResponse
398
400
  from lightning_sdk.lightning_cloud.openapi.models.v1_create_lit_page_request import V1CreateLitPageRequest
399
401
  from lightning_sdk.lightning_cloud.openapi.models.v1_create_lit_page_response import V1CreateLitPageResponse
@@ -452,6 +454,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_delete_incident_response im
452
454
  from lightning_sdk.lightning_cloud.openapi.models.v1_delete_index_response import V1DeleteIndexResponse
453
455
  from lightning_sdk.lightning_cloud.openapi.models.v1_delete_job_response import V1DeleteJobResponse
454
456
  from lightning_sdk.lightning_cloud.openapi.models.v1_delete_kubernetes_template_response import V1DeleteKubernetesTemplateResponse
457
+ from lightning_sdk.lightning_cloud.openapi.models.v1_delete_license_response import V1DeleteLicenseResponse
455
458
  from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lightning_run_response import V1DeleteLightningRunResponse
456
459
  from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lightningapp_instance_artifact_response import V1DeleteLightningappInstanceArtifactResponse
457
460
  from lightning_sdk.lightning_cloud.openapi.models.v1_delete_lightningapp_instance_response import V1DeleteLightningappInstanceResponse
@@ -546,6 +549,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_cloud_space impo
546
549
  from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_dataset import V1FilesystemDataset
547
550
  from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_job import V1FilesystemJob
548
551
  from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_mmt import V1FilesystemMMT
552
+ from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_metric import V1FilesystemMetric
549
553
  from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_metrics import V1FilesystemMetrics
550
554
  from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_slurm_job import V1FilesystemSlurmJob
551
555
  from lightning_sdk.lightning_cloud.openapi.models.v1_filesystem_snowflake_connection import V1FilesystemSnowflakeConnection
@@ -630,6 +634,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_ids_logger_metrics import V
630
634
  from lightning_sdk.lightning_cloud.openapi.models.v1_image_spec import V1ImageSpec
631
635
  from lightning_sdk.lightning_cloud.openapi.models.v1_image_state import V1ImageState
632
636
  from lightning_sdk.lightning_cloud.openapi.models.v1_incident import V1Incident
637
+ from lightning_sdk.lightning_cloud.openapi.models.v1_incident_detail import V1IncidentDetail
633
638
  from lightning_sdk.lightning_cloud.openapi.models.v1_incident_event import V1IncidentEvent
634
639
  from lightning_sdk.lightning_cloud.openapi.models.v1_incident_message import V1IncidentMessage
635
640
  from lightning_sdk.lightning_cloud.openapi.models.v1_incident_severity import V1IncidentSeverity
@@ -662,6 +667,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_kubernetes_direct_v1_status
662
667
  from lightning_sdk.lightning_cloud.openapi.models.v1_kubernetes_template import V1KubernetesTemplate
663
668
  from lightning_sdk.lightning_cloud.openapi.models.v1_kubernetes_template_property import V1KubernetesTemplateProperty
664
669
  from lightning_sdk.lightning_cloud.openapi.models.v1_lambda_labs_direct_v1 import V1LambdaLabsDirectV1
670
+ from lightning_sdk.lightning_cloud.openapi.models.v1_license import V1License
665
671
  from lightning_sdk.lightning_cloud.openapi.models.v1_lightning_app_user import V1LightningAppUser
666
672
  from lightning_sdk.lightning_cloud.openapi.models.v1_lightning_auth import V1LightningAuth
667
673
  from lightning_sdk.lightning_cloud.openapi.models.v1_lightning_basic_auth import V1LightningBasicAuth
@@ -730,6 +736,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_cloud_space
730
736
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_datasets_response import V1ListFilesystemDatasetsResponse
731
737
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_jobs_response import V1ListFilesystemJobsResponse
732
738
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_mm_ts_response import V1ListFilesystemMMTsResponse
739
+ from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_metrics_response import V1ListFilesystemMetricsResponse
733
740
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_slurm_jobs_response import V1ListFilesystemSlurmJobsResponse
734
741
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_filesystem_snowflake_response import V1ListFilesystemSnowflakeResponse
735
742
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_gallery_components_response import V1ListGalleryComponentsResponse
@@ -745,6 +752,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_list_jobs_response import V
745
752
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_joinable_organizations_response import V1ListJoinableOrganizationsResponse
746
753
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_kai_scheduler_queues_metrics_response import V1ListKaiSchedulerQueuesMetricsResponse
747
754
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_kubernetes_templates_response import V1ListKubernetesTemplatesResponse
755
+ from lightning_sdk.lightning_cloud.openapi.models.v1_list_license_response import V1ListLicenseResponse
748
756
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_lightning_run_response import V1ListLightningRunResponse
749
757
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_lightningapp_instance_artifacts_response import V1ListLightningappInstanceArtifactsResponse
750
758
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_lightningapp_instance_events_response import V1ListLightningappInstanceEventsResponse
@@ -774,8 +782,8 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_list_org_roles_response imp
774
782
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_organization_cluster_encryption_keys_response import V1ListOrganizationClusterEncryptionKeysResponse
775
783
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_organizations_response import V1ListOrganizationsResponse
776
784
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_pipelines_response import V1ListPipelinesResponse
785
+ from lightning_sdk.lightning_cloud.openapi.models.v1_list_platform_notifications_response import V1ListPlatformNotificationsResponse
777
786
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_pod_metrics_response import V1ListPodMetricsResponse
778
- from lightning_sdk.lightning_cloud.openapi.models.v1_list_product_licenses_response import V1ListProductLicensesResponse
779
787
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_profiler_captures_response import V1ListProfilerCapturesResponse
780
788
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_project_artifacts_response import V1ListProjectArtifactsResponse
781
789
  from lightning_sdk.lightning_cloud.openapi.models.v1_list_project_cluster_accelerators_response import V1ListProjectClusterAcceleratorsResponse
@@ -882,13 +890,12 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_pipeline_step_status import
882
890
  from lightning_sdk.lightning_cloud.openapi.models.v1_pipeline_step_type import V1PipelineStepType
883
891
  from lightning_sdk.lightning_cloud.openapi.models.v1_pipeline_template import V1PipelineTemplate
884
892
  from lightning_sdk.lightning_cloud.openapi.models.v1_pipeline_template_visibility_type import V1PipelineTemplateVisibilityType
893
+ from lightning_sdk.lightning_cloud.openapi.models.v1_platform_notification import V1PlatformNotification
885
894
  from lightning_sdk.lightning_cloud.openapi.models.v1_plugin import V1Plugin
886
895
  from lightning_sdk.lightning_cloud.openapi.models.v1_plugins_list_response import V1PluginsListResponse
887
896
  from lightning_sdk.lightning_cloud.openapi.models.v1_pod_metrics import V1PodMetrics
888
897
  from lightning_sdk.lightning_cloud.openapi.models.v1_post_cloud_space_artifact_events_response import V1PostCloudSpaceArtifactEventsResponse
889
898
  from lightning_sdk.lightning_cloud.openapi.models.v1_presigned_url import V1PresignedUrl
890
- from lightning_sdk.lightning_cloud.openapi.models.v1_product_license import V1ProductLicense
891
- from lightning_sdk.lightning_cloud.openapi.models.v1_product_license_check_response import V1ProductLicenseCheckResponse
892
899
  from lightning_sdk.lightning_cloud.openapi.models.v1_profiler_capture import V1ProfilerCapture
893
900
  from lightning_sdk.lightning_cloud.openapi.models.v1_profiler_enabled_response import V1ProfilerEnabledResponse
894
901
  from lightning_sdk.lightning_cloud.openapi.models.v1_project import V1Project
@@ -938,6 +945,8 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_request_cluster_access_resp
938
945
  from lightning_sdk.lightning_cloud.openapi.models.v1_request_verification_code_response import V1RequestVerificationCodeResponse
939
946
  from lightning_sdk.lightning_cloud.openapi.models.v1_required_balance_reason import V1RequiredBalanceReason
940
947
  from lightning_sdk.lightning_cloud.openapi.models.v1_reservation_details import V1ReservationDetails
948
+ from lightning_sdk.lightning_cloud.openapi.models.v1_reset_api_key_request import V1ResetAPIKeyRequest
949
+ from lightning_sdk.lightning_cloud.openapi.models.v1_reset_api_key_response import V1ResetAPIKeyResponse
941
950
  from lightning_sdk.lightning_cloud.openapi.models.v1_resource_tag import V1ResourceTag
942
951
  from lightning_sdk.lightning_cloud.openapi.models.v1_resource_visibility import V1ResourceVisibility
943
952
  from lightning_sdk.lightning_cloud.openapi.models.v1_resources import V1Resources
@@ -1010,6 +1019,9 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_system_metrics_aggregated i
1010
1019
  from lightning_sdk.lightning_cloud.openapi.models.v1_system_metrics_list import V1SystemMetricsList
1011
1020
  from lightning_sdk.lightning_cloud.openapi.models.v1_telemetry import V1Telemetry
1012
1021
  from lightning_sdk.lightning_cloud.openapi.models.v1_timestamp_code_telemetry import V1TimestampCodeTelemetry
1022
+ from lightning_sdk.lightning_cloud.openapi.models.v1_token_login_request import V1TokenLoginRequest
1023
+ from lightning_sdk.lightning_cloud.openapi.models.v1_token_login_response import V1TokenLoginResponse
1024
+ from lightning_sdk.lightning_cloud.openapi.models.v1_token_owner_type import V1TokenOwnerType
1013
1025
  from lightning_sdk.lightning_cloud.openapi.models.v1_token_usage import V1TokenUsage
1014
1026
  from lightning_sdk.lightning_cloud.openapi.models.v1_tool import V1Tool
1015
1027
  from lightning_sdk.lightning_cloud.openapi.models.v1_tool_call import V1ToolCall
@@ -1074,6 +1086,7 @@ from lightning_sdk.lightning_cloud.openapi.models.v1_validate_auto_join_domain_r
1074
1086
  from lightning_sdk.lightning_cloud.openapi.models.v1_validate_data_connection_response import V1ValidateDataConnectionResponse
1075
1087
  from lightning_sdk.lightning_cloud.openapi.models.v1_validate_deployment_image_request import V1ValidateDeploymentImageRequest
1076
1088
  from lightning_sdk.lightning_cloud.openapi.models.v1_validate_deployment_image_response import V1ValidateDeploymentImageResponse
1089
+ from lightning_sdk.lightning_cloud.openapi.models.v1_validate_license_response import V1ValidateLicenseResponse
1077
1090
  from lightning_sdk.lightning_cloud.openapi.models.v1_validate_managed_endpoint_request import V1ValidateManagedEndpointRequest
1078
1091
  from lightning_sdk.lightning_cloud.openapi.models.v1_validate_managed_endpoint_response import V1ValidateManagedEndpointResponse
1079
1092
  from lightning_sdk.lightning_cloud.openapi.models.v1_validate_managed_model_response import V1ValidateManagedModelResponse