skypilot-nightly 1.0.0.dev20250627__py3-none-any.whl → 1.0.0.dev20250628__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.
- sky/__init__.py +2 -2
- sky/adaptors/kubernetes.py +7 -0
- sky/adaptors/nebius.py +2 -2
- sky/authentication.py +12 -5
- sky/backends/backend_utils.py +92 -26
- sky/check.py +5 -2
- sky/client/cli/command.py +38 -6
- sky/client/sdk.py +217 -167
- sky/client/service_account_auth.py +47 -0
- sky/clouds/aws.py +10 -4
- sky/clouds/azure.py +5 -2
- sky/clouds/cloud.py +5 -2
- sky/clouds/gcp.py +31 -18
- sky/clouds/kubernetes.py +54 -34
- sky/clouds/nebius.py +8 -2
- sky/clouds/ssh.py +5 -2
- sky/clouds/utils/aws_utils.py +10 -4
- sky/clouds/utils/gcp_utils.py +22 -7
- sky/clouds/utils/oci_utils.py +62 -14
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/{HudU4f4Xsy-cP51JvXSZ- → ZYLkkWSYZjJhLVsObh20y}/_buildManifest.js +1 -1
- sky/dashboard/out/_next/static/chunks/43-f38a531f6692f281.js +1 -0
- sky/dashboard/out/_next/static/chunks/601-111d06d9ded11d00.js +1 -0
- sky/dashboard/out/_next/static/chunks/{616-d6128fa9e7cae6e6.js → 616-50a620ac4a23deb4.js} +1 -1
- sky/dashboard/out/_next/static/chunks/691.fd9292250ab089af.js +21 -0
- sky/dashboard/out/_next/static/chunks/{785.dc2686c3c1235554.js → 785.3446c12ffdf3d188.js} +1 -1
- sky/dashboard/out/_next/static/chunks/871-e547295e7e21399c.js +6 -0
- sky/dashboard/out/_next/static/chunks/937.72796f7afe54075b.js +1 -0
- sky/dashboard/out/_next/static/chunks/938-0a770415b5ce4649.js +1 -0
- sky/dashboard/out/_next/static/chunks/982.d7bd80ed18cad4cc.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-21080826c6095f21.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-77d4816945b04793.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/{clusters-f119a5630a1efd61.js → clusters-65b2c90320b8afb8.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-64bdc0b2d3a44709.js +16 -0
- sky/dashboard/out/_next/static/chunks/pages/{jobs-0a5695ff3075d94a.js → jobs-df7407b5e37d3750.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/{users-4978cbb093e141e7.js → users-d7684eaa04c4f58f.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-cb7e720b739de53a.js → [name]-04e1b3ad4207b1e9.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/{workspaces-50e230828730cfb3.js → workspaces-c470366a6179f16e.js} +1 -1
- sky/dashboard/out/_next/static/chunks/{webpack-08fdb9e6070127fc.js → webpack-75a3310ef922a299.js} +1 -1
- sky/dashboard/out/_next/static/css/605ac87514049058.css +3 -0
- sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
- sky/dashboard/out/clusters/[cluster].html +1 -1
- sky/dashboard/out/clusters.html +1 -1
- sky/dashboard/out/config.html +1 -1
- sky/dashboard/out/index.html +1 -1
- sky/dashboard/out/infra/[context].html +1 -1
- sky/dashboard/out/infra.html +1 -1
- sky/dashboard/out/jobs/[job].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/volumes.html +1 -1
- sky/dashboard/out/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/data/storage.py +8 -3
- sky/global_user_state.py +257 -9
- sky/jobs/client/sdk.py +20 -25
- sky/models.py +16 -0
- sky/provision/kubernetes/config.py +1 -1
- sky/provision/kubernetes/instance.py +7 -4
- sky/provision/kubernetes/network.py +15 -9
- sky/provision/kubernetes/network_utils.py +42 -23
- sky/provision/kubernetes/utils.py +73 -35
- sky/provision/nebius/utils.py +10 -4
- sky/resources.py +10 -4
- sky/serve/client/sdk.py +28 -34
- sky/server/common.py +51 -3
- sky/server/constants.py +3 -0
- sky/server/requests/executor.py +4 -0
- sky/server/requests/payloads.py +33 -0
- sky/server/requests/requests.py +19 -0
- sky/server/rest.py +6 -15
- sky/server/server.py +121 -6
- sky/skylet/constants.py +6 -0
- sky/skypilot_config.py +32 -4
- sky/users/permission.py +29 -0
- sky/users/server.py +384 -5
- sky/users/token_service.py +196 -0
- sky/utils/common_utils.py +4 -5
- sky/utils/config_utils.py +41 -0
- sky/utils/controller_utils.py +5 -1
- sky/utils/resource_checker.py +153 -0
- sky/utils/resources_utils.py +12 -4
- sky/utils/schemas.py +87 -60
- sky/utils/subprocess_utils.py +2 -6
- sky/workspaces/core.py +9 -117
- {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250628.dist-info}/METADATA +1 -1
- {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250628.dist-info}/RECORD +94 -91
- sky/dashboard/out/_next/static/chunks/43-36177d00f6956ab2.js +0 -1
- sky/dashboard/out/_next/static/chunks/690.55f9eed3be903f56.js +0 -16
- sky/dashboard/out/_next/static/chunks/871-3db673be3ee3750b.js +0 -6
- sky/dashboard/out/_next/static/chunks/937.3759f538f11a0953.js +0 -1
- sky/dashboard/out/_next/static/chunks/938-068520cc11738deb.js +0 -1
- sky/dashboard/out/_next/static/chunks/973-81b2d057178adb76.js +0 -1
- sky/dashboard/out/_next/static/chunks/982.1b61658204416b0f.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-aff040d7bc5d0086.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-8040f2483897ed0c.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-e4b23128db0774cd.js +0 -16
- sky/dashboard/out/_next/static/css/52082cf558ec9705.css +0 -3
- /sky/dashboard/out/_next/static/{HudU4f4Xsy-cP51JvXSZ- → ZYLkkWSYZjJhLVsObh20y}/_ssgManifest.js +0 -0
- /sky/dashboard/out/_next/static/chunks/pages/{_app-9a3ce3170d2edcec.js → _app-050a9e637b057b24.js} +0 -0
- {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250628.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250628.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250628.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250627.dist-info → skypilot_nightly-1.0.0.dev20250628.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
"""Service account token authentication for SkyPilot client."""
|
2
|
+
|
3
|
+
import os
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
from sky import skypilot_config
|
7
|
+
from sky.skylet import constants
|
8
|
+
|
9
|
+
|
10
|
+
def _get_service_account_token() -> Optional[str]:
|
11
|
+
"""Get service account token from environment variable or config file.
|
12
|
+
|
13
|
+
Priority order:
|
14
|
+
1. SKYPILOT_SERVICE_ACCOUNT_TOKEN environment variable
|
15
|
+
2. ~/.sky/config.yaml service_account_token field
|
16
|
+
|
17
|
+
Returns:
|
18
|
+
The service account token if found, None otherwise.
|
19
|
+
"""
|
20
|
+
# Check environment variable first
|
21
|
+
token = os.environ.get(constants.SERVICE_ACCOUNT_TOKEN_ENV_VAR)
|
22
|
+
if token:
|
23
|
+
if not token.startswith('sky_'):
|
24
|
+
raise ValueError('Invalid service account token format. '
|
25
|
+
'Token must start with "sky_"')
|
26
|
+
return token
|
27
|
+
|
28
|
+
# Check config file
|
29
|
+
token = skypilot_config.get_nested(('api_server', 'service_account_token'),
|
30
|
+
default_value=None)
|
31
|
+
if token and not token.startswith('sky_'):
|
32
|
+
raise ValueError('Invalid service account token format in config. '
|
33
|
+
'Token must start with "sky_"')
|
34
|
+
return token
|
35
|
+
|
36
|
+
|
37
|
+
def get_service_account_headers() -> dict:
|
38
|
+
"""Get headers for service account authentication.
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
Dictionary with Authorization header if token is available,
|
42
|
+
empty dict otherwise.
|
43
|
+
"""
|
44
|
+
token = _get_service_account_token()
|
45
|
+
if token:
|
46
|
+
return {'Authorization': f'Bearer {token}'}
|
47
|
+
return {}
|
sky/clouds/aws.py
CHANGED
@@ -458,10 +458,16 @@ class AWS(clouds.Cloud):
|
|
458
458
|
image_id = self._get_image_id(image_id_to_use, region_name,
|
459
459
|
resources.instance_type)
|
460
460
|
|
461
|
-
disk_encrypted = skypilot_config.
|
462
|
-
|
463
|
-
|
464
|
-
('
|
461
|
+
disk_encrypted = skypilot_config.get_effective_region_config(
|
462
|
+
cloud='aws',
|
463
|
+
region=region_name,
|
464
|
+
keys=('disk_encrypted',),
|
465
|
+
default_value=False)
|
466
|
+
user_security_group_config = skypilot_config.get_effective_region_config(
|
467
|
+
cloud='aws',
|
468
|
+
region=region_name,
|
469
|
+
keys=('security_group_name',),
|
470
|
+
default_value=None)
|
465
471
|
user_security_group = None
|
466
472
|
if isinstance(user_security_group_config, str):
|
467
473
|
user_security_group = user_security_group_config
|
sky/clouds/azure.py
CHANGED
@@ -380,8 +380,11 @@ class Azure(clouds.Cloud):
|
|
380
380
|
}
|
381
381
|
|
382
382
|
# Determine resource group for deploying the instance.
|
383
|
-
resource_group_name = skypilot_config.
|
384
|
-
|
383
|
+
resource_group_name = skypilot_config.get_effective_region_config(
|
384
|
+
cloud='azure',
|
385
|
+
region=region_name,
|
386
|
+
keys=('resource_group_vm',),
|
387
|
+
default_value=None)
|
385
388
|
use_external_resource_group = resource_group_name is not None
|
386
389
|
if resource_group_name is None:
|
387
390
|
resource_group_name = f'{cluster_name.name_on_cloud}-{region_name}'
|
sky/clouds/cloud.py
CHANGED
@@ -669,8 +669,11 @@ class Cloud:
|
|
669
669
|
resources)
|
670
670
|
|
671
671
|
# Docker image is not compatible with ssh proxy command.
|
672
|
-
if skypilot_config.
|
673
|
-
|
672
|
+
if skypilot_config.get_effective_region_config(
|
673
|
+
cloud=str(cls).lower(),
|
674
|
+
region=None,
|
675
|
+
keys=('ssh_proxy_command',),
|
676
|
+
default_value=None) is not None:
|
674
677
|
unsupported_features2reason.update({
|
675
678
|
CloudImplementationFeatures.DOCKER_IMAGE: (
|
676
679
|
f'Docker image is currently not supported on {cls._REPR} '
|
sky/clouds/gcp.py
CHANGED
@@ -229,9 +229,10 @@ class GCP(clouds.Cloud):
|
|
229
229
|
# TODO(zhwu): We probably need to store the MIG requirement in resources
|
230
230
|
# because `skypilot_config` may change for an existing cluster.
|
231
231
|
# Clusters created with MIG (only GPU clusters) cannot be stopped.
|
232
|
-
if (skypilot_config.
|
233
|
-
|
234
|
-
|
232
|
+
if (skypilot_config.get_effective_region_config(
|
233
|
+
cloud='gcp',
|
234
|
+
region=resources.region,
|
235
|
+
keys=('managed_instance_group',),
|
235
236
|
override_configs=resources.cluster_config_overrides) is not None
|
236
237
|
and resources.accelerators):
|
237
238
|
unsupported[clouds.CloudImplementationFeatures.STOP] = (
|
@@ -504,9 +505,11 @@ class GCP(clouds.Cloud):
|
|
504
505
|
r.instance_type,
|
505
506
|
GCP.failover_disk_tier(r.instance_type, r.disk_tier)),
|
506
507
|
}
|
507
|
-
enable_gpu_direct = skypilot_config.
|
508
|
-
|
509
|
-
|
508
|
+
enable_gpu_direct = skypilot_config.get_effective_region_config(
|
509
|
+
cloud='gcp',
|
510
|
+
region=region_name,
|
511
|
+
keys=('enable_gpu_direct',),
|
512
|
+
default_value=False,
|
510
513
|
override_configs=resources.cluster_config_overrides)
|
511
514
|
resources_vars['enable_gpu_direct'] = enable_gpu_direct
|
512
515
|
network_tier = r.network_tier
|
@@ -591,9 +594,11 @@ class GCP(clouds.Cloud):
|
|
591
594
|
|
592
595
|
resources_vars['tpu_node_name'] = tpu_node_name
|
593
596
|
|
594
|
-
managed_instance_group_config = skypilot_config.
|
595
|
-
|
596
|
-
|
597
|
+
managed_instance_group_config = skypilot_config.get_effective_region_config(
|
598
|
+
cloud='gcp',
|
599
|
+
region=region_name,
|
600
|
+
keys=('managed_instance_group',),
|
601
|
+
default_value=None,
|
597
602
|
override_configs=resources.cluster_config_overrides)
|
598
603
|
use_mig = managed_instance_group_config is not None
|
599
604
|
resources_vars['gcp_use_managed_instance_group'] = use_mig
|
@@ -604,8 +609,11 @@ class GCP(clouds.Cloud):
|
|
604
609
|
if use_mig:
|
605
610
|
resources_vars.update(managed_instance_group_config)
|
606
611
|
resources_vars[
|
607
|
-
'force_enable_external_ips'] = skypilot_config.
|
608
|
-
|
612
|
+
'force_enable_external_ips'] = skypilot_config.get_effective_region_config(
|
613
|
+
cloud='gcp',
|
614
|
+
region=region_name,
|
615
|
+
keys=('force_enable_external_ips',),
|
616
|
+
default_value=False)
|
609
617
|
|
610
618
|
volumes, device_mount_points = GCP._get_volumes_specs(
|
611
619
|
region, zones, r.instance_type, r.volumes, use_mig,
|
@@ -629,13 +637,18 @@ class GCP(clouds.Cloud):
|
|
629
637
|
device_mounts=device_mounts_str)
|
630
638
|
|
631
639
|
# Add gVNIC from config
|
632
|
-
resources_vars[
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
640
|
+
resources_vars[
|
641
|
+
'enable_gvnic'] = skypilot_config.get_effective_region_config(
|
642
|
+
cloud='gcp',
|
643
|
+
region=region_name,
|
644
|
+
keys=('enable_gvnic',),
|
645
|
+
default_value=False,
|
646
|
+
override_configs=resources.cluster_config_overrides)
|
647
|
+
placement_policy = skypilot_config.get_effective_region_config(
|
648
|
+
cloud='gcp',
|
649
|
+
region=region_name,
|
650
|
+
keys=('placement_policy',),
|
651
|
+
default_value=None,
|
639
652
|
override_configs=resources.cluster_config_overrides)
|
640
653
|
if enable_gpu_direct or network_tier == resources_utils.NetworkTier.BEST:
|
641
654
|
user_data += constants.GPU_DIRECT_TCPX_USER_DATA
|
sky/clouds/kubernetes.py
CHANGED
@@ -168,8 +168,11 @@ class Kubernetes(clouds.Cloud):
|
|
168
168
|
allowed_contexts = skypilot_config.get_workspace_cloud(
|
169
169
|
'kubernetes').get('allowed_contexts', None)
|
170
170
|
if allowed_contexts is None:
|
171
|
-
allowed_contexts = skypilot_config.
|
172
|
-
|
171
|
+
allowed_contexts = skypilot_config.get_effective_region_config(
|
172
|
+
cloud='kubernetes',
|
173
|
+
region=None,
|
174
|
+
keys=('allowed_contexts',),
|
175
|
+
default_value=None)
|
173
176
|
|
174
177
|
# Exclude contexts starting with `ssh-`
|
175
178
|
# TODO(romilb): Remove when SSH Node Pools use a separate kubeconfig.
|
@@ -254,22 +257,6 @@ class Kubernetes(clouds.Cloud):
|
|
254
257
|
if instance_type is None:
|
255
258
|
return regions
|
256
259
|
|
257
|
-
autoscaler_type = kubernetes_utils.get_autoscaler_type()
|
258
|
-
if (autoscaler_type is not None and not kubernetes_utils.get_autoscaler(
|
259
|
-
autoscaler_type).can_query_backend):
|
260
|
-
# Unsupported autoscaler type. Rely on the autoscaler to
|
261
|
-
# provision the right instance type without running checks.
|
262
|
-
# Worst case, if autoscaling fails, the pod will be stuck in
|
263
|
-
# pending state until provision_timeout, after which failover
|
264
|
-
# will be triggered.
|
265
|
-
#
|
266
|
-
# Removing this if statement produces the same behavior,
|
267
|
-
# because can_create_new_instance_of_type() always returns True
|
268
|
-
# for unsupported autoscaler types.
|
269
|
-
# This check is here as a performance optimization to avoid
|
270
|
-
# further code executions that is known to return this result.
|
271
|
-
return regions
|
272
|
-
|
273
260
|
regions_to_return = []
|
274
261
|
for r in regions:
|
275
262
|
context = r.name
|
@@ -286,6 +273,29 @@ class Kubernetes(clouds.Cloud):
|
|
286
273
|
'not fit in the existing Kubernetes cluster '
|
287
274
|
'with context: '
|
288
275
|
f'{context}. Reason: {reason}')
|
276
|
+
|
277
|
+
autoscaler_type = skypilot_config.get_effective_region_config(
|
278
|
+
cloud='kubernetes',
|
279
|
+
region=context,
|
280
|
+
keys=('autoscaler',),
|
281
|
+
default_value=None)
|
282
|
+
if (autoscaler_type is not None and
|
283
|
+
not kubernetes_utils.get_autoscaler(
|
284
|
+
autoscaler_type).can_query_backend):
|
285
|
+
# Unsupported autoscaler type. Rely on the autoscaler to
|
286
|
+
# provision the right instance type without running checks.
|
287
|
+
# Worst case, if autoscaling fails, the pod will be stuck in
|
288
|
+
# pending state until provision_timeout, after which failover
|
289
|
+
# will be triggered.
|
290
|
+
#
|
291
|
+
# Removing this if statement produces the same behavior,
|
292
|
+
# because can_create_new_instance_of_type() always returns True
|
293
|
+
# for unsupported autoscaler types.
|
294
|
+
# This check is here as a performance optimization to avoid
|
295
|
+
# further code executions that is known to return this result.
|
296
|
+
regions_to_return.append(r)
|
297
|
+
continue
|
298
|
+
|
289
299
|
if autoscaler_type is None:
|
290
300
|
continue
|
291
301
|
autoscaler = kubernetes_utils.get_autoscaler(autoscaler_type)
|
@@ -532,11 +542,13 @@ class Kubernetes(clouds.Cloud):
|
|
532
542
|
context)
|
533
543
|
if len(avoid_label_keys) == 0:
|
534
544
|
avoid_label_keys = None
|
535
|
-
port_mode = network_utils.get_port_mode(None)
|
545
|
+
port_mode = network_utils.get_port_mode(None, context)
|
536
546
|
|
537
|
-
remote_identity = skypilot_config.
|
538
|
-
|
539
|
-
|
547
|
+
remote_identity = skypilot_config.get_effective_region_config(
|
548
|
+
cloud='kubernetes',
|
549
|
+
region=context,
|
550
|
+
keys=('remote_identity',),
|
551
|
+
default_value=schemas.get_default_remote_identity('kubernetes'))
|
540
552
|
|
541
553
|
if isinstance(remote_identity, dict):
|
542
554
|
# If remote_identity is a dict, use the service account for the
|
@@ -580,9 +592,11 @@ class Kubernetes(clouds.Cloud):
|
|
580
592
|
# number of nodes.
|
581
593
|
|
582
594
|
timeout = self._calculate_provision_timeout(num_nodes, volume_mounts)
|
583
|
-
timeout = skypilot_config.
|
584
|
-
|
585
|
-
|
595
|
+
timeout = skypilot_config.get_effective_region_config(
|
596
|
+
cloud='kubernetes',
|
597
|
+
region=context,
|
598
|
+
keys=('provision_timeout',),
|
599
|
+
default_value=timeout,
|
586
600
|
override_configs=resources.cluster_config_overrides)
|
587
601
|
|
588
602
|
# Check if this cluster supports high performance networking and
|
@@ -614,15 +628,20 @@ class Kubernetes(clouds.Cloud):
|
|
614
628
|
}
|
615
629
|
|
616
630
|
# Get the storage class name for high availability controller's PVC
|
617
|
-
k8s_ha_storage_class_name =
|
618
|
-
(
|
619
|
-
|
620
|
-
|
631
|
+
k8s_ha_storage_class_name = (
|
632
|
+
skypilot_config.get_effective_region_config(
|
633
|
+
cloud='kubernetes',
|
634
|
+
region=context,
|
635
|
+
keys=('high_availability', 'storage_class_name'),
|
636
|
+
default_value=None))
|
637
|
+
|
638
|
+
k8s_kueue_local_queue_name = (
|
639
|
+
skypilot_config.get_effective_region_config(
|
640
|
+
cloud='kubernetes',
|
641
|
+
region=context,
|
642
|
+
keys=('kueue', 'local_queue_name'),
|
643
|
+
default_value=None))
|
621
644
|
|
622
|
-
k8s_kueue_local_queue_name = skypilot_config.get_nested(
|
623
|
-
('kubernetes', 'kueue', 'local_queue_name'),
|
624
|
-
None,
|
625
|
-
override_configs=resources.cluster_config_overrides)
|
626
645
|
deploy_vars = {
|
627
646
|
'instance_type': resources.instance_type,
|
628
647
|
'custom_resources': custom_resources,
|
@@ -631,7 +650,8 @@ class Kubernetes(clouds.Cloud):
|
|
631
650
|
'accelerator_count': str(acc_count),
|
632
651
|
'timeout': str(timeout),
|
633
652
|
'k8s_port_mode': port_mode.value,
|
634
|
-
'k8s_networking_mode': network_utils.get_networking_mode(
|
653
|
+
'k8s_networking_mode': network_utils.get_networking_mode(
|
654
|
+
None, context=context).value,
|
635
655
|
'k8s_ssh_key_secret_name': self.SKY_SSH_KEY_SECRET_NAME,
|
636
656
|
'k8s_acc_label_key': k8s_acc_label_key,
|
637
657
|
'k8s_acc_label_values': k8s_acc_label_values,
|
sky/clouds/nebius.py
CHANGED
@@ -224,8 +224,14 @@ class Nebius(clouds.Cloud):
|
|
224
224
|
raise RuntimeError('Unsupported instance type for Nebius cloud:'
|
225
225
|
f' {resources.instance_type}')
|
226
226
|
|
227
|
-
config_fs = skypilot_config.
|
228
|
-
|
227
|
+
config_fs = skypilot_config.get_effective_region_config(
|
228
|
+
cloud='nebius',
|
229
|
+
region=None,
|
230
|
+
keys=(
|
231
|
+
region.name,
|
232
|
+
'filesystems',
|
233
|
+
),
|
234
|
+
default_value=[])
|
229
235
|
resources_vars_fs = []
|
230
236
|
for i, fs in enumerate(config_fs):
|
231
237
|
resources_vars_fs.append({
|
sky/clouds/ssh.py
CHANGED
@@ -143,8 +143,11 @@ class SSH(kubernetes.Kubernetes):
|
|
143
143
|
allowed_node_pools = skypilot_config.get_workspace_cloud('ssh').get(
|
144
144
|
'allowed_node_pools', None)
|
145
145
|
if allowed_node_pools is None:
|
146
|
-
allowed_node_pools = skypilot_config.
|
147
|
-
|
146
|
+
allowed_node_pools = skypilot_config.get_effective_region_config(
|
147
|
+
cloud='ssh',
|
148
|
+
region=None,
|
149
|
+
keys=('allowed_node_pools',),
|
150
|
+
default_value=None)
|
148
151
|
|
149
152
|
# Filter for SSH contexts (those starting with 'ssh-')
|
150
153
|
ssh_contexts = [
|
sky/clouds/utils/aws_utils.py
CHANGED
@@ -28,10 +28,16 @@ class AWSReservation:
|
|
28
28
|
|
29
29
|
|
30
30
|
def use_reservations() -> bool:
|
31
|
-
prioritize_reservations = skypilot_config.
|
32
|
-
|
33
|
-
|
34
|
-
('
|
31
|
+
prioritize_reservations = skypilot_config.get_effective_region_config(
|
32
|
+
cloud='aws',
|
33
|
+
region=None,
|
34
|
+
keys=('prioritize_reservations',),
|
35
|
+
default_value=False)
|
36
|
+
specific_reservations = skypilot_config.get_effective_region_config(
|
37
|
+
cloud='aws',
|
38
|
+
region=None,
|
39
|
+
keys=('specific_reservations',),
|
40
|
+
default_value=set())
|
35
41
|
return prioritize_reservations or specific_reservations
|
36
42
|
|
37
43
|
|
sky/clouds/utils/gcp_utils.py
CHANGED
@@ -137,10 +137,16 @@ def _list_reservations_for_instance_type(
|
|
137
137
|
For example, if we have a specific reservation with n1-highmem-8
|
138
138
|
in us-central1-c. `sky launch --gpus V100` will fail.
|
139
139
|
"""
|
140
|
-
prioritize_reservations = skypilot_config.
|
141
|
-
|
142
|
-
|
143
|
-
('
|
140
|
+
prioritize_reservations = skypilot_config.get_effective_region_config(
|
141
|
+
cloud='gcp',
|
142
|
+
region=None,
|
143
|
+
keys=('prioritize_reservations',),
|
144
|
+
default_value=False)
|
145
|
+
specific_reservations = skypilot_config.get_effective_region_config(
|
146
|
+
cloud='gcp',
|
147
|
+
region=None,
|
148
|
+
keys=('specific_reservations',),
|
149
|
+
default_value=[])
|
144
150
|
if not prioritize_reservations and not specific_reservations:
|
145
151
|
return []
|
146
152
|
logger.debug(f'Querying GCP reservations for instance {instance_type!r}')
|
@@ -170,14 +176,23 @@ def _list_reservations_for_instance_type(
|
|
170
176
|
|
171
177
|
def get_minimal_compute_permissions() -> List[str]:
|
172
178
|
permissions = copy.copy(constants.VM_MINIMAL_PERMISSIONS)
|
173
|
-
if skypilot_config.
|
179
|
+
if skypilot_config.get_effective_region_config(
|
180
|
+
cloud='gcp', region=None, keys=('vpc_name',),
|
181
|
+
default_value=None) is None:
|
174
182
|
# If custom VPC is not specified, permissions to modify network are
|
175
183
|
# required to ensure SkyPilot to be able to setup the network, and
|
176
184
|
# allow opening ports (e.g., via `resources.ports`).
|
177
185
|
permissions += constants.FIREWALL_PERMISSIONS
|
178
186
|
|
179
|
-
if (skypilot_config.
|
180
|
-
|
187
|
+
if (skypilot_config.get_effective_region_config(
|
188
|
+
cloud='gcp',
|
189
|
+
region=None,
|
190
|
+
keys=('prioritize_reservations',),
|
191
|
+
default_value=False) or skypilot_config.get_effective_region_config(
|
192
|
+
cloud='gcp',
|
193
|
+
region=None,
|
194
|
+
keys=('specific_reservations',),
|
195
|
+
default_value=[])):
|
181
196
|
permissions += constants.RESERVATION_PERMISSIONS
|
182
197
|
|
183
198
|
permissions += constants.GCP_MINIMAL_PERMISSIONS
|
sky/clouds/utils/oci_utils.py
CHANGED
@@ -105,22 +105,46 @@ class OCIConfig:
|
|
105
105
|
@classmethod
|
106
106
|
def get_compartment(cls, region):
|
107
107
|
# Allow task(cluster)-specific compartment/VCN parameters.
|
108
|
-
default_compartment_ocid = skypilot_config.
|
109
|
-
|
110
|
-
|
111
|
-
(
|
108
|
+
default_compartment_ocid = skypilot_config.get_effective_region_config(
|
109
|
+
cloud='oci',
|
110
|
+
region=None,
|
111
|
+
keys=(
|
112
|
+
'default',
|
113
|
+
'compartment_ocid',
|
114
|
+
),
|
115
|
+
default_value=None)
|
116
|
+
compartment = skypilot_config.get_effective_region_config(
|
117
|
+
cloud='oci',
|
118
|
+
region=None,
|
119
|
+
keys=(
|
120
|
+
region,
|
121
|
+
'compartment_ocid',
|
122
|
+
),
|
123
|
+
default_value=default_compartment_ocid)
|
112
124
|
return compartment
|
113
125
|
|
114
126
|
@classmethod
|
115
127
|
def get_vcn_ocid(cls, region):
|
116
128
|
# Will reuse the regional VCN if specified.
|
117
|
-
vcn = skypilot_config.
|
129
|
+
vcn = skypilot_config.get_effective_region_config(cloud='oci',
|
130
|
+
region=None,
|
131
|
+
keys=(
|
132
|
+
region,
|
133
|
+
'vcn_ocid',
|
134
|
+
),
|
135
|
+
default_value=None)
|
118
136
|
return vcn
|
119
137
|
|
120
138
|
@classmethod
|
121
139
|
def get_vcn_subnet(cls, region):
|
122
140
|
# Will reuse the subnet if specified.
|
123
|
-
vcn = skypilot_config.
|
141
|
+
vcn = skypilot_config.get_effective_region_config(cloud='oci',
|
142
|
+
region=None,
|
143
|
+
keys=(
|
144
|
+
region,
|
145
|
+
'vcn_subnet',
|
146
|
+
),
|
147
|
+
default_value=None)
|
124
148
|
return vcn
|
125
149
|
|
126
150
|
@classmethod
|
@@ -129,16 +153,28 @@ class OCIConfig:
|
|
129
153
|
# we give a choice to set the default image tag (for gpu instances) in
|
130
154
|
# the sky's user-config file (if not specified, use the hardcode one at
|
131
155
|
# last)
|
132
|
-
return skypilot_config.
|
133
|
-
|
156
|
+
return skypilot_config.get_effective_region_config(
|
157
|
+
cloud='oci',
|
158
|
+
region=None,
|
159
|
+
keys=(
|
160
|
+
'default',
|
161
|
+
'image_tag_gpu',
|
162
|
+
),
|
163
|
+
default_value='skypilot:gpu-ubuntu-2204')
|
134
164
|
|
135
165
|
@classmethod
|
136
166
|
def get_default_image_tag(cls) -> str:
|
137
167
|
# Get the default image tag. Instead of hardcoding, we give a choice to
|
138
168
|
# set the default image tag in the sky's user-config file. (if not
|
139
169
|
# specified, use the hardcode one at last)
|
140
|
-
return skypilot_config.
|
141
|
-
|
170
|
+
return skypilot_config.get_effective_region_config(
|
171
|
+
cloud='oci',
|
172
|
+
region=None,
|
173
|
+
keys=(
|
174
|
+
'default',
|
175
|
+
'image_tag_general',
|
176
|
+
),
|
177
|
+
default_value='skypilot:cpu-ubuntu-2204')
|
142
178
|
|
143
179
|
@classmethod
|
144
180
|
def get_sky_user_config_file(cls) -> str:
|
@@ -152,16 +188,28 @@ class OCIConfig:
|
|
152
188
|
|
153
189
|
@classmethod
|
154
190
|
def get_profile(cls) -> str:
|
155
|
-
return skypilot_config.
|
156
|
-
|
191
|
+
return skypilot_config.get_effective_region_config(
|
192
|
+
cloud='oci',
|
193
|
+
region=None,
|
194
|
+
keys=(
|
195
|
+
'default',
|
196
|
+
'oci_config_profile',
|
197
|
+
),
|
198
|
+
default_value='DEFAULT')
|
157
199
|
|
158
200
|
@classmethod
|
159
201
|
def get_default_image_os(cls) -> str:
|
160
202
|
# Get the default image OS. Instead of hardcoding, we give a choice to
|
161
203
|
# set the default image OS type in the sky's user-config file. (if not
|
162
204
|
# specified, use the hardcode one at last)
|
163
|
-
return skypilot_config.
|
164
|
-
|
205
|
+
return skypilot_config.get_effective_region_config(
|
206
|
+
cloud='oci',
|
207
|
+
region=None,
|
208
|
+
keys=(
|
209
|
+
'default',
|
210
|
+
'image_os_type',
|
211
|
+
),
|
212
|
+
default_value='ubuntu')
|
165
213
|
|
166
214
|
|
167
215
|
oci_config = OCIConfig()
|
sky/dashboard/out/404.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/605ac87514049058.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/605ac87514049058.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-75a3310ef922a299.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-050a9e637b057b24.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/ZYLkkWSYZjJhLVsObh20y/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"ZYLkkWSYZjJhLVsObh20y","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/_next/static/{HudU4f4Xsy-cP51JvXSZ- → ZYLkkWSYZjJhLVsObh20y}/_buildManifest.js
RENAMED
@@ -1 +1 @@
|
|
1
|
-
self.__BUILD_MANIFEST=function(s,c,e,a,t,u,n,r,b,
|
1
|
+
self.__BUILD_MANIFEST=function(s,c,e,a,t,u,n,r,i,b,j,k,f,o){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-6b0d9e5031b70c58.js"],"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],"/clusters":["static/chunks/pages/clusters-65b2c90320b8afb8.js"],"/clusters/[cluster]":[s,c,e,a,t,r,b,u,n,j,i,k,f,o,"static/chunks/871-e547295e7e21399c.js","static/chunks/pages/clusters/[cluster]-77d4816945b04793.js"],"/clusters/[cluster]/[job]":[s,c,e,a,t,u,n,"static/chunks/pages/clusters/[cluster]/[job]-21080826c6095f21.js"],"/config":["static/chunks/pages/config-6b255eae088da6a3.js"],"/infra":["static/chunks/pages/infra-ee8cc4d449945d19.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-b302aea4d65766bf.js"],"/jobs":["static/chunks/pages/jobs-df7407b5e37d3750.js"],"/jobs/[job]":[s,c,e,a,t,r,u,n,i,"static/chunks/pages/jobs/[job]-64bdc0b2d3a44709.js"],"/users":["static/chunks/pages/users-d7684eaa04c4f58f.js"],"/volumes":["static/chunks/pages/volumes-476b670ef33d1ecd.js"],"/workspace/new":["static/chunks/pages/workspace/new-5b59bce9eb208d84.js"],"/workspaces":["static/chunks/pages/workspaces-c470366a6179f16e.js"],"/workspaces/[name]":[s,c,e,a,t,r,b,u,n,j,i,k,f,o,"static/chunks/141-fa5a20cbf401b351.js","static/chunks/pages/workspaces/[name]-04e1b3ad4207b1e9.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/[job]","/users","/volumes","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-50a620ac4a23deb4.js","static/chunks/230-d6e363362017ff3a.js","static/chunks/799-3625946b2ec2eb30.js","static/chunks/664-047bc03493fda379.js","static/chunks/804-4c9fc53aa74bc191.js","static/chunks/989-db34c16ad7ea6155.js","static/chunks/470-92dd1614396389be.js","static/chunks/798-c0525dc3f21e488d.js","static/chunks/969-d3a0b53f728d280a.js","static/chunks/947-6620842ef80ae879.js","static/chunks/990-0ad5ea1699e03ee8.js","static/chunks/43-f38a531f6692f281.js","static/chunks/601-111d06d9ded11d00.js","static/chunks/938-0a770415b5ce4649.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[43],{326:function(e,t,a){a.d(t,{$N:function(){return p},Be:function(){return _},Vq:function(){return c},cN:function(){return f},cZ:function(){return d},fK:function(){return g}});var r=a(5893),s=a(7294),o=a(6327),n=a(2350),l=a(3767);let c=o.fC;o.xz;let u=o.h_;o.x8;let i=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.aV,{ref:t,className:(0,n.cn)("fixed inset-0 z-50 bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",a),...s})});i.displayName=o.aV.displayName;let d=s.forwardRef((e,t)=>{let{className:a,children:s,...c}=e;return(0,r.jsxs)(u,{children:[(0,r.jsx)(i,{}),(0,r.jsxs)(o.VY,{ref:t,className:(0,n.cn)("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-gray-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",a),...c,children:[s,(0,r.jsxs)(o.x8,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-gray-100 data-[state=open]:text-gray-500",children:[(0,r.jsx)(l.Z,{className:"h-4 w-4"}),(0,r.jsx)("span",{className:"sr-only",children:"Close"})]})]})]})});d.displayName=o.VY.displayName;let g=e=>{let{className:t,...a}=e;return(0,r.jsx)("div",{className:(0,n.cn)("flex flex-col space-y-1.5 text-center sm:text-left",t),...a})};g.displayName="DialogHeader";let f=e=>{let{className:t,...a}=e;return(0,r.jsx)("div",{className:(0,n.cn)("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...a})};f.displayName="DialogFooter";let p=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.Dx,{ref:t,className:(0,n.cn)("text-lg font-semibold leading-none tracking-tight",a),...s})});p.displayName=o.Dx.displayName;let _=s.forwardRef((e,t)=>{let{className:a,...s}=e;return(0,r.jsx)(o.dk,{ref:t,className:(0,n.cn)("text-sm text-gray-500",a),...s})});_.displayName=o.dk.displayName},3266:function(e,t,a){a.d(t,{QL:function(){return g},Sl:function(){return i},getClusters:function(){return c},uR:function(){return u}});var r=a(7294),s=a(5821),o=a(7145),n=a(6378);let l={UP:"RUNNING",STOPPED:"STOPPED",INIT:"LAUNCHING",null:"TERMINATED"};async function c(){let{clusterNames:e=null}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{return(await o.x.fetch("/status",{cluster_names:e,all_users:!0})).map(e=>{let t="",a=t=e.zone?e.zone:e.region;return t&&t.length>25&&(t=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:15;if(!e||e.length<=t)return e;if(t<=3)return"...";let a=Math.floor((t-3)/2),r=a+(t-3)%2;return 0===a?e.substring(0,r)+"...":e.substring(0,r)+"..."+e.substring(e.length-a)}(t,25)),{status:l[e.status],cluster:e.name,user:e.user_name,user_hash:e.user_hash,cloud:e.cloud,region:e.region,infra:t?e.cloud+" ("+t+")":e.cloud,full_infra:a?"".concat(e.cloud," (").concat(a,")"):e.cloud,cpus:e.cpus,mem:e.memory,gpus:e.accelerators,resources_str:e.resources_str,resources_str_full:e.resources_str_full,time:new Date(1e3*e.launched_at),num_nodes:e.nodes,workspace:e.workspace,autostop:e.autostop,to_down:e.to_down,jobs:[],command:e.last_creation_command||e.last_use,task_yaml:e.last_creation_yaml||"{}",events:[{time:new Date(1e3*e.launched_at),event:"Cluster created."}]}})}catch(e){return console.error("Error fetching clusters:",e),[]}}async function u(){try{let e=await o.x.fetch("/cost_report",{days:30});console.log("Raw cluster history data:",e);let t=e.map(e=>{let t="Unknown";e.cloud?t=e.cloud:e.resources&&e.resources.cloud&&(t=e.resources.cloud);let a=e.user_name||"-";return{status:e.status?l[e.status]:"TERMINATED",cluster:e.name,user:a,user_hash:e.user_hash,cloud:t,region:"",infra:t,full_infra:t,resources_str:e.resources_str,resources_str_full:e.resources_str_full,time:e.launched_at?new Date(1e3*e.launched_at):null,num_nodes:e.num_nodes||1,duration:e.duration,total_cost:e.total_cost,workspace:e.workspace||"default",autostop:-1,to_down:!1,cluster_hash:e.cluster_hash,usage_intervals:e.usage_intervals,command:e.last_creation_command||"",task_yaml:e.last_creation_yaml||"{}",events:[{time:e.launched_at?new Date(1e3*e.launched_at):new Date,event:"Cluster created."}]}});return console.log("Processed cluster history data:",t),t}catch(e){return console.error("Error fetching cluster history:",e),[]}}async function i(e){let{clusterName:t,jobId:a,onNewLog:r,workspace:n}=e;try{await o.x.stream("/logs",{follow:!1,cluster_name:t,job_id:a,override_skypilot_config:{active_workspace:n||"default"}},r)}catch(e){console.error("Error in streamClusterJobLogs:",e),(0,s.C)("Error in streamClusterJobLogs: ".concat(e.message),"error")}}async function d(e){let{clusterName:t,workspace:a}=e;try{return(await o.x.fetch("/queue",{cluster_name:t,all_users:!0,override_skypilot_config:{active_workspace:a}})).map(e=>{let r=e.end_at?e.end_at:Date.now()/1e3,s=0,o=0;return e.submitted_at&&(s=r-e.submitted_at),e.start_at&&(o=r-e.start_at),{id:e.job_id,status:e.status,job:e.job_name,user:e.username,user_hash:e.user_hash,gpus:e.accelerators||{},submitted_at:e.submitted_at?new Date(1e3*e.submitted_at):null,resources:e.resources,cluster:t,total_duration:s,job_duration:o,infra:"",logs:"",workspace:a||"default"}})}catch(e){return console.error("Error fetching cluster jobs:",e),[]}}function g(e){let{cluster:t,job:a=null}=e,[s,o]=(0,r.useState)(null),[l,u]=(0,r.useState)(null),[i,g]=(0,r.useState)(!0),[f,p]=(0,r.useState)(!0),_=(0,r.useCallback)(async()=>{if(t)try{g(!0);let e=await n.default.get(c,[{clusterNames:[t]}]);return o(e[0]),e[0]}catch(e){console.error("Error fetching cluster data:",e)}finally{g(!1)}return null},[t]),h=(0,r.useCallback)(async e=>{if(t)try{p(!0);let a=await n.default.get(d,[{clusterName:t,workspace:e||"default"}]);u(a)}catch(e){console.error("Error fetching cluster job data:",e)}finally{p(!1)}},[t]),m=(0,r.useCallback)(async()=>{n.default.invalidate(c,[{clusterNames:[t]}]);let e=await _();e&&(n.default.invalidate(d,[{clusterName:t,workspace:e.workspace||"default"}]),await h(e.workspace))},[_,h,t]),b=(0,r.useCallback)(async()=>{s&&(n.default.invalidate(d,[{clusterName:t,workspace:s.workspace||"default"}]),await h(s.workspace))},[h,s,t]);return(0,r.useEffect)(()=>{(async()=>{let e=await _();e&&h(e.workspace)})()},[t,a,_,h]),{clusterData:s,clusterJobData:l,loading:i,clusterDetailsLoading:i,clusterJobsLoading:f,refreshData:m,refreshClusterJobsOnly:b}}},2045:function(e,t,a){a.d(t,{l4:function(){return n}});var r=a(3225),s=a(7145);async function o(e,t){try{let a=[];try{let e=await s.x.get("/enabled_clouds"),t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("X-Request-ID"),r=await s.x.get("/api/get?request_id=".concat(t)),o=await r.json();a=o.return_value?JSON.parse(o.return_value):[],console.log("Enabled clouds:",a)}catch(e){console.error("Error fetching enabled clouds:",e),a=[]}let o={};r.$m.forEach(e=>{let t=a.includes(e.toLowerCase());o[e]={name:e,clusters:0,jobs:0,enabled:t}}),e.forEach(e=>{if(e.cloud){let t=e.cloud;o[t]&&(o[t].clusters+=1,o[t].enabled=!0)}}),t.forEach(e=>{if(e.cloud){let t=e.cloud;o[t]&&(o[t].jobs+=1,o[t].enabled=!0)}});let n=r.$m.length,l=Object.values(o).filter(e=>e.enabled).length;return{clouds:Object.values(o).filter(e=>e.enabled).sort((e,t)=>t.clusters-e.clusters||t.jobs-e.jobs),totalClouds:n,enabledClouds:l}}catch(e){return console.error("Error fetching cloud infrastructure:",e),{clouds:[],totalClouds:r.$m.length,enabledClouds:0}}}async function n(){let{getClusters:e}=await Promise.resolve().then(a.bind(a,3266)),{getManagedJobs:t}=await Promise.resolve().then(a.bind(a,8969)),r=(await Promise.resolve().then(a.bind(a,6378))).default,[s,n]=await Promise.all([r.get(e),r.get(t,[{allUsers:!0}])]),c=s||[],u=(null==n?void 0:n.jobs)||[],[i,d]=await Promise.all([l(c,u),o(c,u)]);return{gpuData:i,cloudData:d}}async function l(e,t){return await g({clusters:e||[],jobs:t||[]})}async function c(){try{let e=await s.x.post("/realtime_kubernetes_gpu_availability",{context:null,name_filter:null,quantity_filter:null});if(!e.ok)return console.error("Error fetching Kubernetes context GPUs (in getKubernetesContextGPUs): ".concat(e.status," ").concat(e.statusText)),[];let t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("x-request-id");if(!t)return console.error("No request ID returned for Kubernetes GPU availability (in getKubernetesContextGPUs)"),[];let a=await s.x.get("/api/get?request_id=".concat(t)),r=await a.text();if(500===a.status){try{let e=JSON.parse(r);if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);console.error("[infra.jsx] getKubernetesContextGPUs: Server error detail:",t.message)}catch(t){console.error("[infra.jsx] getKubernetesContextGPUs: Error parsing server error JSON:",t,"Original error text:",e.detail.error)}}catch(e){console.error("[infra.jsx] getKubernetesContextGPUs: Error parsing 500 error response JSON:",e,"Raw text was:",r)}return[]}let o=JSON.parse(r);return o.return_value?JSON.parse(o.return_value):[]}catch(e){return console.error("[infra.jsx] Outer error in getKubernetesContextGPUs:",e),[]}}async function u(){try{let e=await s.x.get("/all_contexts");if(!e.ok)return console.error("Error fetching all contexts: ".concat(e.status," ").concat(e.statusText)),[];let t=e.headers.get("X-Skypilot-Request-ID")||e.headers.get("x-request-id");if(!t)return console.error("No request ID returned for /all_contexts"),[];let a=await s.x.get("/api/get?request_id=".concat(t)),r=await a.json();return r.return_value?JSON.parse(r.return_value):[]}catch(e){return console.error("[infra.jsx] Error in getAllContexts:",e),[]}}async function i(e){try{let t=await s.x.post("/kubernetes_node_info",{context:e}),a=t.headers.get("X-Skypilot-Request-ID")||t.headers.get("x-request-id"),r=await s.x.get("/api/get?request_id=".concat(a));if(500===r.status){try{let e=await r.json();if(e.detail&&e.detail.error)try{let t=JSON.parse(e.detail.error);console.error("Error fetching Kubernetes per node GPUs:",t.message)}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{}}let o=await r.json();return(o.return_value?JSON.parse(o.return_value):{}).node_info_dict||{}}catch(t){return console.error("[infra.jsx] Error in getKubernetesPerNodeGPUs for context",e,":",t),{}}}async function d(e){try{let t=e.clusters,a=e.jobs,r={};return t.forEach(e=>{let t=null;if("Kubernetes"===e.cloud)(t=e.region)&&(t="kubernetes/".concat(t));else if("SSH"===e.cloud&&(t=e.region)){let e=t.startsWith("ssh-")?t.substring(4):t;t="ssh/".concat(e)}t&&(r[t]||(r[t]={clusters:0,jobs:0}),r[t].clusters+=1)}),a.forEach(e=>{let t=null;if("Kubernetes"===e.cloud)(t=e.region)&&(t="kubernetes/".concat(t));else if("SSH"===e.cloud&&(t=e.region)){let e=t.startsWith("ssh-")?t.substring(4):t;t="ssh/".concat(e)}t&&(r[t]||(r[t]={clusters:0,jobs:0}),r[t].jobs+=1)}),r}catch(e){return console.error("=== Error in getContextClustersAndJobs ===",e),{}}}async function g(e){try{let o=await u();if(!o||0===o.length)return console.log("No contexts found from /all_contexts endpoint."),{allContextNames:[],allGPUs:[],perContextGPUs:[],perNodeGPUs:[],contextStats:{}};let n=await d(e),l=await c(),g=new Map;l&&l.forEach(e=>{g.set(e[0],e[1])});let f={},p={},_={};for(let e of o){p[e]||(p[e]=[]);let o=g.get(e);if(o&&o.length>0)for(let t of o){let a=t[0],r=t[1].join(", "),s=t[2],o=t[3];a in f?(f[a].gpu_total+=s,f[a].gpu_free+=o):f[a]={gpu_total:s,gpu_free:o,gpu_name:a},p[e].push({gpu_name:a,gpu_requestable_qty_per_node:r,gpu_total:s,gpu_free:o,context:e})}let n=await i(e);if(n&&Object.keys(n).length>0)for(let o in n){var t,a,r,s;let l=n[o],c=l.accelerator_type||"-",u=null!==(r=null===(t=l.total)||void 0===t?void 0:t.accelerator_count)&&void 0!==r?r:0,i=null!==(s=null===(a=l.free)||void 0===a?void 0:a.accelerators_available)&&void 0!==s?s:0;_["".concat(e,"/").concat(o)]={node_name:l.name,gpu_name:c,gpu_total:u,gpu_free:i,ip_address:l.ip_address||null,context:e},"-"===c||p[e].some(e=>e.gpu_name===c)||(c in f||(f[c]={gpu_total:0,gpu_free:0,gpu_name:c}),p[e].find(e=>e.gpu_name===c)||p[e].push({gpu_name:c,gpu_requestable_qty_per_node:"-",gpu_total:0,gpu_free:0,context:e}))}0===p[e].length&&n&&Object.keys(n).length}return{allContextNames:o.sort(),allGPUs:Object.values(f).sort((e,t)=>e.gpu_name.localeCompare(t.gpu_name)),perContextGPUs:Object.values(p).flat().sort((e,t)=>e.context.localeCompare(t.context)||e.gpu_name.localeCompare(t.gpu_name)),perNodeGPUs:Object.values(_).sort((e,t)=>e.context.localeCompare(t.context)||e.node_name.localeCompare(t.node_name)||e.gpu_name.localeCompare(t.gpu_name)),contextStats:n}}catch(e){return console.error("[infra.jsx] Outer error in getKubernetesGPUs:",e),{allContextNames:[],allGPUs:[],perContextGPUs:[],perNodeGPUs:[],contextStats:{}}}}},3081:function(e,t,a){a.d(t,{R:function(){return s}}),a(3266),a(8969);var r=a(7145);async function s(){try{let e=await r.x.get("/users");if(!e.ok)throw Error("HTTP error! status: ".concat(e.status));return(await e.json()).map(e=>({userId:e.id,username:e.name,role:e.role}))||[]}catch(e){return console.error("Failed to fetch users:",e),[]}}},6856:function(e,t,a){var r=a(6378),s=a(3266),o=a(8969),n=a(7324),l=a(3081),c=a(2045);let u={base:{getClusters:{fn:s.getClusters,args:[]},getClusterHistory:{fn:s.uR,args:[]},getManagedJobs:{fn:o.getManagedJobs,args:[{allUsers:!0}]},getWorkspaces:{fn:n.fX,args:[]},getUsers:{fn:l.R,args:[]},getInfraData:{fn:c.l4,args:[]}},dynamic:{getEnabledClouds:{fn:n.yz,requiresWorkspaces:!0}},pages:{clusters:["getClusters","getClusterHistory","getWorkspaces","getUsers"],jobs:["getManagedJobs","getClusters","getWorkspaces","getUsers"],infra:["getInfraData","getClusters","getManagedJobs"],workspaces:["getWorkspaces","getClusters","getManagedJobs","getEnabledClouds"],users:["getUsers","getClusters","getManagedJobs"]}};class i{async preloadForPage(e,t){let{backgroundPreload:a=!0,force:r=!1}=t||{};if(!u.pages[e]){console.warn("Unknown page: ".concat(e));return}console.log("[CachePreloader] Preloading cache for page: ".concat(e));try{await this._loadPageData(e,r),a&&this._backgroundPreloadOtherPages(e)}catch(t){console.error("[CachePreloader] Error preloading for page ".concat(e,":"),t)}}async _loadPageData(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=u.pages[e],s=[];for(let e of a)if(u.base[e]){let{fn:a,args:o}=u.base[e];t&&r.default.invalidate(a,o),s.push(r.default.get(a,o))}else"getEnabledClouds"===e&&s.push(this._loadEnabledCloudsForAllWorkspaces(t));await Promise.allSettled(s),console.log("[CachePreloader] Loaded data for page: ".concat(e))}async _loadEnabledCloudsForAllWorkspaces(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];try{e&&r.default.invalidate(n.fX);let t=await r.default.get(n.fX),a=Object.keys(t||{}).map(t=>(e&&r.default.invalidate(n.yz,[t]),r.default.get(n.yz,[t])));await Promise.allSettled(a)}catch(e){console.error("[CachePreloader] Error loading enabled clouds:",e)}}_backgroundPreloadOtherPages(e){if(this.isPreloading)return;this.isPreloading=!0;let t=Object.keys(u.pages).filter(t=>t!==e);console.log("[CachePreloader] Background preloading pages: ".concat(t.join(", "))),Promise.allSettled(t.map(async e=>{try{await this._loadPageData(e,!1),console.log("[CachePreloader] Background loaded: ".concat(e))}catch(t){console.error("[CachePreloader] Background load failed for ".concat(e,":"),t)}})).then(()=>{this.isPreloading=!1,console.log("[CachePreloader] Background preloading complete")})}async preloadBaseFunctions(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];console.log("[CachePreloader] Preloading all base functions");let t=Object.entries(u.base).map(t=>{let[a,{fn:s,args:o}]=t;return e&&r.default.invalidate(s,o),r.default.get(s,o).catch(e=>{console.error("[CachePreloader] Failed to preload ".concat(a,":"),e)})});await Promise.allSettled(t),console.log("[CachePreloader] Base functions preloaded")}getCacheStats(){return{...r.default.getStats(),isPreloading:this.isPreloading}}clearCache(){r.default.clear(),this.isPreloading=!1,this.preloadPromises.clear(),console.log("[CachePreloader] Cache cleared")}constructor(){this.isPreloading=!1,this.preloadPromises=new Map}}let d=new i;t.ZP=d}}]);
|