skypilot-nightly 1.0.0.dev20250812__py3-none-any.whl → 1.0.0.dev20250814__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.

Potentially problematic release.


This version of skypilot-nightly might be problematic. Click here for more details.

Files changed (102) hide show
  1. sky/__init__.py +4 -2
  2. sky/backends/backend_utils.py +69 -6
  3. sky/backends/cloud_vm_ray_backend.py +156 -25
  4. sky/catalog/cudo_catalog.py +1 -1
  5. sky/catalog/data_fetchers/fetch_cudo.py +1 -1
  6. sky/catalog/data_fetchers/fetch_nebius.py +6 -3
  7. sky/client/cli/command.py +40 -77
  8. sky/client/common.py +1 -1
  9. sky/client/sdk.py +19 -19
  10. sky/client/sdk_async.py +5 -4
  11. sky/clouds/aws.py +52 -1
  12. sky/clouds/kubernetes.py +14 -0
  13. sky/dag.py +1 -0
  14. sky/dashboard/out/404.html +1 -1
  15. sky/dashboard/out/_next/static/{Fuy7OzApYTUMz2QgoP7dP → Y0eNlwi85qGRecLTin11y}/_buildManifest.js +1 -1
  16. sky/dashboard/out/_next/static/chunks/{6989-6129c1cfbcf51063.js → 6989-37611fe6b86d274d.js} +1 -1
  17. sky/dashboard/out/_next/static/chunks/pages/{_app-491a4d699d95e808.js → _app-c2ea34fda4f1f8c8.js} +1 -1
  18. sky/dashboard/out/_next/static/chunks/pages/jobs/pools/{[pool]-f5ccf5d39d87aebe.js → [pool]-664c36eda967b1ba.js} +1 -1
  19. sky/dashboard/out/_next/static/chunks/{webpack-7fd0cf9dbecff10f.js → webpack-00c0a51d21157453.js} +1 -1
  20. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  21. sky/dashboard/out/clusters/[cluster].html +1 -1
  22. sky/dashboard/out/clusters.html +1 -1
  23. sky/dashboard/out/config.html +1 -1
  24. sky/dashboard/out/index.html +1 -1
  25. sky/dashboard/out/infra/[context].html +1 -1
  26. sky/dashboard/out/infra.html +1 -1
  27. sky/dashboard/out/jobs/[job].html +1 -1
  28. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  29. sky/dashboard/out/jobs.html +1 -1
  30. sky/dashboard/out/users.html +1 -1
  31. sky/dashboard/out/volumes.html +1 -1
  32. sky/dashboard/out/workspace/new.html +1 -1
  33. sky/dashboard/out/workspaces/[name].html +1 -1
  34. sky/dashboard/out/workspaces.html +1 -1
  35. sky/data/storage.py +11 -1
  36. sky/exceptions.py +5 -0
  37. sky/global_user_state.py +63 -7
  38. sky/jobs/constants.py +1 -1
  39. sky/jobs/controller.py +0 -1
  40. sky/jobs/recovery_strategy.py +3 -3
  41. sky/jobs/scheduler.py +23 -68
  42. sky/jobs/server/core.py +18 -12
  43. sky/jobs/state.py +6 -2
  44. sky/jobs/utils.py +8 -0
  45. sky/provision/__init__.py +1 -0
  46. sky/provision/aws/config.py +9 -0
  47. sky/provision/aws/instance.py +36 -13
  48. sky/provision/azure/instance.py +2 -0
  49. sky/provision/cudo/cudo_wrapper.py +1 -1
  50. sky/provision/cudo/instance.py +2 -0
  51. sky/provision/do/instance.py +2 -0
  52. sky/provision/fluidstack/instance.py +2 -0
  53. sky/provision/gcp/instance.py +2 -0
  54. sky/provision/hyperbolic/instance.py +2 -1
  55. sky/provision/kubernetes/instance.py +133 -0
  56. sky/provision/lambda_cloud/instance.py +2 -0
  57. sky/provision/nebius/instance.py +2 -0
  58. sky/provision/oci/instance.py +2 -0
  59. sky/provision/paperspace/instance.py +2 -1
  60. sky/provision/paperspace/utils.py +1 -1
  61. sky/provision/runpod/instance.py +2 -0
  62. sky/provision/runpod/utils.py +1 -1
  63. sky/provision/scp/instance.py +2 -0
  64. sky/provision/vast/instance.py +2 -0
  65. sky/provision/vsphere/instance.py +2 -0
  66. sky/resources.py +1 -2
  67. sky/schemas/__init__.py +0 -0
  68. sky/schemas/api/__init__.py +0 -0
  69. sky/schemas/api/responses.py +70 -0
  70. sky/schemas/generated/__init__.py +0 -0
  71. sky/schemas/generated/autostopv1_pb2.py +36 -0
  72. sky/schemas/generated/autostopv1_pb2.pyi +43 -0
  73. sky/schemas/generated/autostopv1_pb2_grpc.py +146 -0
  74. sky/serve/constants.py +3 -7
  75. sky/serve/replica_managers.py +15 -16
  76. sky/serve/serve_state.py +10 -0
  77. sky/serve/serve_utils.py +21 -20
  78. sky/serve/server/impl.py +15 -19
  79. sky/serve/service.py +31 -16
  80. sky/server/server.py +20 -14
  81. sky/setup_files/dependencies.py +11 -10
  82. sky/skylet/autostop_lib.py +38 -5
  83. sky/skylet/constants.py +3 -1
  84. sky/skylet/services.py +44 -0
  85. sky/skylet/skylet.py +49 -4
  86. sky/task.py +19 -16
  87. sky/templates/aws-ray.yml.j2 +2 -2
  88. sky/templates/jobs-controller.yaml.j2 +6 -0
  89. sky/utils/command_runner.py +1 -1
  90. sky/utils/config_utils.py +29 -5
  91. sky/utils/controller_utils.py +73 -0
  92. sky/utils/db/db_utils.py +17 -0
  93. sky/utils/schemas.py +3 -0
  94. sky/volumes/server/core.py +2 -2
  95. sky/volumes/server/server.py +2 -2
  96. {skypilot_nightly-1.0.0.dev20250812.dist-info → skypilot_nightly-1.0.0.dev20250814.dist-info}/METADATA +5 -7
  97. {skypilot_nightly-1.0.0.dev20250812.dist-info → skypilot_nightly-1.0.0.dev20250814.dist-info}/RECORD +102 -94
  98. /sky/dashboard/out/_next/static/{Fuy7OzApYTUMz2QgoP7dP → Y0eNlwi85qGRecLTin11y}/_ssgManifest.js +0 -0
  99. {skypilot_nightly-1.0.0.dev20250812.dist-info → skypilot_nightly-1.0.0.dev20250814.dist-info}/WHEEL +0 -0
  100. {skypilot_nightly-1.0.0.dev20250812.dist-info → skypilot_nightly-1.0.0.dev20250814.dist-info}/entry_points.txt +0 -0
  101. {skypilot_nightly-1.0.0.dev20250812.dist-info → skypilot_nightly-1.0.0.dev20250814.dist-info}/licenses/LICENSE +0 -0
  102. {skypilot_nightly-1.0.0.dev20250812.dist-info → skypilot_nightly-1.0.0.dev20250814.dist-info}/top_level.txt +0 -0
sky/client/cli/command.py CHANGED
@@ -275,65 +275,6 @@ def _merge_env_vars(env_dict: Optional[Dict[str, str]],
275
275
  return list(env_dict.items())
276
276
 
277
277
 
278
- def _format_job_ids_str(job_ids: List[int], max_length: int = 30) -> str:
279
- """Format job IDs string with ellipsis if too long.
280
-
281
- Args:
282
- job_ids: List of job IDs to format.
283
- max_length: Maximum length of the output string.
284
-
285
- Returns:
286
- Formatted string like "11,12,...,2017,2018" if truncated,
287
- or the full string if it fits within max_length.
288
- """
289
- if not job_ids:
290
- return ''
291
-
292
- # Convert all to strings
293
- job_strs = [str(job_id) for job_id in job_ids]
294
- full_str = ','.join(job_strs)
295
-
296
- # If it fits, return as is
297
- if len(full_str) <= max_length:
298
- return full_str
299
-
300
- if len(job_strs) <= 2:
301
- return full_str # Can't truncate further
302
-
303
- # Need to truncate with ellipsis
304
- ellipsis = '...'
305
-
306
- # Start with minimum: first and last
307
- start_count = 1
308
- end_count = 1
309
-
310
- while start_count + end_count < len(job_strs):
311
- # Try adding one more to start
312
- if start_count + 1 + end_count < len(job_strs):
313
- start_part = ','.join(job_strs[:start_count + 1])
314
- end_part = ','.join(job_strs[-end_count:])
315
- candidate = f'{start_part},{ellipsis},{end_part}'
316
- if len(candidate) <= max_length:
317
- start_count += 1
318
- continue
319
-
320
- # Try adding one more to end
321
- if start_count + end_count + 1 < len(job_strs):
322
- start_part = ','.join(job_strs[:start_count])
323
- end_part = ','.join(job_strs[-(end_count + 1):])
324
- candidate = f'{start_part},{ellipsis},{end_part}'
325
- if len(candidate) <= max_length:
326
- end_count += 1
327
- continue
328
-
329
- # Can't add more
330
- break
331
-
332
- start_part = ','.join(job_strs[:start_count])
333
- end_part = ','.join(job_strs[-end_count:])
334
- return f'{start_part},{ellipsis},{end_part}'
335
-
336
-
337
278
  def _complete_cluster_name(ctx: click.Context, param: click.Parameter,
338
279
  incomplete: str) -> List[str]:
339
280
  """Handle shell completion for cluster names."""
@@ -1187,11 +1128,15 @@ def launch(
1187
1128
  raise ValueError(f'{backend_name} backend is not supported.')
1188
1129
 
1189
1130
  if task.service is not None:
1131
+ noun = 'pool' if task.service.pool else 'service'
1132
+ capnoun = noun.capitalize()
1133
+ sysname = 'Jobs Worker Pool' if task.service.pool else 'SkyServe'
1134
+ cmd = 'sky jobs pool apply' if task.service.pool else 'sky serve up'
1190
1135
  logger.info(
1191
- f'{colorama.Fore.YELLOW}Service section will be ignored when using '
1192
- f'`sky launch`. {colorama.Style.RESET_ALL}\n{colorama.Fore.YELLOW}'
1193
- 'To spin up a service, use SkyServe CLI: '
1194
- f'{colorama.Style.RESET_ALL}{colorama.Style.BRIGHT}sky serve up'
1136
+ f'{colorama.Fore.YELLOW}{capnoun} section will be ignored when '
1137
+ f'using `sky launch`. {colorama.Style.RESET_ALL}\n'
1138
+ f'{colorama.Fore.YELLOW}To spin up a {noun}, use {sysname} CLI: '
1139
+ f'{colorama.Style.RESET_ALL}{colorama.Style.BRIGHT}{cmd}'
1195
1140
  f'{colorama.Style.RESET_ALL}')
1196
1141
 
1197
1142
  request_id = sdk.launch(
@@ -2981,15 +2926,15 @@ def _hint_or_raise_for_down_jobs_controller(controller_name: str,
2981
2926
  controller = controller_utils.Controllers.from_name(controller_name)
2982
2927
  assert controller is not None, controller_name
2983
2928
 
2984
- # TODO(tian): We also need to check pools after we allow running pools on
2985
- # jobs controller.
2986
2929
  with rich_utils.client_status(
2987
- '[bold cyan]Checking for in-progress managed jobs[/]'):
2930
+ '[bold cyan]Checking for in-progress managed jobs and pools[/]'):
2988
2931
  try:
2989
2932
  request_id = managed_jobs.queue(refresh=False,
2990
2933
  skip_finished=True,
2991
2934
  all_users=True)
2992
2935
  managed_jobs_ = sdk.stream_and_get(request_id)
2936
+ request_id_pools = managed_jobs.pool_status(pool_names=None)
2937
+ pools_ = sdk.stream_and_get(request_id_pools)
2993
2938
  except exceptions.ClusterNotUpError as e:
2994
2939
  if controller.value.connection_error_hint in str(e):
2995
2940
  with ux_utils.print_exception_no_traceback():
@@ -3004,6 +2949,7 @@ def _hint_or_raise_for_down_jobs_controller(controller_name: str,
3004
2949
  # the controller being STOPPED or being firstly launched, i.e.,
3005
2950
  # there is no in-prgress managed jobs.
3006
2951
  managed_jobs_ = []
2952
+ pools_ = []
3007
2953
  except exceptions.InconsistentConsolidationModeError:
3008
2954
  # If this error is raised, it means the user switched to the
3009
2955
  # consolidation mode but the previous controller cluster is still
@@ -3021,6 +2967,8 @@ def _hint_or_raise_for_down_jobs_controller(controller_name: str,
3021
2967
  skip_finished=True,
3022
2968
  all_users=True)
3023
2969
  managed_jobs_ = sdk.stream_and_get(request_id)
2970
+ request_id_pools = managed_jobs.pool_status(pool_names=None)
2971
+ pools_ = sdk.stream_and_get(request_id_pools)
3024
2972
 
3025
2973
  msg = (f'{colorama.Fore.YELLOW}WARNING: Tearing down the managed '
3026
2974
  'jobs controller. Please be aware of the following:'
@@ -3042,9 +2990,23 @@ def _hint_or_raise_for_down_jobs_controller(controller_name: str,
3042
2990
  else:
3043
2991
  with ux_utils.print_exception_no_traceback():
3044
2992
  raise exceptions.NotSupportedError(msg)
2993
+ elif pools_:
2994
+ pool_names = ', '.join([pool['name'] for pool in pools_])
2995
+ if purge:
2996
+ logger.warning('--purge is set, ignoring the in-progress pools. '
2997
+ 'This could cause leaked clusters!')
2998
+ else:
2999
+ msg = (f'{colorama.Fore.YELLOW}WARNING: Tearing down the managed '
3000
+ 'jobs controller is not supported, as it is currently '
3001
+ f'hosting the following pools: {pool_names}. Please '
3002
+ 'terminate the pools first with '
3003
+ f'{colorama.Style.BRIGHT}sky jobs pool down -a'
3004
+ f'{colorama.Style.RESET_ALL}.')
3005
+ with ux_utils.print_exception_no_traceback():
3006
+ raise exceptions.NotSupportedError(msg)
3045
3007
  else:
3046
- click.echo(' * No in-progress managed jobs found. It should be safe to '
3047
- 'terminate (see caveats above).')
3008
+ click.echo(' * No in-progress managed jobs or running pools found. It '
3009
+ 'should be safe to terminate (see caveats above).')
3048
3010
 
3049
3011
 
3050
3012
  def _hint_or_raise_for_down_sky_serve_controller(controller_name: str,
@@ -4509,8 +4471,8 @@ def jobs_launch(
4509
4471
  if print_setup_fm_warning:
4510
4472
  click.secho(
4511
4473
  f'{colorama.Fore.YELLOW}setup/file_mounts/storage_mounts'
4512
- ' will be ignored in pool. To update a pool, please '
4513
- f'use `sky pool apply {pool} pool.yaml`. '
4474
+ ' will be ignored when submit jobs to pool. To update a pool, '
4475
+ f'please use `sky jobs pool apply {pool} new-pool.yaml`. '
4514
4476
  f'{colorama.Style.RESET_ALL}')
4515
4477
 
4516
4478
  # Optimize info is only show if _need_confirmation.
@@ -4537,7 +4499,9 @@ def jobs_launch(
4537
4499
  controller=False)
4538
4500
  sys.exit(returncode)
4539
4501
  else:
4540
- job_ids_str = _format_job_ids_str(job_ids)
4502
+ # TODO(tian): This can be very long. Considering have a "group id"
4503
+ # and query all job ids with the same group id.
4504
+ job_ids_str = ','.join(map(str, job_ids))
4541
4505
  click.secho(
4542
4506
  f'Jobs submitted with IDs: {colorama.Fore.CYAN}'
4543
4507
  f'{job_ids_str}{colorama.Style.RESET_ALL}.'
@@ -6212,16 +6176,15 @@ def api_info():
6212
6176
  """Shows the SkyPilot API server URL."""
6213
6177
  url = server_common.get_server_url()
6214
6178
  api_server_info = sdk.api_info()
6215
- api_server_user = api_server_info.get('user')
6179
+ api_server_user = api_server_info.user
6216
6180
  if api_server_user is not None:
6217
- user = models.User(id=api_server_user['id'],
6218
- name=api_server_user['name'])
6181
+ user = api_server_user
6219
6182
  else:
6220
6183
  user = models.User.get_current_user()
6221
6184
  click.echo(f'Using SkyPilot API server and dashboard: {url}\n'
6222
- f'{ux_utils.INDENT_SYMBOL}Status: {api_server_info["status"]}, '
6223
- f'commit: {api_server_info["commit"]}, '
6224
- f'version: {api_server_info["version"]}\n'
6185
+ f'{ux_utils.INDENT_SYMBOL}Status: {api_server_info.status}, '
6186
+ f'commit: {api_server_info.commit}, '
6187
+ f'version: {api_server_info.version}\n'
6225
6188
  f'{ux_utils.INDENT_LAST_SYMBOL}User: {user.name} ({user.id})')
6226
6189
 
6227
6190
 
sky/client/common.py CHANGED
@@ -32,7 +32,7 @@ if typing.TYPE_CHECKING:
32
32
  import requests
33
33
 
34
34
  import sky
35
- import sky.dag as dag_lib
35
+ from sky import dag as dag_lib
36
36
  else:
37
37
  httpx = adaptors_common.LazyImport('httpx')
38
38
  requests = adaptors_common.LazyImport('requests')
sky/client/sdk.py CHANGED
@@ -30,6 +30,7 @@ from sky import skypilot_config
30
30
  from sky.adaptors import common as adaptors_common
31
31
  from sky.client import common as client_common
32
32
  from sky.client import oauth as oauth_lib
33
+ from sky.schemas.api import responses
33
34
  from sky.server import common as server_common
34
35
  from sky.server import rest
35
36
  from sky.server import versions
@@ -66,8 +67,8 @@ if typing.TYPE_CHECKING:
66
67
 
67
68
  import sky
68
69
  from sky import backends
70
+ from sky import catalog
69
71
  from sky import models
70
- import sky.catalog
71
72
  from sky.provision.kubernetes import utils as kubernetes_utils
72
73
  from sky.skylet import job_lib
73
74
  else:
@@ -234,7 +235,7 @@ def list_accelerators(
234
235
  require_price: bool = True,
235
236
  case_sensitive: bool = True
236
237
  ) -> server_common.RequestId[Dict[str,
237
- List['sky.catalog.common.InstanceTypeInfo']]]:
238
+ List['catalog.common.InstanceTypeInfo']]]:
238
239
  """Lists the names of all accelerators offered by Sky.
239
240
 
240
241
  This will include all accelerators offered by Sky, including those
@@ -479,11 +480,11 @@ def launch(
479
480
  This option works in conjunction with ``idle_minutes_to_autostop``.
480
481
  Choices:
481
482
 
482
- 1. "jobs_and_ssh" (default) - Wait for all jobs to complete
483
- AND all SSH sessions to disconnect.
484
- 2. "jobs" - Wait for all jobs to complete.
485
- 3. "none" - Stop immediately after idle time expires,
486
- regardless of running jobs or SSH connections.
483
+ 1. "jobs_and_ssh" (default) - Wait for in-progress jobs and SSH
484
+ connections to finish.
485
+ 2. "jobs" - Only wait for in-progress jobs.
486
+ 3. "none" - Wait for nothing; autostop right after
487
+ ``idle_minutes_to_autostop``.
487
488
  dryrun: if True, do not actually launch the cluster.
488
489
  down: Tear down the cluster after all jobs finish (successfully or
489
490
  abnormally). If --idle-minutes-to-autostop is also set, the
@@ -935,11 +936,11 @@ def start(
935
936
  This option works in conjunction with ``idle_minutes_to_autostop``.
936
937
  Choices:
937
938
 
938
- 1. "jobs_and_ssh" (default) - Wait for all jobs to complete
939
- AND all SSH sessions to disconnect.
940
- 2. "jobs" - Wait for all jobs to complete.
941
- 3. "none" - Stop immediately after idle time expires,
942
- regardless of running jobs or SSH connections.
939
+ 1. "jobs_and_ssh" (default) - Wait for in-progress jobs and SSH
940
+ connections to finish.
941
+ 2. "jobs" - Only wait for in-progress jobs.
942
+ 3. "none" - Wait for nothing; autostop right after
943
+ ``idle_minutes_to_autostop``.
943
944
  retry_until_up: whether to retry launching the cluster until it is
944
945
  up.
945
946
  down: Autodown the cluster: tear down the cluster after specified
@@ -1118,11 +1119,10 @@ def autostop(
1118
1119
  This option works in conjunction with ``idle_minutes``.
1119
1120
  Choices:
1120
1121
 
1121
- 1. "jobs_and_ssh" (default) - Wait for all jobs to complete
1122
- AND all SSH sessions to disconnect.
1123
- 2. "jobs" - Wait for all jobs to complete.
1124
- 3. "none" - Stop immediately after idle time expires,
1125
- regardless of running jobs or SSH connections.
1122
+ 1. "jobs_and_ssh" (default) - Wait for in-progress jobs and SSH
1123
+ connections to finish.
1124
+ 2. "jobs" - Only wait for in-progress jobs.
1125
+ 3. "none" - Wait for nothing; autostop right after ``idle_minutes``.
1126
1126
  down: if true, use autodown (tear down the cluster; non-restartable),
1127
1127
  rather than autostop (restartable).
1128
1128
 
@@ -2059,7 +2059,7 @@ def api_status(
2059
2059
  @usage_lib.entrypoint
2060
2060
  @server_common.check_server_healthy_or_start
2061
2061
  @annotations.client_api
2062
- def api_info() -> Dict[str, Any]:
2062
+ def api_info() -> responses.APIHealthResponse:
2063
2063
  """Gets the server's status, commit and version.
2064
2064
 
2065
2065
  Returns:
@@ -2084,7 +2084,7 @@ def api_info() -> Dict[str, Any]:
2084
2084
  """
2085
2085
  response = server_common.make_authenticated_request('GET', '/api/health')
2086
2086
  response.raise_for_status()
2087
- return response.json()
2087
+ return responses.APIHealthResponse(**response.json())
2088
2088
 
2089
2089
 
2090
2090
  @usage_lib.entrypoint
sky/client/sdk_async.py CHANGED
@@ -20,13 +20,14 @@ import colorama
20
20
 
21
21
  from sky import admin_policy
22
22
  from sky import backends
23
+ from sky import catalog
23
24
  from sky import exceptions
24
25
  from sky import models
25
26
  from sky import sky_logging
26
- import sky.catalog
27
27
  from sky.client import common as client_common
28
28
  from sky.client import sdk
29
29
  from sky.provision.kubernetes import utils as kubernetes_utils
30
+ from sky.schemas.api import responses
30
31
  from sky.server import common as server_common
31
32
  from sky.server import rest
32
33
  from sky.server.requests import payloads
@@ -301,7 +302,7 @@ async def list_accelerators(
301
302
  require_price: bool = True,
302
303
  case_sensitive: bool = True,
303
304
  stream_logs: Optional[StreamConfig] = DEFAULT_STREAM_CONFIG
304
- ) -> Dict[str, List[sky.catalog.common.InstanceTypeInfo]]:
305
+ ) -> Dict[str, List[catalog.common.InstanceTypeInfo]]:
305
306
  """Async version of list_accelerators() that lists the names of all
306
307
  accelerators offered by Sky."""
307
308
  request_id = await context_utils.to_thread(sdk.list_accelerators, gpus_only,
@@ -345,7 +346,7 @@ async def optimize(
345
346
  admin_policy_request_options: Optional[
346
347
  admin_policy.RequestOptions] = None,
347
348
  stream_logs: Optional[StreamConfig] = DEFAULT_STREAM_CONFIG
348
- ) -> sky.dag.Dag:
349
+ ) -> 'sky.Dag':
349
350
  """Async version of optimize() that finds the best execution plan for the
350
351
  given DAG."""
351
352
  request_id = await context_utils.to_thread(sdk.optimize, dag, minimize,
@@ -786,7 +787,7 @@ async def dashboard(starting_page: Optional[str] = None) -> None:
786
787
 
787
788
  @usage_lib.entrypoint
788
789
  @annotations.client_api
789
- async def api_info() -> Dict[str, Any]:
790
+ async def api_info() -> responses.APIHealthResponse:
790
791
  """Async version of api_info() that gets the server's status, commit and
791
792
  version."""
792
793
  return await context_utils.to_thread(sdk.api_info)
sky/clouds/aws.py CHANGED
@@ -65,6 +65,8 @@ _CREDENTIAL_FILES = [
65
65
  ]
66
66
 
67
67
  DEFAULT_AMI_GB = 45
68
+ DEFAULT_SSH_USER = 'ubuntu'
69
+ DEFAULT_ROOT_DEVICE_NAME = '/dev/sda1'
68
70
 
69
71
  # Temporary measure, as deleting per-cluster SGs is too slow.
70
72
  # See https://github.com/skypilot-org/skypilot/pull/742.
@@ -343,6 +345,44 @@ class AWS(clouds.Cloud):
343
345
  raise ValueError(image_not_found_message) from None
344
346
  return image_size
345
347
 
348
+ @classmethod
349
+ @annotations.lru_cache(scope='request', maxsize=1)
350
+ def get_image_root_device_name(cls, image_id: str,
351
+ region: Optional[str]) -> str:
352
+ if image_id.startswith('skypilot:'):
353
+ return DEFAULT_ROOT_DEVICE_NAME
354
+ assert region is not None, (image_id, region)
355
+ image_not_found_message = (
356
+ f'Image {image_id!r} not found in AWS region {region}.\n'
357
+ f'To find AWS AMI IDs: https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html#examples\n' # pylint: disable=line-too-long
358
+ 'Example: ami-0729d913a335efca7')
359
+ try:
360
+ client = aws.client('ec2', region_name=region)
361
+ image_info = client.describe_images(ImageIds=[image_id]).get(
362
+ 'Images', [])
363
+ if not image_info:
364
+ with ux_utils.print_exception_no_traceback():
365
+ raise ValueError(image_not_found_message)
366
+ image = image_info[0]
367
+ if 'RootDeviceName' not in image:
368
+ logger.warning(f'Image {image_id!r} does not have a root '
369
+ f'device name. '
370
+ f'Using {DEFAULT_ROOT_DEVICE_NAME}.')
371
+ return DEFAULT_ROOT_DEVICE_NAME
372
+ return image['RootDeviceName']
373
+ except (aws.botocore_exceptions().NoCredentialsError,
374
+ aws.botocore_exceptions().ProfileNotFound):
375
+ # Fallback to default root device name if no credentials are
376
+ # available.
377
+ # The credentials issue will be caught when actually provisioning
378
+ # the instance and appropriate errors will be raised there.
379
+ logger.warning(f'No credentials available for region {region}. '
380
+ f'Using {DEFAULT_ROOT_DEVICE_NAME}.')
381
+ return DEFAULT_ROOT_DEVICE_NAME
382
+ except aws.botocore_exceptions().ClientError:
383
+ with ux_utils.print_exception_no_traceback():
384
+ raise ValueError(image_not_found_message) from None
385
+
346
386
  @classmethod
347
387
  def get_zone_shell_cmd(cls) -> Optional[str]:
348
388
  # The command for getting the current zone is from:
@@ -466,6 +506,15 @@ class AWS(clouds.Cloud):
466
506
  image_id = self._get_image_id(image_id_to_use, region_name,
467
507
  resources.instance_type)
468
508
 
509
+ root_device_name = self.get_image_root_device_name(
510
+ image_id, region_name)
511
+
512
+ ssh_user = skypilot_config.get_effective_region_config(
513
+ cloud='aws',
514
+ region=region_name,
515
+ keys=('ssh_user',),
516
+ default_value=DEFAULT_SSH_USER)
517
+
469
518
  disk_encrypted = skypilot_config.get_effective_region_config(
470
519
  cloud='aws',
471
520
  region=region_name,
@@ -509,6 +558,8 @@ class AWS(clouds.Cloud):
509
558
  'region': region_name,
510
559
  'zones': ','.join(zone_names),
511
560
  'image_id': image_id,
561
+ 'root_device_name': root_device_name,
562
+ 'ssh_user': ssh_user,
512
563
  'security_group': security_group,
513
564
  'security_group_managed_by_skypilot':
514
565
  str(security_group != user_security_group).lower(),
@@ -1080,7 +1131,7 @@ class AWS(clouds.Cloud):
1080
1131
 
1081
1132
  image_name = f'skypilot-{cluster_name.display_name}-{int(time.time())}'
1082
1133
 
1083
- status = provision_lib.query_instances('AWS',
1134
+ status = provision_lib.query_instances('AWS', cluster_name.display_name,
1084
1135
  cluster_name.name_on_cloud,
1085
1136
  {'region': region})
1086
1137
  instance_ids = list(status.keys())
sky/clouds/kubernetes.py CHANGED
@@ -771,11 +771,25 @@ class Kubernetes(clouds.Cloud):
771
771
 
772
772
  return deploy_vars
773
773
 
774
+ @staticmethod
775
+ def _warn_on_disk_size(resources: 'resources_lib.Resources'):
776
+ if resources.disk_size is not None:
777
+ logger.info(f'{colorama.Style.DIM}Disk size {resources.disk_size} '
778
+ 'is not supported by Kubernetes. '
779
+ 'To add additional disk, use volumes.'
780
+ f'{colorama.Style.RESET_ALL}')
781
+ if resources.disk_tier is not None:
782
+ logger.info(f'{colorama.Style.DIM}Disk tier {resources.disk_tier} '
783
+ 'is not supported by Kubernetes. '
784
+ 'To add additional disk, use volumes.'
785
+ f'{colorama.Style.RESET_ALL}')
786
+
774
787
  def _get_feasible_launchable_resources(
775
788
  self, resources: 'resources_lib.Resources'
776
789
  ) -> 'resources_utils.FeasibleResources':
777
790
  # TODO(zhwu): This needs to be updated to return the correct region
778
791
  # (context) that has enough resources.
792
+ self._warn_on_disk_size(resources)
779
793
  fuzzy_candidate_list: List[str] = []
780
794
  if resources.instance_type is not None:
781
795
  assert resources.is_launchable(), resources
sky/dag.py CHANGED
@@ -24,6 +24,7 @@ class Dag:
24
24
  self.graph = nx.DiGraph()
25
25
  self.name: Optional[str] = None
26
26
  self.policy_applied: bool = False
27
+ self.pool: Optional[str] = None
27
28
 
28
29
  def add(self, task: 'task.Task') -> None:
29
30
  self.graph.add_node(task)
@@ -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/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.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-7fd0cf9dbecff10f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-491a4d699d95e808.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/Fuy7OzApYTUMz2QgoP7dP/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Fuy7OzApYTUMz2QgoP7dP/_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":"Fuy7OzApYTUMz2QgoP7dP","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
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/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.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-00c0a51d21157453.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-c2ea34fda4f1f8c8.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/Y0eNlwi85qGRecLTin11y/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Y0eNlwi85qGRecLTin11y/_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":"Y0eNlwi85qGRecLTin11y","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- self.__BUILD_MANIFEST=function(s,c,a,e,t,f,u,n,o,r,j,i,b,k,h){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-b30460f683e6ba96.js"],"/clusters/[cluster]":[s,c,a,f,u,j,r,e,t,n,i,b,o,k,h,"static/chunks/1871-980a395e92633a5c.js","static/chunks/pages/clusters/[cluster]-da9cc0901349c2e9.js"],"/clusters/[cluster]/[job]":[s,c,a,f,e,t,o,"static/chunks/pages/clusters/[cluster]/[job]-078751bad714c017.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-fc9222e26c8e2f0d.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-13d53fffc03ccb52.js"],"/jobs":["static/chunks/pages/jobs-cdc60fb5d371e16a.js"],"/jobs/pools/[pool]":[s,c,a,u,r,e,t,n,"static/chunks/pages/jobs/pools/[pool]-f5ccf5d39d87aebe.js"],"/jobs/[job]":[s,c,a,f,u,r,e,t,n,o,"static/chunks/pages/jobs/[job]-154f55cf8af55be5.js"],"/users":["static/chunks/pages/users-7ed36e44e779d5c7.js"],"/volumes":["static/chunks/pages/volumes-c9695d657f78b5dc.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-8f67be60165724cc.js"],"/workspaces/[name]":[s,c,a,f,u,j,e,t,n,i,b,o,k,h,"static/chunks/1141-a8a8f1adba34c892.js","static/chunks/pages/workspaces/[name]-f72f73bcef9541dc.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/pools/[pool]","/jobs/[job]","/users","/volumes","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-3d59f75e2ccf9321.js","static/chunks/6130-2be46d70a38f1e82.js","static/chunks/5739-d67458fcb1386c92.js","static/chunks/6989-6129c1cfbcf51063.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-c9686994ddafcf01.js","static/chunks/6135-85426374db04811e.js","static/chunks/6212-7bd06f60ba693125.js","static/chunks/1559-6c00e20454194859.js","static/chunks/6990-0f886f16e0d55ff8.js","static/chunks/8056-5bdeda81199c0def.js","static/chunks/6601-06114c982db410b6.js","static/chunks/9159-11421c0f2909236f.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
1
+ self.__BUILD_MANIFEST=function(s,c,a,e,t,f,u,n,o,r,j,b,i,k,d){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-b30460f683e6ba96.js"],"/clusters/[cluster]":[s,c,a,f,u,j,r,e,t,n,b,i,o,k,d,"static/chunks/1871-980a395e92633a5c.js","static/chunks/pages/clusters/[cluster]-da9cc0901349c2e9.js"],"/clusters/[cluster]/[job]":[s,c,a,f,e,t,o,"static/chunks/pages/clusters/[cluster]/[job]-078751bad714c017.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-fc9222e26c8e2f0d.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-13d53fffc03ccb52.js"],"/jobs":["static/chunks/pages/jobs-cdc60fb5d371e16a.js"],"/jobs/pools/[pool]":[s,c,a,u,r,e,t,n,"static/chunks/pages/jobs/pools/[pool]-664c36eda967b1ba.js"],"/jobs/[job]":[s,c,a,f,u,r,e,t,n,o,"static/chunks/pages/jobs/[job]-154f55cf8af55be5.js"],"/users":["static/chunks/pages/users-7ed36e44e779d5c7.js"],"/volumes":["static/chunks/pages/volumes-c9695d657f78b5dc.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-8f67be60165724cc.js"],"/workspaces/[name]":[s,c,a,f,u,j,e,t,n,b,i,o,k,d,"static/chunks/1141-a8a8f1adba34c892.js","static/chunks/pages/workspaces/[name]-f72f73bcef9541dc.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/pools/[pool]","/jobs/[job]","/users","/volumes","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-3d59f75e2ccf9321.js","static/chunks/6130-2be46d70a38f1e82.js","static/chunks/5739-d67458fcb1386c92.js","static/chunks/6989-37611fe6b86d274d.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-c9686994ddafcf01.js","static/chunks/6135-85426374db04811e.js","static/chunks/6212-7bd06f60ba693125.js","static/chunks/1559-6c00e20454194859.js","static/chunks/6990-0f886f16e0d55ff8.js","static/chunks/8056-5bdeda81199c0def.js","static/chunks/6601-06114c982db410b6.js","static/chunks/9159-11421c0f2909236f.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -1 +1 @@
1
- "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6989],{88950:function(e,n,t){t.d(n,{Bw:function(){return p},Ph:function(){return d},Ql:function(){return x},i4:function(){return m},ki:function(){return u}});var r=t(85893),a=t(67294),s=t(2067),l=t(45895),o=t(7242),i=t(70282),c=t(32350);let d=s.fC;s.ZA;let u=s.B4,m=a.forwardRef((e,n)=>{let{className:t,children:a,...o}=e;return(0,r.jsxs)(s.xz,{ref:n,className:(0,c.cn)("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",t),...o,children:[a,(0,r.jsx)(s.JO,{asChild:!0,children:(0,r.jsx)(l.Z,{className:"h-4 w-4 opacity-50"})})]})});m.displayName=s.xz.displayName;let f=a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.u_,{ref:n,className:(0,c.cn)("flex cursor-default items-center justify-center py-1",t),...a,children:(0,r.jsx)(o.Z,{className:"h-4 w-4"})})});f.displayName=s.u_.displayName;let h=a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.$G,{ref:n,className:(0,c.cn)("flex cursor-default items-center justify-center py-1",t),...a,children:(0,r.jsx)(l.Z,{className:"h-4 w-4"})})});h.displayName=s.$G.displayName;let p=a.forwardRef((e,n)=>{let{className:t,children:a,position:l="popper",...o}=e;return(0,r.jsx)(s.h_,{children:(0,r.jsxs)(s.VY,{ref:n,className:(0,c.cn)("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2","popper"===l&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",t),position:l,...o,children:[(0,r.jsx)(f,{}),(0,r.jsx)(s.l_,{className:(0,c.cn)("p-1","popper"===l&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:a}),(0,r.jsx)(h,{})]})})});p.displayName=s.VY.displayName,a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.__,{ref:n,className:(0,c.cn)("py-1.5 pl-8 pr-2 text-sm font-semibold",t),...a})}).displayName=s.__.displayName;let x=a.forwardRef((e,n)=>{let{className:t,children:a,...l}=e;return(0,r.jsxs)(s.ck,{ref:n,className:(0,c.cn)("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",t),...l,children:[(0,r.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,r.jsx)(s.wU,{children:(0,r.jsx)(i.Z,{className:"h-4 w-4"})})}),(0,r.jsx)(s.eT,{children:a})]})});x.displayName=s.ck.displayName,a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.Z0,{ref:n,className:(0,c.cn)("-mx-1 my-1 h-px bg-muted",t),...a})}).displayName=s.Z0.displayName},36989:function(e,n,t){t.d(n,{$B:function(){return g},Kl:function(){return v},LU:function(){return p},Md:function(){return h},WH:function(){return f},Zg:function(){return b},Zn:function(){return x},os:function(){return _},sY:function(){return j},x9:function(){return N},xn:function(){return y},yc:function(){return u}});var r=t(85893),a=t(67294),s=t(53302),l=t(11886),o=t(88950),i=t(51214),c=t(41664),d=t.n(c);let u=i.nb.REFRESH_INTERVAL,m={placement:"bottom",color:"default"},f=e=>{let{children:n,...t}=e,a=t.content;return t.content=void 0,(0,r.jsx)(s.e,{...m,...t,content:(0,r.jsx)("span",{className:"left-full w-max px-2 py-1 text-sm text-gray-100 bg-gray-500 text-sm capitalize rounded",children:a}),children:n})},h=e=>{let{children:n,...t}=e,a=t.content;return t.content=void 0,(0,r.jsx)(s.e,{...m,...t,content:(0,r.jsx)("span",{className:"left-full w-max px-2 py-1 text-sm text-gray-100 bg-gray-500 text-sm rounded",children:a}),children:n})};function p(e){if(!e&&0!==e)return"-";let n=e=Math.floor(e),t="",r=0;for(let e of[{value:31536e3,label:"y"},{value:2592e3,label:"mo"},{value:86400,label:"d"},{value:3600,label:"h"},{value:60,label:"m"},{value:1,label:"s"}])if(n>=e.value&&r<2){let a=Math.floor(n/e.value);t+="".concat(a).concat(e.label," "),n%=e.value,r++}return t.trim()||"0s"}function x(e){return e.replace(/\x1b\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGKH]/g,"")}function g(e){let{logs:n,controller:t=!1}=e,[s,l]=(0,a.useState)("all"),[i,c]=(0,a.useState)(n),[d,u]=(0,a.useState)([]);return(0,a.useEffect)(()=>{u(function(e){let n;let t=/\((head|worker\d+),/g,r=new Set;for(;null!==(n=t.exec(e));)r.add(n[1]);return Array.from(r).sort((e,n)=>"head"===e?-1:"head"===n?1:e.localeCompare(n,void 0,{numeric:!0,sensitivity:"base"}))}(n))},[n]),(0,a.useEffect)(()=>{"all"===s?c(n):c(n.split("\n").filter(e=>e.includes("(".concat(s,","))).join("\n"))},[s,n]),(0,r.jsxs)("div",{children:[(0,r.jsx)("style",{children:'\n .logs-container {\n background-color: #f7f7f7;\n padding: 16px;\n max-height: calc(100vh - 300px);\n overflow-y: auto;\n overflow-x: hidden;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n line-height: 1.5;\n border-radius: 6px;\n min-height: fit-content;\n }\n\n .log-line {\n display: block;\n white-space: pre-wrap;\n margin: 2px 0;\n }\n\n .log-line .level {\n display: inline;\n width: 1ch;\n margin-right: 1ch;\n font-weight: bold;\n }\n\n .log-line.INFO .level {\n color: #2563eb;\n }\n\n .log-line.WARNING .level {\n color: #d97706;\n }\n\n .log-line.ERROR .level {\n color: #dc2626;\n }\n\n .log-line.DEBUG .level {\n color: #6b7280;\n }\n\n .log-line .timestamp {\n color: #059669;\n margin-right: 1ch;\n white-space: nowrap;\n }\n\n .log-line .location {\n color: #6366f1;\n margin-right: 1ch;\n white-space: nowrap;\n }\n\n .log-line .message {\n color: #111827;\n word-break: break-word;\n white-space: pre-wrap;\n }\n\n .log-line .log-prefix {\n color: #6366f1;\n font-weight: 500;\n }\n\n .log-line .log-rest {\n color: #111827;\n word-break: break-word;\n white-space: pre-wrap;\n }\n'}),!t&&(0,r.jsx)("div",{style:{marginBottom:"1rem"},children:(0,r.jsxs)(o.Ph,{onValueChange:e=>l(e),value:s,children:[(0,r.jsx)(o.i4,{"aria-label":"Node",className:"focus:ring-0 focus:ring-offset-0",children:(0,r.jsx)(o.ki,{placeholder:"Select Node"})}),(0,r.jsxs)(o.Bw,{children:[(0,r.jsx)(o.Ql,{value:"all",children:"All Nodes"}),d.map(e=>(0,r.jsx)(o.Ql,{value:e,children:e},e))]})]})}),(0,r.jsx)("div",{className:"logs-container",dangerouslySetInnerHTML:{__html:i?x(i).split("\n").filter(e=>""!==e.trim()&&!e.match(/<rich_.*?\[bold cyan\]/)&&!e.match(/<rich_.*>.*<\/rich_.*>/)&&!e.match(/├──/)&&!e.match(/└──/)).map(e=>'<span class="log-line"><span class="message">'.concat(e,"</span></span>")).join("\n"):""}})]})}function b(e){let n,{date:t}=e;if(!t)return"N/A";let a=new Date,s=t.getFullYear()+"-"+String(t.getMonth()+1).padStart(2,"0")+"-"+String(t.getDate()).padStart(2,"0"),o=t.toLocaleString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0,timeZoneName:"short"});return n=function(e){if(!e||"string"!=typeof e)return e;if("just now"===e)return"now";if("less than a minute ago"===e.toLowerCase())return"Less than 1m ago";let n=e.match(/^about\s+(\d+)\s+(\w+)\s+ago$/i);if(n){let e=n[1],t=n[2],r={second:"s",seconds:"s",minute:"m",minutes:"m",hour:"h",hours:"h",day:"d",days:"d",month:"mo",months:"mo",year:"yr",years:"yr"};if(r[t])return"".concat(e).concat(r[t]," ago")}let t=e.match(/^a[n]?\s+(\w+)\s+ago$/i);if(t){let e=t[1],n={second:"s",minute:"m",hour:"h",day:"d",month:"mo",year:"yr"};if(n[e])return"1".concat(n[e]," ago")}let r=e.match(/^(\d+)\s+(\w+)\s+ago$/i);if(r){let e=r[1],n=r[2],t={second:"s",seconds:"s",minute:"m",minutes:"m",hour:"h",hours:"h",day:"d",days:"d",month:"mo",months:"mo",year:"yr",years:"yr"};if(t[n])return"".concat(e).concat(t[n]," ago")}return e}((0,l.B)(t,a,{addSuffix:!0})),(0,r.jsx)(f,{content:s+" "+o,className:"text-sm text-muted-foreground",children:(0,r.jsx)("span",{className:"border-b border-dotted border-gray-400 cursor-help",children:n})})}function y(e){return e?e.getFullYear()+"-"+String(e.getMonth()+1).padStart(2,"0")+"-"+String(e.getDate()).padStart(2,"0")+" "+e.toLocaleString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0,timeZoneName:"short"}):"N/A"}let j=e=>e&&e.jobCounts?e.jobCounts:{},w=e=>{if(!e||0===e.length)return{};let n=e.filter(e=>"READY"===e.status),t={};n.forEach(e=>{try{let n=e.cloud,r=e.region;t[n]||(t[n]={count:0,regions:new Set}),t[n].count+=1,r&&t[n].regions.add(r)}catch(e){t.Unknown||(t.Unknown={count:0,regions:new Set}),t.Unknown.count+=1}});let r={};return Object.entries(t).forEach(e=>{let[n,t]=e,a=t.regions.size,s=n.toLowerCase().includes("kubernetes")||n.toLowerCase().includes("k8s")?"context":"region",l=1===a?"1 ".concat(s):"".concat(a," ").concat(s,"s");r[a>0?"".concat(n," (").concat(l,")"):n]=t.count}),r},N=e=>{let{jobCounts:n,getStatusStyle:t}=e;return n&&0!==Object.keys(n).length?(0,r.jsx)("div",{className:"flex flex-wrap gap-1",children:Object.entries(n).map(e=>{let[n,a]=e,s=t(n);return(0,r.jsxs)("span",{className:"px-2 py-1 rounded-full flex items-center space-x-2 text-xs font-medium ".concat(s),children:[(0,r.jsx)("span",{children:n}),(0,r.jsx)("span",{className:"text-xs bg-white/50 px-1.5 py-0.5 rounded",children:a})]},n)})}):(0,r.jsx)("span",{className:"text-gray-1000",children:"No active jobs"})},v=e=>{let{replicaInfo:n}=e,t=w(n);if(0===Object.keys(t).length)return(0,r.jsx)("span",{className:"text-gray-500 text-sm",children:"-"});let a=i.MO.NAME_TRUNCATE_LENGTH,s=e=>{let n=e.indexOf("(");if(-1===n)return e;let t=e.substring(0,n).trim(),r=e.substring(n+1,e.length-1);if(r.length<=a)return e;let s="".concat(r.substring(0,Math.floor((a-3)/2)),"...").concat(r.substring(r.length-Math.ceil((a-3)/2)));return"".concat(t," (").concat(s,")")};return(0,r.jsx)("div",{className:"flex flex-wrap gap-1",children:Object.entries(t).map(e=>{let[n,t]=e,a=s(n),l=a!==n;return(0,r.jsxs)("span",{className:"px-2 py-1 rounded-full flex items-center space-x-2 text-xs font-medium bg-blue-50 text-blue-700",children:[l?(0,r.jsx)(h,{content:n,className:"text-sm text-muted-foreground",children:(0,r.jsx)("span",{children:a})}):(0,r.jsx)("span",{children:n}),(0,r.jsx)("span",{className:"text-xs bg-white/50 px-1.5 py-0.5 rounded",children:t})]},n)})})},_=(e,n,t)=>{if(!e)return"-";if(t.find(t=>t.name===e&&t.hash===n)&&n)return(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(h,{content:"This pool is running",placement:"top",children:(0,r.jsx)("div",{className:"w-2 h-2 bg-green-700 rounded-full"})}),(0,r.jsx)(d(),{href:"/jobs/pools/".concat(e),className:"text-gray-700 hover:text-blue-600 hover:underline",children:e})]});let a=n?n.substring(0,4):"";return(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(h,{content:"This pool is terminated",placement:"top",children:(0,r.jsx)("div",{className:"w-2 h-2 bg-gray-800"})}),(0,r.jsxs)("span",{children:[e," (",a,")"]})]})}},51214:function(e,n,t){t.d(n,{MO:function(){return s},ej:function(){return r},nb:function(){return a}});let r={DEFAULT_TTL:12e4},a={REFRESH_INTERVAL:3e4,GPU_REFRESH_INTERVAL:3e4},s={NAME_TRUNCATE_LENGTH:20}}}]);
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6989],{88950:function(e,n,t){t.d(n,{Bw:function(){return p},Ph:function(){return d},Ql:function(){return x},i4:function(){return f},ki:function(){return u}});var r=t(85893),a=t(67294),s=t(2067),l=t(45895),o=t(7242),i=t(70282),c=t(32350);let d=s.fC;s.ZA;let u=s.B4,f=a.forwardRef((e,n)=>{let{className:t,children:a,...o}=e;return(0,r.jsxs)(s.xz,{ref:n,className:(0,c.cn)("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",t),...o,children:[a,(0,r.jsx)(s.JO,{asChild:!0,children:(0,r.jsx)(l.Z,{className:"h-4 w-4 opacity-50"})})]})});f.displayName=s.xz.displayName;let m=a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.u_,{ref:n,className:(0,c.cn)("flex cursor-default items-center justify-center py-1",t),...a,children:(0,r.jsx)(o.Z,{className:"h-4 w-4"})})});m.displayName=s.u_.displayName;let h=a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.$G,{ref:n,className:(0,c.cn)("flex cursor-default items-center justify-center py-1",t),...a,children:(0,r.jsx)(l.Z,{className:"h-4 w-4"})})});h.displayName=s.$G.displayName;let p=a.forwardRef((e,n)=>{let{className:t,children:a,position:l="popper",...o}=e;return(0,r.jsx)(s.h_,{children:(0,r.jsxs)(s.VY,{ref:n,className:(0,c.cn)("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2","popper"===l&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",t),position:l,...o,children:[(0,r.jsx)(m,{}),(0,r.jsx)(s.l_,{className:(0,c.cn)("p-1","popper"===l&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:a}),(0,r.jsx)(h,{})]})})});p.displayName=s.VY.displayName,a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.__,{ref:n,className:(0,c.cn)("py-1.5 pl-8 pr-2 text-sm font-semibold",t),...a})}).displayName=s.__.displayName;let x=a.forwardRef((e,n)=>{let{className:t,children:a,...l}=e;return(0,r.jsxs)(s.ck,{ref:n,className:(0,c.cn)("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",t),...l,children:[(0,r.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,r.jsx)(s.wU,{children:(0,r.jsx)(i.Z,{className:"h-4 w-4"})})}),(0,r.jsx)(s.eT,{children:a})]})});x.displayName=s.ck.displayName,a.forwardRef((e,n)=>{let{className:t,...a}=e;return(0,r.jsx)(s.Z0,{ref:n,className:(0,c.cn)("-mx-1 my-1 h-px bg-muted",t),...a})}).displayName=s.Z0.displayName},36989:function(e,n,t){t.d(n,{$B:function(){return g},Kl:function(){return v},LU:function(){return p},Md:function(){return h},WH:function(){return m},Zg:function(){return b},Zn:function(){return x},os:function(){return _},sY:function(){return j},x9:function(){return N},xn:function(){return y},yc:function(){return u}});var r=t(85893),a=t(67294),s=t(53302),l=t(11886),o=t(88950),i=t(51214),c=t(41664),d=t.n(c);let u=i.nb.REFRESH_INTERVAL,f={placement:"bottom",color:"default"},m=e=>{let{children:n,...t}=e,a=t.content;return t.content=void 0,(0,r.jsx)(s.e,{...f,...t,content:(0,r.jsx)("span",{className:"left-full w-max px-2 py-1 text-sm text-gray-100 bg-gray-500 text-sm capitalize rounded",children:a}),children:n})},h=e=>{let{children:n,...t}=e,a=t.content;return t.content=void 0,(0,r.jsx)(s.e,{...f,...t,content:(0,r.jsx)("span",{className:"left-full w-max px-2 py-1 text-sm text-gray-100 bg-gray-500 text-sm rounded",children:a}),children:n})};function p(e){if(!e&&0!==e)return"-";let n=e=Math.floor(e),t="",r=0;for(let e of[{value:31536e3,label:"y"},{value:2592e3,label:"mo"},{value:86400,label:"d"},{value:3600,label:"h"},{value:60,label:"m"},{value:1,label:"s"}])if(n>=e.value&&r<2){let a=Math.floor(n/e.value);t+="".concat(a).concat(e.label," "),n%=e.value,r++}return t.trim()||"0s"}function x(e){return e.replace(/\x1b\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGKH]/g,"")}function g(e){let{logs:n,controller:t=!1}=e,[s,l]=(0,a.useState)("all"),[i,c]=(0,a.useState)(n),[d,u]=(0,a.useState)([]);return(0,a.useEffect)(()=>{u(function(e){let n;let t=/\((head|worker\d+),/g,r=new Set;for(;null!==(n=t.exec(e));)r.add(n[1]);return Array.from(r).sort((e,n)=>"head"===e?-1:"head"===n?1:e.localeCompare(n,void 0,{numeric:!0,sensitivity:"base"}))}(n))},[n]),(0,a.useEffect)(()=>{"all"===s?c(n):c(n.split("\n").filter(e=>e.includes("(".concat(s,","))).join("\n"))},[s,n]),(0,r.jsxs)("div",{children:[(0,r.jsx)("style",{children:'\n .logs-container {\n background-color: #f7f7f7;\n padding: 16px;\n max-height: calc(100vh - 300px);\n overflow-y: auto;\n overflow-x: hidden;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n line-height: 1.5;\n border-radius: 6px;\n min-height: fit-content;\n }\n\n .log-line {\n display: block;\n white-space: pre-wrap;\n margin: 2px 0;\n }\n\n .log-line .level {\n display: inline;\n width: 1ch;\n margin-right: 1ch;\n font-weight: bold;\n }\n\n .log-line.INFO .level {\n color: #2563eb;\n }\n\n .log-line.WARNING .level {\n color: #d97706;\n }\n\n .log-line.ERROR .level {\n color: #dc2626;\n }\n\n .log-line.DEBUG .level {\n color: #6b7280;\n }\n\n .log-line .timestamp {\n color: #059669;\n margin-right: 1ch;\n white-space: nowrap;\n }\n\n .log-line .location {\n color: #6366f1;\n margin-right: 1ch;\n white-space: nowrap;\n }\n\n .log-line .message {\n color: #111827;\n word-break: break-word;\n white-space: pre-wrap;\n }\n\n .log-line .log-prefix {\n color: #6366f1;\n font-weight: 500;\n }\n\n .log-line .log-rest {\n color: #111827;\n word-break: break-word;\n white-space: pre-wrap;\n }\n'}),!t&&(0,r.jsx)("div",{style:{marginBottom:"1rem"},children:(0,r.jsxs)(o.Ph,{onValueChange:e=>l(e),value:s,children:[(0,r.jsx)(o.i4,{"aria-label":"Node",className:"focus:ring-0 focus:ring-offset-0",children:(0,r.jsx)(o.ki,{placeholder:"Select Node"})}),(0,r.jsxs)(o.Bw,{children:[(0,r.jsx)(o.Ql,{value:"all",children:"All Nodes"}),d.map(e=>(0,r.jsx)(o.Ql,{value:e,children:e},e))]})]})}),(0,r.jsx)("div",{className:"logs-container",dangerouslySetInnerHTML:{__html:i?x(i).split("\n").filter(e=>""!==e.trim()&&!e.match(/<rich_.*?\[bold cyan\]/)&&!e.match(/<rich_.*>.*<\/rich_.*>/)&&!e.match(/├──/)&&!e.match(/└──/)).map(e=>'<span class="log-line"><span class="message">'.concat(e,"</span></span>")).join("\n"):""}})]})}function b(e){let n,{date:t}=e;if(!t)return"N/A";let a=new Date,s=t.getFullYear()+"-"+String(t.getMonth()+1).padStart(2,"0")+"-"+String(t.getDate()).padStart(2,"0"),o=t.toLocaleString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0,timeZoneName:"short"});return n=function(e){if(!e||"string"!=typeof e)return e;if("just now"===e)return"now";if("less than a minute ago"===e.toLowerCase())return"Less than 1m ago";let n=e.match(/^about\s+(\d+)\s+(\w+)\s+ago$/i);if(n){let e=n[1],t=n[2],r={second:"s",seconds:"s",minute:"m",minutes:"m",hour:"h",hours:"h",day:"d",days:"d",month:"mo",months:"mo",year:"yr",years:"yr"};if(r[t])return"".concat(e).concat(r[t]," ago")}let t=e.match(/^a[n]?\s+(\w+)\s+ago$/i);if(t){let e=t[1],n={second:"s",minute:"m",hour:"h",day:"d",month:"mo",year:"yr"};if(n[e])return"1".concat(n[e]," ago")}let r=e.match(/^(\d+)\s+(\w+)\s+ago$/i);if(r){let e=r[1],n=r[2],t={second:"s",seconds:"s",minute:"m",minutes:"m",hour:"h",hours:"h",day:"d",days:"d",month:"mo",months:"mo",year:"yr",years:"yr"};if(t[n])return"".concat(e).concat(t[n]," ago")}return e}((0,l.B)(t,a,{addSuffix:!0})),(0,r.jsx)(m,{content:s+" "+o,className:"text-sm text-muted-foreground",children:(0,r.jsx)("span",{className:"border-b border-dotted border-gray-400 cursor-help",children:n})})}function y(e){return e?e.getFullYear()+"-"+String(e.getMonth()+1).padStart(2,"0")+"-"+String(e.getDate()).padStart(2,"0")+" "+e.toLocaleString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0,timeZoneName:"short"}):"N/A"}let j=e=>e&&e.jobCounts?e.jobCounts:{},w=e=>{if(!e||0===e.length)return{};let n=e.filter(e=>"READY"===e.status),t={};n.forEach(e=>{try{let n=e.cloud&&""!==e.cloud.trim()&&"undefined"!==e.cloud,r=e.region&&"undefined"!==e.region&&null!==e.region&&""!==e.region.trim();if(!n&&!r)return;let a=n?e.cloud:"Unknown",s=r?e.region:null;t[a]||(t[a]={count:0,regions:new Set}),t[a].count+=1,s&&t[a].regions.add(s)}catch(e){t.Unknown||(t.Unknown={count:0,regions:new Set}),t.Unknown.count+=1}});let r={};return Object.entries(t).forEach(e=>{let[n,t]=e,a=t.regions.size,s=n.toLowerCase().includes("kubernetes")||n.toLowerCase().includes("k8s")?"context":"region",l=1===a?"1 ".concat(s):"".concat(a," ").concat(s,"s");r[a>0?"".concat(n," (").concat(l,")"):n]=t.count}),r},N=e=>{let{jobCounts:n,getStatusStyle:t}=e;return n&&0!==Object.keys(n).length?(0,r.jsx)("div",{className:"flex flex-wrap gap-1",children:Object.entries(n).map(e=>{let[n,a]=e,s=t(n);return(0,r.jsxs)("span",{className:"px-2 py-1 rounded-full flex items-center space-x-2 text-xs font-medium ".concat(s),children:[(0,r.jsx)("span",{children:n}),(0,r.jsx)("span",{className:"text-xs bg-white/50 px-1.5 py-0.5 rounded",children:a})]},n)})}):(0,r.jsx)("span",{className:"text-gray-1000",children:"No active jobs"})},v=e=>{let{replicaInfo:n}=e,t=w(n);if(0===Object.keys(t).length)return(0,r.jsx)("span",{className:"text-gray-500 text-sm",children:"-"});let a=i.MO.NAME_TRUNCATE_LENGTH,s=e=>{let n=e.indexOf("(");if(-1===n)return e;let t=e.substring(0,n).trim(),r=e.substring(n+1,e.length-1);if(r.length<=a)return e;let s="".concat(r.substring(0,Math.floor((a-3)/2)),"...").concat(r.substring(r.length-Math.ceil((a-3)/2)));return"".concat(t," (").concat(s,")")};return(0,r.jsx)("div",{className:"flex flex-wrap gap-1",children:Object.entries(t).map(e=>{let[n,t]=e,a=s(n),l=a!==n;return(0,r.jsxs)("span",{className:"px-2 py-1 rounded-full flex items-center space-x-2 text-xs font-medium bg-blue-50 text-blue-700",children:[l?(0,r.jsx)(h,{content:n,className:"text-sm text-muted-foreground",children:(0,r.jsx)("span",{children:a})}):(0,r.jsx)("span",{children:n}),(0,r.jsx)("span",{className:"text-xs bg-white/50 px-1.5 py-0.5 rounded",children:t})]},n)})})},_=(e,n,t)=>{if(!e)return"-";if(t.find(t=>t.name===e&&t.hash===n)&&n)return(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(h,{content:"This pool is running",placement:"top",children:(0,r.jsx)("div",{className:"w-2 h-2 bg-green-700 rounded-full"})}),(0,r.jsx)(d(),{href:"/jobs/pools/".concat(e),className:"text-gray-700 hover:text-blue-600 hover:underline",children:e})]});let a=n?n.substring(0,4):"";return(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)(h,{content:"This pool is terminated",placement:"top",children:(0,r.jsx)("div",{className:"w-2 h-2 bg-gray-800"})}),(0,r.jsxs)("span",{children:[e," (",a,")"]})]})}},51214:function(e,n,t){t.d(n,{MO:function(){return s},ej:function(){return r},nb:function(){return a}});let r={DEFAULT_TTL:12e4},a={REFRESH_INTERVAL:3e4,GPU_REFRESH_INTERVAL:3e4},s={NAME_TRUNCATE_LENGTH:20}}}]);