skypilot-nightly 1.0.0.dev20250526__py3-none-any.whl → 1.0.0.dev20250527__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/check.py +28 -5
- sky/cli.py +5 -22
- sky/client/cli.py +5 -22
- sky/client/sdk.py +5 -2
- sky/clouds/cloud.py +2 -2
- sky/clouds/kubernetes.py +10 -5
- sky/clouds/service_catalog/kubernetes_catalog.py +4 -0
- sky/clouds/ssh.py +24 -8
- sky/core.py +20 -2
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_buildManifest.js +1 -0
- sky/dashboard/out/_next/static/chunks/236-e220ba0c35bf089e.js +6 -0
- sky/dashboard/out/_next/static/chunks/{498-d7722313e5e5b4e6.js → 320-afea3ddcc5bd1c6c.js} +1 -16
- sky/dashboard/out/_next/static/chunks/{480-5a0de8b6570ea105.js → 470-1d784f5c8750744a.js} +1 -1
- sky/dashboard/out/_next/static/chunks/627-31b701e69f52db0c.js +1 -0
- sky/dashboard/out/_next/static/chunks/843-e35d71cf1c7f706e.js +11 -0
- sky/dashboard/out/_next/static/chunks/990-f85643b521f7ca65.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-339b59921ccfe266.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-e23fcddf60578a0d.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/{clusters-9e6d1ec6e1ac5b29.js → clusters-8afda8efa5b74997.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/config-72b8c6c2edfd0e39.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/infra-1521baab6992916b.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-4d913940b4fa6f5a.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs-ff7e8e377d02b651.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/users-9900af52acf8648d.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/workspace/{new-bbf436f41381e169.js → new-63763ffa3edb4508.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-7733c960685b4385.js → [name]-3ede7a13caf23375.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-72330c4d0fc9a4a2.js +1 -0
- sky/dashboard/out/_next/static/css/6a1c0d711a4bdaf1.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 -0
- sky/dashboard/out/index.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/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/server/constants.py +1 -1
- sky/server/requests/payloads.py +18 -5
- sky/server/requests/serializers/decoders.py +0 -11
- sky/server/server.py +19 -9
- sky/skypilot_config.py +4 -0
- sky/utils/kubernetes/exec_kubeconfig_converter.py +19 -0
- sky/utils/schemas.py +57 -5
- sky/workspaces/core.py +186 -50
- sky/workspaces/server.py +25 -0
- {skypilot_nightly-1.0.0.dev20250526.dist-info → skypilot_nightly-1.0.0.dev20250527.dist-info}/METADATA +1 -1
- {skypilot_nightly-1.0.0.dev20250526.dist-info → skypilot_nightly-1.0.0.dev20250527.dist-info}/RECORD +61 -58
- {skypilot_nightly-1.0.0.dev20250526.dist-info → skypilot_nightly-1.0.0.dev20250527.dist-info}/WHEEL +1 -1
- sky/dashboard/out/_next/static/7GEgRyZKRaSnYZCV1Jwol/_buildManifest.js +0 -1
- sky/dashboard/out/_next/static/chunks/25-062253ea41fb8eec.js +0 -6
- sky/dashboard/out/_next/static/chunks/734-a6e01d7f98904741.js +0 -1
- sky/dashboard/out/_next/static/chunks/938-59956af3950b02ed.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-3b5aad09a25f64b7.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-9529d9e882a0e75c.js +0 -16
- sky/dashboard/out/_next/static/chunks/pages/infra-abb7d744ecf15109.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-48dc8d67d4b60be1.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs-73d5e0c369d00346.js +0 -16
- sky/dashboard/out/_next/static/chunks/pages/users-b8acf6e6735323a2.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-5ed48b3201b998c8.js +0 -1
- sky/dashboard/out/_next/static/css/28558d57108b05ae.css +0 -3
- /sky/dashboard/out/_next/static/{7GEgRyZKRaSnYZCV1Jwol → D5bjIfl4Ob3SV3LJz3CO0}/_ssgManifest.js +0 -0
- /sky/dashboard/out/_next/static/chunks/{573-f17bd89d9f9118b3.js → 573-82bd40a37af834f1.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{578-d351125af46c293f.js → 578-24f35aa98d38d638.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/pages/{_app-96a715a6fb01e228.js → _app-3985f074c163a856.js} +0 -0
- {skypilot_nightly-1.0.0.dev20250526.dist-info → skypilot_nightly-1.0.0.dev20250527.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250526.dist-info → skypilot_nightly-1.0.0.dev20250527.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250526.dist-info → skypilot_nightly-1.0.0.dev20250527.dist-info}/top_level.txt +0 -0
sky/__init__.py
CHANGED
@@ -5,7 +5,7 @@ from typing import Optional
|
|
5
5
|
import urllib.request
|
6
6
|
|
7
7
|
# Replaced with the current commit when building the wheels.
|
8
|
-
_SKYPILOT_COMMIT_SHA = '
|
8
|
+
_SKYPILOT_COMMIT_SHA = '269ed1497f78a46da5dd05a528000da55eacf551'
|
9
9
|
|
10
10
|
|
11
11
|
def _get_git_commit():
|
@@ -35,7 +35,7 @@ def _get_git_commit():
|
|
35
35
|
|
36
36
|
|
37
37
|
__commit__ = _get_git_commit()
|
38
|
-
__version__ = '1.0.0.
|
38
|
+
__version__ = '1.0.0.dev20250527'
|
39
39
|
__root_dir__ = os.path.dirname(os.path.abspath(__file__))
|
40
40
|
|
41
41
|
|
sky/check.py
CHANGED
@@ -504,6 +504,18 @@ def _format_context_details(cloud: Union[str, sky_clouds.Cloud],
|
|
504
504
|
f'{str_to_format}'
|
505
505
|
f'{colorama.Style.RESET_ALL}')
|
506
506
|
|
507
|
+
# For SSH, determine which contexts are disabled due to allowed_node_pools
|
508
|
+
disabled_due_to_allowed_node_pools = set()
|
509
|
+
if isinstance(cloud_type, sky_clouds.SSH):
|
510
|
+
# Get all node pool contexts from file
|
511
|
+
all_node_pool_contexts = sky_clouds.SSH.get_ssh_node_pool_contexts()
|
512
|
+
# Get allowed contexts (after filtering)
|
513
|
+
allowed_contexts = sky_clouds.SSH.existing_allowed_contexts()
|
514
|
+
# Contexts that exist in file but not in allowed list are disabled
|
515
|
+
# due to allowed_node_pools configuration
|
516
|
+
disabled_due_to_allowed_node_pools = (set(all_node_pool_contexts) -
|
517
|
+
set(allowed_contexts))
|
518
|
+
|
507
519
|
# Format the context info with consistent styling
|
508
520
|
contexts_formatted = []
|
509
521
|
for i, context in enumerate(filtered_contexts):
|
@@ -519,11 +531,22 @@ def _format_context_details(cloud: Union[str, sky_clouds.Cloud],
|
|
519
531
|
text_suffix = ''
|
520
532
|
if show_details:
|
521
533
|
if ctx2text is not None:
|
522
|
-
|
523
|
-
f': {ctx2text[context]}'
|
524
|
-
|
525
|
-
|
526
|
-
|
534
|
+
if context in ctx2text:
|
535
|
+
text_suffix = f': {ctx2text[context]}'
|
536
|
+
elif (isinstance(cloud_type, sky_clouds.SSH) and
|
537
|
+
context in disabled_due_to_allowed_node_pools):
|
538
|
+
# Context is disabled due to allowed_node_pools config
|
539
|
+
text_suffix = (': ' + _red_color('disabled. ') +
|
540
|
+
_dim_color('Reason: Not included in '
|
541
|
+
'allowed_node_pools '
|
542
|
+
'configuration.'))
|
543
|
+
else:
|
544
|
+
# Default case - not set up
|
545
|
+
text_suffix = (': ' + _red_color('disabled. ') +
|
546
|
+
_dim_color('Reason: Not set up. Use '
|
547
|
+
'`sky ssh up --infra '
|
548
|
+
f'{context.lstrip("ssh-")}` '
|
549
|
+
'to set up.'))
|
527
550
|
contexts_formatted.append(
|
528
551
|
f'\n {symbol}{cleaned_context}{text_suffix}')
|
529
552
|
identity_str = ('SSH Node Pools' if isinstance(cloud_type, sky_clouds.SSH)
|
sky/cli.py
CHANGED
@@ -1789,20 +1789,8 @@ def _show_enabled_infra(active_workspace: str, show_workspace: bool):
|
|
1789
1789
|
title = (f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Enabled Infra'
|
1790
1790
|
f'{workspace_str}:'
|
1791
1791
|
f'{colorama.Style.RESET_ALL} ')
|
1792
|
-
|
1793
|
-
|
1794
|
-
enabled_k8s_infras = []
|
1795
|
-
enabled_cloud_infras = []
|
1796
|
-
for cloud in enabled_clouds:
|
1797
|
-
cloud_infra = cloud.get_infras()
|
1798
|
-
if isinstance(cloud, clouds.SSH):
|
1799
|
-
enabled_ssh_infras.extend(cloud_infra)
|
1800
|
-
elif isinstance(cloud, clouds.Kubernetes):
|
1801
|
-
enabled_k8s_infras.extend(cloud_infra)
|
1802
|
-
else:
|
1803
|
-
enabled_cloud_infras.extend(cloud_infra)
|
1804
|
-
all_infras = sorted(enabled_ssh_infras) + sorted(
|
1805
|
-
enabled_k8s_infras) + sorted(enabled_cloud_infras)
|
1792
|
+
all_infras = sdk.get(
|
1793
|
+
sdk.enabled_clouds(workspace=active_workspace, expand=True))
|
1806
1794
|
click.echo(f'{title}{", ".join(all_infras)}\n')
|
1807
1795
|
|
1808
1796
|
|
@@ -1997,7 +1985,7 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
|
|
1997
1985
|
workspace_request_id = sdk.workspaces()
|
1998
1986
|
except RuntimeError:
|
1999
1987
|
# Backward compatibility for API server before #5660.
|
2000
|
-
# TODO(zhwu): remove this after 0.
|
1988
|
+
# TODO(zhwu): remove this after 0.10.0.
|
2001
1989
|
logger.warning(f'{colorama.Style.DIM}SkyPilot API server is '
|
2002
1990
|
'in an old version, and may miss feature: '
|
2003
1991
|
'workspaces. Update with: sky api stop; '
|
@@ -3524,13 +3512,8 @@ def show_gpus(
|
|
3524
3512
|
cloud_is_ssh = isinstance(cloud_obj, clouds.SSH)
|
3525
3513
|
# TODO(romilb): We should move this to the backend.
|
3526
3514
|
kubernetes_autoscaling = kubernetes_utils.get_autoscaler_type() is not None
|
3527
|
-
kubernetes_is_enabled =
|
3528
|
-
ssh_is_enabled =
|
3529
|
-
for cloud in enabled_clouds:
|
3530
|
-
if isinstance(cloud, clouds.SSH):
|
3531
|
-
ssh_is_enabled = True
|
3532
|
-
elif isinstance(cloud, clouds.Kubernetes):
|
3533
|
-
kubernetes_is_enabled = True
|
3515
|
+
kubernetes_is_enabled = clouds.Kubernetes.canonical_name() in enabled_clouds
|
3516
|
+
ssh_is_enabled = clouds.SSH.canonical_name() in enabled_clouds
|
3534
3517
|
query_k8s_realtime_gpu = (kubernetes_is_enabled and
|
3535
3518
|
(cloud_name is None or cloud_is_kubernetes))
|
3536
3519
|
query_ssh_realtime_gpu = (ssh_is_enabled and
|
sky/client/cli.py
CHANGED
@@ -1789,20 +1789,8 @@ def _show_enabled_infra(active_workspace: str, show_workspace: bool):
|
|
1789
1789
|
title = (f'{colorama.Fore.CYAN}{colorama.Style.BRIGHT}Enabled Infra'
|
1790
1790
|
f'{workspace_str}:'
|
1791
1791
|
f'{colorama.Style.RESET_ALL} ')
|
1792
|
-
|
1793
|
-
|
1794
|
-
enabled_k8s_infras = []
|
1795
|
-
enabled_cloud_infras = []
|
1796
|
-
for cloud in enabled_clouds:
|
1797
|
-
cloud_infra = cloud.get_infras()
|
1798
|
-
if isinstance(cloud, clouds.SSH):
|
1799
|
-
enabled_ssh_infras.extend(cloud_infra)
|
1800
|
-
elif isinstance(cloud, clouds.Kubernetes):
|
1801
|
-
enabled_k8s_infras.extend(cloud_infra)
|
1802
|
-
else:
|
1803
|
-
enabled_cloud_infras.extend(cloud_infra)
|
1804
|
-
all_infras = sorted(enabled_ssh_infras) + sorted(
|
1805
|
-
enabled_k8s_infras) + sorted(enabled_cloud_infras)
|
1792
|
+
all_infras = sdk.get(
|
1793
|
+
sdk.enabled_clouds(workspace=active_workspace, expand=True))
|
1806
1794
|
click.echo(f'{title}{", ".join(all_infras)}\n')
|
1807
1795
|
|
1808
1796
|
|
@@ -1997,7 +1985,7 @@ def status(verbose: bool, refresh: bool, ip: bool, endpoints: bool,
|
|
1997
1985
|
workspace_request_id = sdk.workspaces()
|
1998
1986
|
except RuntimeError:
|
1999
1987
|
# Backward compatibility for API server before #5660.
|
2000
|
-
# TODO(zhwu): remove this after 0.
|
1988
|
+
# TODO(zhwu): remove this after 0.10.0.
|
2001
1989
|
logger.warning(f'{colorama.Style.DIM}SkyPilot API server is '
|
2002
1990
|
'in an old version, and may miss feature: '
|
2003
1991
|
'workspaces. Update with: sky api stop; '
|
@@ -3524,13 +3512,8 @@ def show_gpus(
|
|
3524
3512
|
cloud_is_ssh = isinstance(cloud_obj, clouds.SSH)
|
3525
3513
|
# TODO(romilb): We should move this to the backend.
|
3526
3514
|
kubernetes_autoscaling = kubernetes_utils.get_autoscaler_type() is not None
|
3527
|
-
kubernetes_is_enabled =
|
3528
|
-
ssh_is_enabled =
|
3529
|
-
for cloud in enabled_clouds:
|
3530
|
-
if isinstance(cloud, clouds.SSH):
|
3531
|
-
ssh_is_enabled = True
|
3532
|
-
elif isinstance(cloud, clouds.Kubernetes):
|
3533
|
-
kubernetes_is_enabled = True
|
3515
|
+
kubernetes_is_enabled = clouds.Kubernetes.canonical_name() in enabled_clouds
|
3516
|
+
ssh_is_enabled = clouds.SSH.canonical_name() in enabled_clouds
|
3534
3517
|
query_k8s_realtime_gpu = (kubernetes_is_enabled and
|
3535
3518
|
(cloud_name is None or cloud_is_kubernetes))
|
3536
3519
|
query_ssh_realtime_gpu = (ssh_is_enabled and
|
sky/client/sdk.py
CHANGED
@@ -138,12 +138,14 @@ def check(infra_list: Optional[Tuple[str, ...]],
|
|
138
138
|
@usage_lib.entrypoint
|
139
139
|
@server_common.check_server_healthy_or_start
|
140
140
|
@annotations.client_api
|
141
|
-
def enabled_clouds(workspace: Optional[str] = None
|
141
|
+
def enabled_clouds(workspace: Optional[str] = None,
|
142
|
+
expand: bool = False) -> server_common.RequestId:
|
142
143
|
"""Gets the enabled clouds.
|
143
144
|
|
144
145
|
Args:
|
145
146
|
workspace: The workspace to get the enabled clouds for. If None, the
|
146
147
|
active workspace will be used.
|
148
|
+
expand: Whether to expand Kubernetes and SSH to list of resource pools.
|
147
149
|
|
148
150
|
Returns:
|
149
151
|
The request ID of the enabled clouds request.
|
@@ -154,7 +156,7 @@ def enabled_clouds(workspace: Optional[str] = None) -> server_common.RequestId:
|
|
154
156
|
if workspace is None:
|
155
157
|
workspace = skypilot_config.get_active_workspace()
|
156
158
|
response = requests.get((f'{server_common.get_server_url()}/enabled_clouds?'
|
157
|
-
f'workspace={workspace}'),
|
159
|
+
f'workspace={workspace}&expand={expand}'),
|
158
160
|
cookies=server_common.get_api_cookie_jar())
|
159
161
|
return server_common.get_request_id(response)
|
160
162
|
|
@@ -1919,6 +1921,7 @@ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
|
|
1919
1921
|
if (endpoint is not None and not endpoint.startswith('http://') and
|
1920
1922
|
not endpoint.startswith('https://')):
|
1921
1923
|
raise click.BadParameter('Endpoint must be a valid URL.')
|
1924
|
+
endpoint = endpoint.rstrip('/')
|
1922
1925
|
|
1923
1926
|
server_status = server_common.check_server_healthy(endpoint)
|
1924
1927
|
if server_status == server_common.ApiServerStatus.NEEDS_AUTH or get_token:
|
sky/clouds/cloud.py
CHANGED
@@ -492,13 +492,13 @@ class Cloud:
|
|
492
492
|
f'{cls._REPR} does not support {CloudCapability.STORAGE.value}.')
|
493
493
|
|
494
494
|
@classmethod
|
495
|
-
def
|
495
|
+
def expand_infras(cls) -> List[str]:
|
496
496
|
"""Returns a list of enabled infrastructures for this cloud.
|
497
497
|
|
498
498
|
For Kubernetes and SSH, return a list of resource pools.
|
499
499
|
For all other clouds, return self.
|
500
500
|
"""
|
501
|
-
return [cls.
|
501
|
+
return [cls.canonical_name()]
|
502
502
|
|
503
503
|
# TODO(zhwu): Make the return type immutable.
|
504
504
|
@classmethod
|
sky/clouds/kubernetes.py
CHANGED
@@ -164,15 +164,20 @@ class Kubernetes(clouds.Cloud):
|
|
164
164
|
|
165
165
|
all_contexts = set(all_contexts)
|
166
166
|
|
167
|
+
# Allowed_contexts specified for workspace should take precedence over
|
168
|
+
# the global allowed_contexts.
|
169
|
+
allowed_contexts = skypilot_config.get_workspace_cloud(
|
170
|
+
'kubernetes').get('allowed_contexts', None)
|
171
|
+
if allowed_contexts is None:
|
172
|
+
allowed_contexts = skypilot_config.get_nested(
|
173
|
+
('kubernetes', 'allowed_contexts'), None)
|
174
|
+
|
167
175
|
# Exclude contexts starting with `ssh-`
|
168
176
|
# TODO(romilb): Remove when SSH Node Pools use a separate kubeconfig.
|
169
177
|
all_contexts = [
|
170
178
|
ctx for ctx in all_contexts if not ctx.startswith('ssh-')
|
171
179
|
]
|
172
180
|
|
173
|
-
allowed_contexts = skypilot_config.get_nested(
|
174
|
-
('kubernetes', 'allowed_contexts'), None)
|
175
|
-
|
176
181
|
if allowed_contexts is None:
|
177
182
|
# Try kubeconfig if present
|
178
183
|
current_context = (
|
@@ -894,8 +899,8 @@ class Kubernetes(clouds.Cloud):
|
|
894
899
|
return True, None
|
895
900
|
|
896
901
|
@classmethod
|
897
|
-
def
|
902
|
+
def expand_infras(cls) -> List[str]:
|
898
903
|
return [
|
899
|
-
f'{cls.
|
904
|
+
f'{cls.canonical_name()}/{c}'
|
900
905
|
for c in cls.existing_allowed_contexts(silent=True)
|
901
906
|
]
|
@@ -260,6 +260,10 @@ def _list_accelerators(
|
|
260
260
|
container.resources.requests))
|
261
261
|
|
262
262
|
accelerators_available = accelerator_count - allocated_qty
|
263
|
+
# Initialize the total_accelerators_available to make sure the
|
264
|
+
# key exists in the dictionary.
|
265
|
+
total_accelerators_available[accelerator_name] = (
|
266
|
+
total_accelerators_available.get(accelerator_name, 0))
|
263
267
|
|
264
268
|
if accelerators_available >= min_quantity_filter:
|
265
269
|
quantized_availability = min_quantity_filter * (
|
sky/clouds/ssh.py
CHANGED
@@ -7,6 +7,7 @@ from typing import Dict, List, Optional, Set, Tuple, Union
|
|
7
7
|
import yaml
|
8
8
|
|
9
9
|
from sky import sky_logging
|
10
|
+
from sky import skypilot_config
|
10
11
|
from sky.adaptors import kubernetes as kubernetes_adaptor
|
11
12
|
from sky.clouds import kubernetes
|
12
13
|
from sky.provision.kubernetes import utils as kubernetes_utils
|
@@ -134,29 +135,44 @@ class SSH(kubernetes.Kubernetes):
|
|
134
135
|
|
135
136
|
all_contexts = set(all_contexts)
|
136
137
|
|
138
|
+
# Workspace-level allowed_node_pools should take precedence over
|
139
|
+
# the global allowed_node_pools.
|
140
|
+
allowed_node_pools = skypilot_config.get_workspace_cloud('ssh').get(
|
141
|
+
'allowed_node_pools', None)
|
142
|
+
if allowed_node_pools is None:
|
143
|
+
allowed_node_pools = skypilot_config.get_nested(
|
144
|
+
('ssh', 'allowed_node_pools'), None)
|
145
|
+
|
137
146
|
# Filter for SSH contexts (those starting with 'ssh-')
|
138
147
|
ssh_contexts = [
|
139
148
|
context for context in all_contexts if context.startswith('ssh-')
|
140
149
|
]
|
141
150
|
|
142
151
|
# Get contexts from SSH node pools file
|
143
|
-
|
152
|
+
all_node_pool_contexts = cls.get_ssh_node_pool_contexts()
|
153
|
+
|
154
|
+
def filter_by_allowed_node_pools(ctxs):
|
155
|
+
if allowed_node_pools is None:
|
156
|
+
return ctxs
|
157
|
+
return [
|
158
|
+
ctx for ctx in ctxs if ctx.lstrip('ssh-') in allowed_node_pools
|
159
|
+
]
|
144
160
|
|
145
|
-
if
|
161
|
+
if all_node_pool_contexts:
|
146
162
|
# Only include allowed contexts that exist
|
147
163
|
existing_contexts = []
|
148
164
|
skipped_contexts = []
|
149
|
-
for context in
|
165
|
+
for context in all_node_pool_contexts:
|
150
166
|
if context in ssh_contexts:
|
151
167
|
existing_contexts.append(context)
|
152
168
|
else:
|
153
169
|
skipped_contexts.append(context)
|
154
170
|
if not silent:
|
155
171
|
cls._ssh_log_skipped_contexts_once(tuple(skipped_contexts))
|
156
|
-
return existing_contexts
|
172
|
+
return filter_by_allowed_node_pools(existing_contexts)
|
157
173
|
|
158
|
-
# If no
|
159
|
-
return ssh_contexts
|
174
|
+
# If no all_node_pool_contexts found, return all SSH contexts
|
175
|
+
return filter_by_allowed_node_pools(ssh_contexts)
|
160
176
|
|
161
177
|
@classmethod
|
162
178
|
def _check_compute_credentials(
|
@@ -192,9 +208,9 @@ class SSH(kubernetes.Kubernetes):
|
|
192
208
|
return success, ctx2text
|
193
209
|
|
194
210
|
@classmethod
|
195
|
-
def
|
211
|
+
def expand_infras(cls) -> List[str]:
|
196
212
|
return [
|
197
|
-
f'{cls.
|
213
|
+
f'{cls.canonical_name()}/{c.lstrip("ssh-")}'
|
198
214
|
for c in cls.existing_allowed_contexts(silent=True)
|
199
215
|
]
|
200
216
|
|
sky/core.py
CHANGED
@@ -1010,11 +1010,29 @@ def storage_delete(name: str) -> None:
|
|
1010
1010
|
# = Catalog Observe =
|
1011
1011
|
# ===================
|
1012
1012
|
@usage_lib.entrypoint
|
1013
|
-
def enabled_clouds(workspace: Optional[str] = None
|
1013
|
+
def enabled_clouds(workspace: Optional[str] = None,
|
1014
|
+
expand: bool = False) -> List[str]:
|
1014
1015
|
if workspace is None:
|
1015
1016
|
workspace = skypilot_config.get_active_workspace()
|
1016
|
-
|
1017
|
+
cached_clouds = global_user_state.get_cached_enabled_clouds(
|
1017
1018
|
sky_cloud.CloudCapability.COMPUTE, workspace=workspace)
|
1019
|
+
with skypilot_config.local_active_workspace_ctx(workspace):
|
1020
|
+
if not expand:
|
1021
|
+
return [cloud.canonical_name() for cloud in cached_clouds]
|
1022
|
+
enabled_ssh_infras = []
|
1023
|
+
enabled_k8s_infras = []
|
1024
|
+
enabled_cloud_infras = []
|
1025
|
+
for cloud in cached_clouds:
|
1026
|
+
cloud_infra = cloud.expand_infras()
|
1027
|
+
if isinstance(cloud, clouds.SSH):
|
1028
|
+
enabled_ssh_infras.extend(cloud_infra)
|
1029
|
+
elif isinstance(cloud, clouds.Kubernetes):
|
1030
|
+
enabled_k8s_infras.extend(cloud_infra)
|
1031
|
+
else:
|
1032
|
+
enabled_cloud_infras.extend(cloud_infra)
|
1033
|
+
all_infras = sorted(enabled_ssh_infras) + sorted(
|
1034
|
+
enabled_k8s_infras) + sorted(enabled_cloud_infras)
|
1035
|
+
return all_infras
|
1018
1036
|
|
1019
1037
|
|
1020
1038
|
@usage_lib.entrypoint
|
sky/dashboard/out/404.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link rel="preload" href="/dashboard/_next/static/css/6a1c0d711a4bdaf1.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/6a1c0d711a4bdaf1.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-deda68c926e8d0bc.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-3985f074c163a856.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/D5bjIfl4Ob3SV3LJz3CO0/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"D5bjIfl4Ob3SV3LJz3CO0","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
@@ -0,0 +1 @@
|
|
1
|
+
self.__BUILD_MANIFEST=function(s,c,e,a,t,r,f,u,n,j){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-6b0d9e5031b70c58.js"],"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],"/clusters":[s,a,c,e,t,n,"static/chunks/pages/clusters-8afda8efa5b74997.js"],"/clusters/[cluster]":[s,a,c,e,t,r,n,"static/chunks/pages/clusters/[cluster]-e23fcddf60578a0d.js"],"/clusters/[cluster]/[job]":[s,c,"static/chunks/pages/clusters/[cluster]/[job]-339b59921ccfe266.js"],"/config":[f,s,u,c,e,"static/chunks/pages/config-72b8c6c2edfd0e39.js"],"/infra":[s,c,"static/chunks/pages/infra-1521baab6992916b.js"],"/jobs":[s,a,c,e,t,r,"static/chunks/pages/jobs-ff7e8e377d02b651.js"],"/jobs/[job]":[s,c,"static/chunks/pages/jobs/[job]-4d913940b4fa6f5a.js"],"/users":[s,c,"static/chunks/pages/users-9900af52acf8648d.js"],"/workspace/new":[f,s,a,u,c,e,t,r,j,"static/chunks/pages/workspace/new-63763ffa3edb4508.js"],"/workspaces":[f,s,a,u,c,e,t,r,"static/chunks/pages/workspaces-72330c4d0fc9a4a2.js"],"/workspaces/[name]":[f,s,a,u,c,e,t,r,j,"static/chunks/pages/workspaces/[name]-3ede7a13caf23375.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/jobs","/jobs/[job]","/users","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/573-82bd40a37af834f1.js","static/chunks/470-1d784f5c8750744a.js","static/chunks/990-f85643b521f7ca65.js","static/chunks/488-50d843fdb5396d32.js","static/chunks/627-31b701e69f52db0c.js","static/chunks/236-e220ba0c35bf089e.js","static/chunks/9f96d65d-5a3e4af68c26849e.js","static/chunks/320-afea3ddcc5bd1c6c.js","static/chunks/578-24f35aa98d38d638.js","static/chunks/843-e35d71cf1c7f706e.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
@@ -0,0 +1,6 @@
|
|
1
|
+
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[236],{8236:function(e,s,t){t.d(s,{L4:function(){return D},Nk:function(){return R},x2:function(){return S}});var r=t(5893),n=t(7294),a=t(1163),l=t(1664),c=t.n(l),i=t(8799),o=t(803),d=t(7673),h=t(8764),u=t(6989),x=t(8969),m=t(3266),p=t(7324),j=t(9470),f=t(3626),g=t(998);/**
|
2
|
+
* @license lucide-react v0.407.0 - ISC
|
3
|
+
*
|
4
|
+
* This source code is licensed under the ISC license.
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
6
|
+
*/let w=(0,g.Z)("RefreshCcw",[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]]),b=(0,g.Z)("FileSearch",[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3",key:"ms7g94"}],["path",{d:"m9 18-1.5-1.5",key:"1j6qii"}],["circle",{cx:"5",cy:"14",r:"3",key:"ufru5t"}]]),y=(0,g.Z)("MonitorPlay",[["path",{d:"M10 7.75a.75.75 0 0 1 1.142-.638l3.664 2.249a.75.75 0 0 1 0 1.278l-3.664 2.25a.75.75 0 0 1-1.142-.64z",key:"1pctta"}],["path",{d:"M12 17v4",key:"1riwvh"}],["path",{d:"M8 21h8",key:"1ev6f3"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",key:"x3v2xh"}]]);var N=t(9284),v=t(4545),k=t(9307),C=t(3001),_=t(8950);let S={active:["PENDING","RUNNING","RECOVERING","SUBMITTED","STARTING","CANCELLING"],finished:["SUCCEEDED","FAILED","CANCELLED","FAILED_SETUP","FAILED_PRECHECKS","FAILED_NO_RESOURCE","FAILED_CONTROLLER"]},E="__ALL_WORKSPACES__",L=e=>{if(!e)return"-";let s=(0,u.GV)(e);if(n.isValidElement(s)&&s.props&&s.props.children&&(s=n.isValidElement(s.props.children)&&s.props.children.props&&s.props.children.props.children?s.props.children.props.children:s.props.children),"string"!=typeof s)return s;if("just now"===s)return"now";let t=s.match(/^About\s+(\d+)\s+(\w+)\s+ago$/);if(t){let e=t[1],s=t[2],r={second:"sec",seconds:"secs",minute:"min",minutes:"mins",hour:"hr",hours:"hrs",day:"d",days:"d",month:"mo",months:"mos",year:"yr",years:"yrs"};if(r[s])return"~ ".concat(e," ").concat(r[s]," ago")}let r=s.match(/^a[n]?\s+(\w+)\s+ago$/);if(r){let e=r[1],s={second:"sec",minute:"min",hour:"hr",day:"d",month:"mo",year:"yr"};if(s[e])return"1 ".concat(s[e]," ago")}let a=s.match(/^(\d+)\s+(\w+)\s+ago$/);if(a){let e=a[1],s=a[2],t={seconds:"secs",minutes:"mins",hours:"hrs",days:"d",months:"mo",years:"yr"};if(t[s])return"".concat(e," ").concat(t[s]," ago")}return s};function R(){let e=(0,a.useRouter)(),[s,t]=(0,n.useState)(!1),l=n.useRef(null),[d,h]=(0,n.useState)({isOpen:!1,title:"",message:"",onConfirm:null}),m=(0,C.X)(),[g,w]=(0,n.useState)(E),[b,y]=(0,n.useState)([]);return(0,n.useEffect)(()=>{e.isReady&&e.query.workspace&&w(Array.isArray(e.query.workspace)?e.query.workspace[0]:e.query.workspace)},[e.isReady,e.query.workspace]),(0,n.useEffect)(()=>{(async()=>{try{let e=await (0,p.fX)(),s=Object.keys(e),t=(await (0,x.Vp)()).jobs||[],r=[...new Set(t.map(e=>e.workspace||"default").filter(e=>e))],n=new Set(s);r.forEach(e=>n.add(e)),y(Array.from(n).sort())}catch(e){console.error("Error fetching data for workspace filter:",e),y(["default"])}})()},[]),(0,r.jsxs)(j.A,{highlighted:"jobs",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between mb-4 h-5",children:[(0,r.jsxs)("div",{className:"text-base flex items-center",children:[(0,r.jsx)(c(),{href:"/jobs",className:"text-sky-blue hover:underline leading-none",children:"Managed Jobs"}),(0,r.jsxs)(_.Ph,{value:g,onValueChange:w,children:[(0,r.jsx)(_.i4,{className:"h-8 w-48 ml-4 mr-2 text-sm border-none focus:ring-0 focus:outline-none",children:(0,r.jsx)(_.ki,{placeholder:"Filter by workspace...",children:g===E?"All Workspaces":g})}),(0,r.jsxs)(_.Bw,{children:[(0,r.jsx)(_.Ql,{value:E,children:"All Workspaces"}),b.map(e=>(0,r.jsx)(_.Ql,{value:e,children:e},e))]})]})]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[s&&(0,r.jsxs)("div",{className:"flex items-center mr-2",children:[(0,r.jsx)(i.Z,{size:15,className:"mt-0"}),(0,r.jsx)("span",{className:"ml-2 text-gray-500 text-sm",children:"Loading..."})]}),(0,r.jsxs)(o.z,{variant:"ghost",size:"sm",onClick:()=>{l.current&&l.current()},disabled:s,className:"text-sky-blue hover:text-sky-blue-bright",title:"Refresh",children:[(0,r.jsx)(f.Z,{className:"h-4 w-4 mr-1.5"}),!m&&(0,r.jsx)("span",{children:"Refresh"})]})]})]}),(0,r.jsx)(O,{refreshInterval:u.yc,setLoading:t,refreshDataRef:l,workspaceFilter:g}),(0,r.jsx)(N.cV,{isOpen:d.isOpen,onClose:()=>h({...d,isOpen:!1}),onConfirm:d.onConfirm,title:d.title,message:d.message})]})}function O(e){let{refreshInterval:s,setLoading:t,refreshDataRef:a,workspaceFilter:l}=e,[p,j]=(0,n.useState)([]),[f,g]=(0,n.useState)({key:null,direction:"ascending"}),[b,y]=(0,n.useState)(!1),[C,_]=(0,n.useState)(!0),[R,O]=(0,n.useState)(1),[D,z]=(0,n.useState)(10),[P,J]=(0,n.useState)(null),q=(0,n.useRef)(null),[T,F]=(0,n.useState)([]),[W,U]=(0,n.useState)({}),[V,Z]=(0,n.useState)(!1),[B,G]=(0,n.useState)(!1),[H,X]=(0,n.useState)(!1),[$,K]=(0,n.useState)("active"),[Q,Y]=(0,n.useState)(!0),[ee,es]=(0,n.useState)({isOpen:!1,title:"",message:"",onConfirm:null}),et=async()=>{es({isOpen:!0,title:"Restart Controller",message:"Are you sure you want to restart the controller? This will temporarily interrupt job management.",onConfirm:async()=>{try{X(!0),y(!0),await (0,x.Ce)("restartcontroller"),await er()}catch(e){console.error("Error restarting controller:",e)}finally{X(!1),y(!1)}}})},er=n.useCallback(async()=>{y(!0),t(!0);try{let[e,s]=await Promise.all([(0,x.Vp)(),(0,m.zd)()]),{jobs:t,controllerStopped:r}=e,n=s.find(e=>(0,v.Ym)(e.cluster)),a=n?n.status:"NOT_FOUND",l=!1;"STOPPED"==a&&r&&(l=!0),"LAUNCHING"==a?G(!0):G(!1),j(t),Z(l)}catch(e){console.error("Error fetching data:",e),j([])}finally{y(!1),t(!1),_(!1)}},[t]);n.useEffect(()=>{a&&(a.current=er)},[a,er]),(0,n.useEffect)(()=>{j([]);let e=!0;er();let t=setInterval(()=>{e&&er()},s);return()=>{e=!1,clearInterval(t)}},[s,er]),(0,n.useEffect)(()=>{O(1)},[$,p.length]),(0,n.useEffect)(()=>{F([]),Y(!0)},[$]);let en=e=>{let s="ascending";f.key===e&&"ascending"===f.direction&&(s="descending"),g({key:e,direction:s})},ea=e=>f.key===e?"ascending"===f.direction?" ↑":" ↓":"";n.useMemo(()=>({active:p.filter(e=>S.active.includes(e.status)).length,finished:p.filter(e=>S.finished.includes(e.status)).length}),[p]);let el=e=>T.length>0?T.includes(e):S[$].includes(e),ec=n.useMemo(()=>{let e=l&&l!==E?p.filter(e=>(e.workspace||"default").toLowerCase()===l.toLowerCase()):p;return T.length>0?e.filter(e=>T.includes(e.status)):Q?e.filter(e=>S[$].includes(e.status)):[]},[p,$,T,Q,S,l]),ei=n.useMemo(()=>f.key?[...ec].sort((e,s)=>e[f.key]<s[f.key]?"ascending"===f.direction?-1:1:e[f.key]>s[f.key]?"ascending"===f.direction?1:-1:0):ec,[ec,f]),eo=Math.ceil(ei.length/D),ed=(R-1)*D,eh=ed+D,eu=ei.slice(ed,eh),ex=e=>{if(T.includes(e)){let s=T.filter(s=>s!==e);0===s.length?(Y(!0),F([])):(F(s),Y(!1))}else F([...T,e]),Y(!1)};return(0,n.useEffect)(()=>{U(p.reduce((e,s)=>(e[s.status]=(e[s.status]||0)+1,e),{}))},[p]),(0,r.jsxs)("div",{className:"relative",children:[(0,r.jsx)("div",{className:"flex flex-col space-y-1 mb-1",children:(0,r.jsxs)("div",{className:"flex flex-wrap items-center text-sm mb-1",children:[(0,r.jsx)("span",{className:"mr-2 text-sm font-medium",children:"Statuses:"}),(0,r.jsxs)("div",{className:"flex flex-wrap gap-2 items-center",children:[!b&&0===p.length&&!C&&(0,r.jsx)("span",{className:"text-gray-500 mr-2",children:"No jobs found"}),Object.entries(W).map(e=>{let[s,t]=e;return(0,r.jsxs)("button",{onClick:()=>ex(s),className:"px-3 py-1 rounded-full flex items-center space-x-2 ".concat(el(s)||T.includes(s)?(0,k.Cl)(s):"bg-gray-50 text-gray-600 hover:bg-gray-100"),children:[(0,r.jsx)("span",{children:s}),(0,r.jsx)("span",{className:"text-xs ".concat(el(s)||T.includes(s)?"bg-white/50":"bg-gray-200"," px-1.5 py-0.5 rounded"),children:t})]},s)}),p.length>0&&(0,r.jsxs)("div",{className:"flex items-center ml-2 gap-2",children:[(0,r.jsx)("span",{className:"text-gray-500",children:"("}),(0,r.jsx)("button",{onClick:()=>{K("active"),F([]),Y(!0)},className:"text-sm font-medium ".concat("active"===$&&Q?"text-green-700 underline":"text-gray-600 hover:text-green-700 hover:underline"),children:"show all active jobs"}),(0,r.jsx)("span",{className:"text-gray-500 mx-1",children:"|"}),(0,r.jsx)("button",{onClick:()=>{K("finished"),F([]),Y(!0)},className:"text-sm font-medium ".concat("finished"===$&&Q?"text-blue-700 underline":"text-gray-600 hover:text-blue-700 hover:underline"),children:"show all finished jobs"}),(0,r.jsx)("span",{className:"text-gray-500",children:")"})]})]})]})}),(0,r.jsx)(d.Zb,{children:(0,r.jsxs)(h.iA,{children:[(0,r.jsx)(h.xD,{children:(0,r.jsxs)(h.SC,{children:[(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("id"),children:["ID",ea("id")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("name"),children:["Name",ea("name")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("user"),children:["User",ea("user")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("workspace"),children:["Workspace",ea("workspace")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("submitted_at"),children:["Submitted",ea("submitted_at")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("job_duration"),children:["Duration",ea("job_duration")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("status"),children:["Status",ea("status")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("resources_str"),children:["Requested",ea("resources_str")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("infra"),children:["Infra",ea("infra")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("cluster"),children:["Resources",ea("cluster")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>en("recoveries"),children:["Recoveries",ea("recoveries")]}),(0,r.jsx)(h.ss,{children:"Details"}),(0,r.jsx)(h.ss,{children:"Logs"})]})}),(0,r.jsx)(h.RM,{children:b&&C?(0,r.jsx)(h.SC,{children:(0,r.jsx)(h.pj,{colSpan:12,className:"text-center py-6 text-gray-500",children:(0,r.jsxs)("div",{className:"flex justify-center items-center",children:[(0,r.jsx)(i.Z,{size:20,className:"mr-2"}),(0,r.jsx)("span",{children:"Loading..."})]})})}):eu.length>0?(0,r.jsx)(r.Fragment,{children:eu.map(e=>(0,r.jsxs)(n.Fragment,{children:[(0,r.jsxs)(h.SC,{children:[(0,r.jsx)(h.pj,{children:(0,r.jsx)(c(),{href:"/jobs/".concat(e.id),className:"text-blue-600",children:e.id})}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(c(),{href:"/jobs/".concat(e.id),className:"text-blue-600",children:e.name})}),(0,r.jsx)(h.pj,{children:e.user}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(c(),{href:"/workspaces",className:"text-blue-600 hover:underline",children:e.workspace||"default"})}),(0,r.jsx)(h.pj,{children:L(e.submitted_at)}),(0,r.jsx)(h.pj,{children:(0,u.LU)(e.job_duration)}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(k.OE,{status:e.status})}),(0,r.jsx)(h.pj,{children:e.requested_resources}),(0,r.jsx)(h.pj,{children:e.infra&&"-"!==e.infra?(0,r.jsx)(u.Md,{content:e.full_infra||e.infra,className:"text-sm text-muted-foreground",children:(0,r.jsxs)("span",{children:[(0,r.jsx)(c(),{href:"/infra",className:"text-blue-600 hover:underline",children:e.cloud||e.infra.split("(")[0].trim()}),e.infra.includes("(")&&(0,r.jsx)("span",{children:" "+e.infra.substring(e.infra.indexOf("("))})]})}):(0,r.jsx)("span",{children:e.infra||"-"})}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(u.Md,{content:e.resources_str_full||e.resources_str,className:"text-sm text-muted-foreground",children:(0,r.jsx)("span",{children:e.resources_str})})}),(0,r.jsx)(h.pj,{children:e.recoveries}),(0,r.jsx)(h.pj,{children:e.details?(0,r.jsx)(A,{text:e.details,rowId:e.id,expandedRowId:P,setExpandedRowId:J}):"-"}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(M,{jobParent:"/jobs",jobId:e.id,managed:!0})})]}),P===e.id&&(0,r.jsx)(I,{text:e.details,colSpan:12,innerRef:q})]},e.id))}):(0,r.jsx)(h.SC,{children:(0,r.jsx)(h.pj,{colSpan:12,className:"text-center py-6",children:(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-4",children:[B&&(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-2",children:[(0,r.jsx)("p",{className:"text-gray-700",children:"The managed job controller is launching. Please wait for it to be ready."}),(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(i.Z,{size:12,className:"mr-2"}),(0,r.jsx)("span",{className:"text-gray-500",children:"Launching..."})]})]}),!V&&!B&&(0,r.jsx)("p",{className:"text-gray-500",children:"No active jobs"}),V&&(0,r.jsxs)("div",{className:"flex flex-col items-center space-y-2",children:[(0,r.jsx)("p",{className:"text-gray-700",children:"The managed job controller has been stopped. Please restart it to check the latest job status."}),(0,r.jsx)(o.z,{variant:"outline",size:"sm",onClick:et,className:"text-sky-blue hover:text-sky-blue-bright",disabled:b||H,children:H?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.Z,{size:12,className:"mr-2"}),"Restarting..."]}):(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(w,{className:"h-4 w-4 mr-2"}),"Restart Controller"]})})]})]})})})})]})}),ei.length>0&&(0,r.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,r.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,r.jsxs)("div",{className:"relative inline-block",children:[(0,r.jsxs)("select",{value:D,onChange:e=>{z(parseInt(e.target.value,10)),O(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,r.jsx)("option",{value:10,children:"10"}),(0,r.jsx)("option",{value:30,children:"30"}),(0,r.jsx)("option",{value:50,children:"50"}),(0,r.jsx)("option",{value:100,children:"100"}),(0,r.jsx)("option",{value:200,children:"200"})]}),(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-gray-500 absolute right-0 top-1/2 transform -translate-y-1/2 pointer-events-none",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,r.jsxs)("div",{children:[ed+1," – ",Math.min(eh,ei.length)," of"," ",ei.length]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{O(e=>Math.max(e-1,1))},disabled:1===R,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-left",children:(0,r.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{O(e=>Math.min(e+1,eo))},disabled:R===eo||0===eo,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-right",children:(0,r.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})}),(0,r.jsx)(N.cV,{isOpen:ee.isOpen,onClose:()=>es({...ee,isOpen:!1}),onConfirm:ee.onConfirm,title:ee.title,message:ee.message})]})}function M(e){let{withLabel:s=!1,jobParent:t,jobId:n,managed:l}=e,c=(0,a.useRouter)(),i=(e,s)=>{e.preventDefault(),e.stopPropagation(),c.push({pathname:"".concat(t,"/").concat(n),query:{tab:s}})};return(0,r.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,r.jsx)(u.WH,{content:"View Job Logs",className:"capitalize text-sm text-muted-foreground",children:(0,r.jsxs)("button",{onClick:e=>i(e,"logs"),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center h-8",children:[(0,r.jsx)(b,{className:"w-4 h-4"}),s&&(0,r.jsx)("span",{className:"ml-1.5",children:"Logs"})]})},"logs"),l&&(0,r.jsx)(u.WH,{content:"View Controller Logs",className:"capitalize text-sm text-muted-foreground",children:(0,r.jsxs)("button",{onClick:e=>i(e,"controllerlogs"),className:"text-sky-blue hover:text-sky-blue-bright font-medium inline-flex items-center h-8",children:[(0,r.jsx)(y,{className:"w-4 h-4"}),s&&(0,r.jsx)("span",{className:"ml-2",children:"Controller Logs"})]})},"controllerlogs")]})}function D(e){let{clusterName:s,clusterJobData:t,loading:a}=e,[l,x]=(0,n.useState)(null),[m,p]=(0,n.useState)({key:null,direction:"ascending"}),[j,f]=(0,n.useState)(1),[g,w]=(0,n.useState)(10),b=(0,n.useRef)(null),[y,N]=(0,n.useState)(null);(0,n.useEffect)(()=>{let e=e=>{l&&b.current&&!b.current.contains(e.target)&&x(null)};return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[l]);let v=n.useMemo(()=>t||[],[t]);(0,n.useEffect)(()=>{JSON.stringify(t)!==JSON.stringify(y)&&N(t)},[t,y]);let C=n.useMemo(()=>m.key?[...v].sort((e,s)=>e[m.key]<s[m.key]?"ascending"===m.direction?-1:1:e[m.key]>s[m.key]?"ascending"===m.direction?1:-1:0):v,[v,m]),_=e=>{let s="ascending";m.key===e&&"ascending"===m.direction&&(s="descending"),p({key:e,direction:s})},S=e=>m.key===e?"ascending"===m.direction?" ↑":" ↓":"",E=Math.ceil(C.length/g),R=(j-1)*g,O=R+g,D=C.slice(R,O);return(0,r.jsxs)("div",{className:"relative",children:[(0,r.jsxs)(d.Zb,{children:[(0,r.jsxs)("div",{className:"flex items-center justify-between p-4",children:[(0,r.jsx)("h3",{className:"text-lg font-semibold",children:"Cluster Jobs"}),a&&(0,r.jsxs)("div",{className:"flex items-center mr-2",children:[(0,r.jsx)(i.Z,{size:15,className:"mt-0"}),(0,r.jsx)("span",{className:"ml-2 text-gray-500 text-sm",children:"Loading..."})]})]}),(0,r.jsxs)(h.iA,{children:[(0,r.jsx)(h.xD,{children:(0,r.jsxs)(h.SC,{children:[(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("id"),children:["ID",S("id")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("job"),children:["Name",S("job")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("user"),children:["User",S("user")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("workspace"),children:["Workspace",S("workspace")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("submitted_at"),children:["Submitted",S("submitted_at")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("job_duration"),children:["Duration",S("job_duration")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("status"),children:["Status",S("status")]}),(0,r.jsxs)(h.ss,{className:"sortable whitespace-nowrap",onClick:()=>_("resources"),children:["Resources",S("resources")]}),(0,r.jsx)(h.ss,{className:"whitespace-nowrap",children:"Logs"})]})}),(0,r.jsx)(h.RM,{children:D.length>0?D.map(e=>(0,r.jsxs)(n.Fragment,{children:[(0,r.jsxs)(h.SC,{className:l===e.id?"selected-row":"",children:[(0,r.jsx)(h.pj,{children:(0,r.jsx)(c(),{href:"/clusters/".concat(s,"/").concat(e.id),className:"text-blue-600",children:e.id})}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(c(),{href:"/clusters/".concat(s,"/").concat(e.id),className:"text-blue-600",children:(0,r.jsx)(A,{text:e.job||"Unnamed job",rowId:e.id,expandedRowId:l,setExpandedRowId:x})})}),(0,r.jsx)(h.pj,{children:e.user}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(c(),{href:"/workspaces",className:"text-blue-600 hover:underline",children:e.workspace||"default"})}),(0,r.jsx)(h.pj,{children:L(e.submitted_at)}),(0,r.jsx)(h.pj,{children:(0,u.LU)(e.job_duration)}),(0,r.jsx)(h.pj,{children:(0,r.jsx)(k.OE,{status:e.status})}),(0,r.jsx)(h.pj,{children:e.resources}),(0,r.jsx)(h.pj,{className:"flex content-center items-center",children:(0,r.jsx)(M,{jobParent:"/clusters/".concat(s),jobId:e.id,managed:!1})})]}),l===e.id&&(0,r.jsx)(I,{text:e.job||"Unnamed job",colSpan:9,innerRef:b})]},e.id)):(0,r.jsx)(h.SC,{children:(0,r.jsx)(h.pj,{colSpan:9,className:"text-center py-6 text-gray-500",children:"No jobs found"})})})]})]}),C.length>0&&(0,r.jsx)("div",{className:"flex justify-end items-center py-2 px-4 text-sm text-gray-700",children:(0,r.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)("span",{className:"mr-2",children:"Rows per page:"}),(0,r.jsxs)("div",{className:"relative inline-block",children:[(0,r.jsxs)("select",{value:g,onChange:e=>{w(parseInt(e.target.value,10)),f(1)},className:"py-1 pl-2 pr-6 appearance-none outline-none cursor-pointer border-none bg-transparent",style:{minWidth:"40px"},children:[(0,r.jsx)("option",{value:5,children:"5"}),(0,r.jsx)("option",{value:10,children:"10"}),(0,r.jsx)("option",{value:20,children:"20"}),(0,r.jsx)("option",{value:50,children:"50"})]}),(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-gray-500 absolute right-0 top-1/2 transform -translate-y-1/2 pointer-events-none",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]})]}),(0,r.jsxs)("div",{children:[R+1," – ",Math.min(O,C.length)," of"," ",C.length]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{f(e=>Math.max(e-1,1))},disabled:1===j,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-left",children:(0,r.jsx)("path",{d:"M15 18l-6-6 6-6"})})}),(0,r.jsx)(o.z,{variant:"ghost",size:"icon",onClick:()=>{f(e=>Math.min(e+1,E))},disabled:j===E||0===E,className:"text-gray-500 h-8 w-8 p-0",children:(0,r.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"chevron-right",children:(0,r.jsx)("path",{d:"M9 18l6-6-6-6"})})})]})]})})]})}function I(e){let{text:s,colSpan:t,innerRef:n}=e;return(0,r.jsx)(h.SC,{className:"expanded-details",children:(0,r.jsx)(h.pj,{colSpan:t,children:(0,r.jsx)("div",{className:"p-4 bg-gray-50 rounded-md border border-gray-200",ref:n,children:(0,r.jsx)("div",{className:"flex justify-between items-start",children:(0,r.jsxs)("div",{className:"flex-1",children:[(0,r.jsx)("p",{className:"text-sm font-medium text-gray-900",children:"Full Details"}),(0,r.jsx)("p",{className:"mt-1 text-sm text-gray-700",style:{whiteSpace:"pre-wrap"},children:s})]})})})})})}function A(e){let{text:s,rowId:t,expandedRowId:a,setExpandedRowId:l}=e,c=s.length>50,i=a===t,o=c?"".concat(s.substring(0,50)):s,d=(0,n.useRef)(null);return(0,r.jsxs)("div",{className:"truncated-details relative max-w-full flex items-center",children:[(0,r.jsx)("span",{className:"truncate",children:o}),c&&(0,r.jsx)("button",{ref:d,type:"button",onClick:e=>{e.preventDefault(),e.stopPropagation(),l(i?null:t)},className:"text-blue-600 hover:text-blue-800 font-medium ml-1 flex-shrink-0","data-button-type":"show-more-less",children:i?"... show less":"... show more"})]})}},8969:function(e,s,t){t.d(s,{Ce:function(){return o},NJ:function(){return i},Pr:function(){return c},Vp:function(){return l}});var r=t(7294),n=t(5821),a=t(3225);async function l(){let{allUsers:e=!0}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{let s=(await fetch("".concat(a.f4,"/jobs/queue"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({all_users:e})})).headers.get("X-Skypilot-Request-ID"),t=await fetch("".concat(a.f4,"/api/get?request_id=").concat(s));if(500===t.status){try{let e=await t.json();if(e.detail&&e.detail.error)try{let s=JSON.parse(e.detail.error);if(s.type&&s.type===a.iW)return{jobs:[],controllerStopped:!0}}catch(e){console.error("Error parsing JSON:",e)}}catch(e){console.error("Error parsing JSON:",e)}return{jobs:[],controllerStopped:!1}}let r=await t.json();return{jobs:(r.return_value?JSON.parse(r.return_value):[]).map(e=>{let s=[];e.submitted_at&&s.push({time:new Date(1e3*e.submitted_at),event:"Job submitted."}),e.start_at&&s.push({time:new Date(1e3*e.start_at),event:"Job started."}),e.end_at&&("CANCELLING"==e.status||"CANCELLED"==e.status?s.push({time:new Date(1e3*e.end_at),event:"Job cancelled."}):s.push({time:new Date(1e3*e.end_at),event:"Job completed."})),e.last_recovered_at&&e.last_recovered_at!=e.start_at&&s.push({time:new Date(1e3*e.last_recovered_at),event:"Job recovered."});let t=(e.end_at?e.end_at:Date.now()/1e3)-e.submitted_at,r=e.cloud,n=e.cluster_resources;if(!r){if(e.cluster_resources&&"-"!==e.cluster_resources)try{r=e.cluster_resources.split("(")[0].split("x").pop().trim(),n=e.cluster_resources.replace("".concat(r,"("),"(").replace("x ","x")}catch(e){r="Unknown"}else r="Unknown"}let a="",l=a=e.zone?e.zone:e.region;a&&a.length>15&&(a=a.substring(0,15)+"...");let c=r+" ("+a+")";"-"===a&&(c=r);let i=r+" ("+l+")";return"-"===l&&(i=r),{id:e.job_id,task:e.task_name,name:e.job_name,job_duration:e.job_duration,total_duration:t,workspace:e.workspace,status:e.status,requested_resources:e.resources,resources_str:n,resources_str_full:e.cluster_resources_full||n,cloud:r,infra:c,full_infra:i,recoveries:e.recovery_count,details:e.failure_reason,user:e.user_name,user_hash:e.user_hash,submitted_at:e.submitted_at?new Date(1e3*e.submitted_at):null,events:s}}),controllerStopped:!1}}catch(e){return console.error("Error fetching managed job data:",e),{jobs:[],controllerStopped:!1}}}function c(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,[s,t]=(0,r.useState)(null),[n,a]=(0,r.useState)(!0);return(0,r.useEffect)(()=>{(async function(){try{a(!0);let e=await l({allUsers:!0});t(e)}catch(e){console.error("Error fetching managed job data:",e)}finally{a(!1)}})()},[e]),{jobData:s,loading:n}}async function i(e){let{jobId:s,controller:t=!1,signal:r,onNewLog:l}=e,c=new Promise(e=>{setTimeout(()=>{e({timeout:!0})},1e4)}),i=(async()=>{try{let e=(await fetch("".concat(a.f4,"/jobs/logs"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({controller:t,follow:!1,job_id:s}),...r?{signal:r}:{}})).body.getReader();try{for(;;){let{done:s,value:t}=await e.read();if(s)break;let r=new TextDecoder().decode(t);l(r)}}finally{e.cancel()}return{timeout:!1}}catch(e){if("AbortError"===e.name)return{timeout:!1};throw e}})();if((await Promise.race([i,c])).timeout){(0,n.C)("Log request for job ".concat(s," timed out after ").concat(1e4,"ms"),"error");return}}async function o(e,s,t){let r="",l="",c="",i={};if("restartcontroller"===e)r="Restarting",l="restarted",c="jobs/queue",i={all_users:!0,refresh:!0},s="controller";else throw Error("Invalid action: ".concat(e));(0,n.C)("".concat(r," job ").concat(s,"..."),"info");try{try{let e=(await fetch("".concat(a.f4,"/").concat(c),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)})).headers.get("X-Skypilot-Request-ID"),o=await fetch("".concat(a.f4,"/api/get?request_id=").concat(e));if(200===o.status)(0,n.C)("Job ".concat(s," ").concat(l," successfully."),"success");else if(500===o.status)try{let e=await o.json();if(e.detail&&e.detail.error)try{let l=JSON.parse(e.detail.error);l.type&&l.type===a.Bo?(0,n.C)("".concat(r," job ").concat(s," is not supported!"),"error",1e4):l.type&&l.type===a.mF?(0,n.C)("Cluster ".concat(t," does not exist."),"error"):l.type&&l.type===a.iW?(0,n.C)("Cluster ".concat(t," is not up."),"error"):(0,n.C)("".concat(r," job ").concat(s," failed: ").concat(l.type),"error")}catch(t){(0,n.C)("".concat(r," job ").concat(s," failed: ").concat(e.detail.error),"error")}else(0,n.C)("".concat(r," job ").concat(s," failed with no details."),"error")}catch(e){(0,n.C)("".concat(r," job ").concat(s," failed with parse error."),"error")}else(0,n.C)("".concat(r," job ").concat(s," failed with status ").concat(o.status,"."),"error")}catch(e){console.error("Fetch error:",e),(0,n.C)("Network error ".concat(r," job ").concat(s,": ").concat(e.message),"error")}}catch(e){console.error("Error in handleStop:",e),(0,n.C)("Critical error ".concat(r," job ").concat(s,": ").concat(e.message),"error")}}}}]);
|