skypilot-nightly 1.0.0.dev20251001__py3-none-any.whl → 1.0.0.dev20251003__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 (58) hide show
  1. sky/__init__.py +2 -2
  2. sky/authentication.py +19 -109
  3. sky/client/cli/command.py +2 -3
  4. sky/client/cli/table_utils.py +222 -1
  5. sky/clouds/cudo.py +1 -1
  6. sky/clouds/kubernetes.py +7 -19
  7. sky/dashboard/out/404.html +1 -1
  8. sky/dashboard/out/_next/static/{m3YT2i5s6v4SsIdYc8WZa → Haazh5IQz6F8Wyiqxcaj8}/_buildManifest.js +1 -1
  9. sky/dashboard/out/_next/static/chunks/3015-8d748834fcc60b46.js +1 -0
  10. sky/dashboard/out/_next/static/chunks/8969-66237729cdf9749e.js +1 -0
  11. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/{[job]-ad77b12fc736dca3.js → [job]-72794fc3fcdd517a.js} +1 -1
  12. sky/dashboard/out/_next/static/chunks/{webpack-4f0c389a4ce5fd9c.js → webpack-3286453d56f3c0a0.js} +1 -1
  13. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  14. sky/dashboard/out/clusters/[cluster].html +1 -1
  15. sky/dashboard/out/clusters.html +1 -1
  16. sky/dashboard/out/config.html +1 -1
  17. sky/dashboard/out/index.html +1 -1
  18. sky/dashboard/out/infra/[context].html +1 -1
  19. sky/dashboard/out/infra.html +1 -1
  20. sky/dashboard/out/jobs/[job].html +1 -1
  21. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  22. sky/dashboard/out/jobs.html +1 -1
  23. sky/dashboard/out/users.html +1 -1
  24. sky/dashboard/out/volumes.html +1 -1
  25. sky/dashboard/out/workspace/new.html +1 -1
  26. sky/dashboard/out/workspaces/[name].html +1 -1
  27. sky/dashboard/out/workspaces.html +1 -1
  28. sky/data/storage_utils.py +9 -0
  29. sky/global_user_state.py +16 -0
  30. sky/jobs/server/core.py +60 -53
  31. sky/jobs/state.py +21 -1
  32. sky/jobs/utils.py +29 -11
  33. sky/provision/kubernetes/config.py +0 -42
  34. sky/provision/kubernetes/instance.py +1 -33
  35. sky/provision/kubernetes/manifests/fusermount-server-daemonset.yaml +1 -2
  36. sky/provision/kubernetes/network_utils.py +0 -21
  37. sky/provision/kubernetes/utils.py +68 -322
  38. sky/schemas/api/responses.py +21 -0
  39. sky/server/requests/serializers/decoders.py +8 -0
  40. sky/server/requests/serializers/encoders.py +6 -0
  41. sky/templates/kubernetes-ray.yml.j2 +4 -13
  42. sky/utils/env_options.py +4 -0
  43. sky/utils/kubernetes_enums.py +2 -15
  44. sky/utils/schemas.py +17 -6
  45. sky/volumes/client/sdk.py +3 -2
  46. sky/volumes/server/core.py +3 -2
  47. {skypilot_nightly-1.0.0.dev20251001.dist-info → skypilot_nightly-1.0.0.dev20251003.dist-info}/METADATA +37 -37
  48. {skypilot_nightly-1.0.0.dev20251001.dist-info → skypilot_nightly-1.0.0.dev20251003.dist-info}/RECORD +53 -56
  49. sky/dashboard/out/_next/static/chunks/3015-88c7c8d69b0b6dba.js +0 -1
  50. sky/dashboard/out/_next/static/chunks/8969-d8bc3a2b9cf839a9.js +0 -1
  51. sky/templates/kubernetes-ssh-jump.yml.j2 +0 -94
  52. sky/utils/kubernetes/ssh_jump_lifecycle_manager.py +0 -191
  53. sky/volumes/utils.py +0 -224
  54. /sky/dashboard/out/_next/static/{m3YT2i5s6v4SsIdYc8WZa → Haazh5IQz6F8Wyiqxcaj8}/_ssgManifest.js +0 -0
  55. {skypilot_nightly-1.0.0.dev20251001.dist-info → skypilot_nightly-1.0.0.dev20251003.dist-info}/WHEEL +0 -0
  56. {skypilot_nightly-1.0.0.dev20251001.dist-info → skypilot_nightly-1.0.0.dev20251003.dist-info}/entry_points.txt +0 -0
  57. {skypilot_nightly-1.0.0.dev20251001.dist-info → skypilot_nightly-1.0.0.dev20251003.dist-info}/licenses/LICENSE +0 -0
  58. {skypilot_nightly-1.0.0.dev20251001.dist-info → skypilot_nightly-1.0.0.dev20251003.dist-info}/top_level.txt +0 -0
sky/__init__.py CHANGED
@@ -7,7 +7,7 @@ import urllib.request
7
7
  from sky.utils import directory_utils
8
8
 
9
9
  # Replaced with the current commit when building the wheels.
10
- _SKYPILOT_COMMIT_SHA = '047e366ad4c073a5753b62cc5d4c3c4660b1476a'
10
+ _SKYPILOT_COMMIT_SHA = 'd9e8cda1c05e4d5e7135d47a4720d236c932e8d7'
11
11
 
12
12
 
13
13
  def _get_git_commit():
@@ -37,7 +37,7 @@ def _get_git_commit():
37
37
 
38
38
 
39
39
  __commit__ = _get_git_commit()
40
- __version__ = '1.0.0.dev20251001'
40
+ __version__ = '1.0.0.dev20251003'
41
41
  __root_dir__ = directory_utils.get_sky_dir()
42
42
 
43
43
 
sky/authentication.py CHANGED
@@ -35,10 +35,8 @@ from sky import clouds
35
35
  from sky import exceptions
36
36
  from sky import global_user_state
37
37
  from sky import sky_logging
38
- from sky import skypilot_config
39
38
  from sky.adaptors import gcp
40
39
  from sky.adaptors import ibm
41
- from sky.adaptors import kubernetes
42
40
  from sky.adaptors import runpod
43
41
  from sky.adaptors import seeweb as seeweb_adaptor
44
42
  from sky.adaptors import vast
@@ -47,8 +45,6 @@ from sky.provision.kubernetes import utils as kubernetes_utils
47
45
  from sky.provision.lambda_cloud import lambda_utils
48
46
  from sky.provision.primeintellect import utils as primeintellect_utils
49
47
  from sky.utils import common_utils
50
- from sky.utils import config_utils
51
- from sky.utils import kubernetes_enums
52
48
  from sky.utils import subprocess_utils
53
49
  from sky.utils import ux_utils
54
50
  from sky.utils import yaml_utils
@@ -431,116 +427,30 @@ def setup_ibm_authentication(config: Dict[str, Any]) -> Dict[str, Any]:
431
427
 
432
428
  def setup_kubernetes_authentication(config: Dict[str, Any]) -> Dict[str, Any]:
433
429
  context = kubernetes_utils.get_context_from_config(config['provider'])
434
-
435
- # Default ssh session is established with kubectl port-forwarding with
436
- # ClusterIP service.
437
- nodeport_mode = kubernetes_enums.KubernetesNetworkingMode.NODEPORT
438
- port_forward_mode = kubernetes_enums.KubernetesNetworkingMode.PORTFORWARD
439
- network_mode_str = skypilot_config.get_effective_region_config(
440
- cloud='kubernetes',
441
- region=context,
442
- keys=('networking',),
443
- default_value=port_forward_mode.value)
444
- try:
445
- network_mode = kubernetes_enums.KubernetesNetworkingMode.from_str(
446
- network_mode_str)
447
- except ValueError as e:
448
- # Add message saying "Please check: ~/.sky/config.yaml" to the error
449
- # message.
450
- with ux_utils.print_exception_no_traceback():
451
- raise ValueError(str(e) +
452
- ' Please check: ~/.sky/config.yaml.') from None
453
- _, public_key_path = get_or_generate_keys()
454
-
455
- # Add the user's public key to the SkyPilot cluster.
456
- secret_name = clouds.Kubernetes.SKY_SSH_KEY_SECRET_NAME
457
- secret_field_name = clouds.Kubernetes().ssh_key_secret_field_name
458
430
  namespace = kubernetes_utils.get_namespace_from_config(config['provider'])
459
- k8s = kubernetes.kubernetes
460
- with open(public_key_path, 'r', encoding='utf-8') as f:
461
- public_key = f.read()
462
- if not public_key.endswith('\n'):
463
- public_key += '\n'
464
-
465
- # Generate metadata
466
- secret_metadata = {
467
- 'name': secret_name,
468
- 'labels': {
469
- 'parent': 'skypilot'
470
- }
471
- }
472
- custom_metadata = skypilot_config.get_effective_region_config(
473
- cloud='kubernetes',
474
- region=context,
475
- keys=('custom_metadata',),
476
- default_value={})
477
- config_utils.merge_k8s_configs(secret_metadata, custom_metadata)
478
-
479
- secret = k8s.client.V1Secret(
480
- metadata=k8s.client.V1ObjectMeta(**secret_metadata),
481
- string_data={secret_field_name: public_key})
482
- try:
483
- if kubernetes_utils.check_secret_exists(secret_name, namespace,
484
- context):
485
- logger.debug(f'Key {secret_name} exists in the cluster, '
486
- 'patching it...')
487
- kubernetes.core_api(context).patch_namespaced_secret(
488
- secret_name, namespace, secret)
489
- else:
490
- logger.debug(f'Key {secret_name} does not exist in the cluster, '
491
- 'creating it...')
492
- kubernetes.core_api(context).create_namespaced_secret(
493
- namespace, secret)
494
- except kubernetes.api_exception() as e:
495
- if e.status == 409 and e.reason == 'AlreadyExists':
496
- logger.debug(f'Key {secret_name} was created concurrently, '
497
- 'patching it...')
498
- kubernetes.core_api(context).patch_namespaced_secret(
499
- secret_name, namespace, secret)
500
- else:
501
- raise e
502
-
503
431
  private_key_path, _ = get_or_generate_keys()
504
- if network_mode == nodeport_mode:
505
- ssh_jump_name = clouds.Kubernetes.SKY_SSH_JUMP_NAME
506
- service_type = kubernetes_enums.KubernetesServiceType.NODEPORT
507
- # Setup service for SSH jump pod. We create the SSH jump service here
508
- # because we need to know the service IP address and port to set the
509
- # ssh_proxy_command in the autoscaler config.
510
- kubernetes_utils.setup_ssh_jump_svc(ssh_jump_name, namespace, context,
511
- service_type)
512
- ssh_proxy_cmd = kubernetes_utils.get_ssh_proxy_command(
513
- ssh_jump_name,
514
- nodeport_mode,
515
- private_key_path=private_key_path,
516
- context=context,
517
- namespace=namespace)
518
- elif network_mode == port_forward_mode:
519
- # Using `kubectl port-forward` creates a direct tunnel to the pod and
520
- # does not require a ssh jump pod.
521
- kubernetes_utils.check_port_forward_mode_dependencies()
522
- # TODO(romilb): This can be further optimized. Instead of using the
523
- # head node as a jump pod for worker nodes, we can also directly
524
- # set the ssh_target to the worker node. However, that requires
525
- # changes in the downstream code to return a mapping of node IPs to
526
- # pod names (to be used as ssh_target) and updating the upstream
527
- # SSHConfigHelper to use a different ProxyCommand for each pod.
528
- # This optimization can reduce SSH time from ~0.35s to ~0.25s, tested
529
- # on GKE.
530
- ssh_target = config['cluster_name'] + '-head'
531
- ssh_proxy_cmd = kubernetes_utils.get_ssh_proxy_command(
532
- ssh_target,
533
- port_forward_mode,
534
- private_key_path=private_key_path,
535
- context=context,
536
- namespace=namespace)
537
- else:
538
- # This should never happen because we check for this in from_str above.
539
- raise ValueError(f'Unsupported networking mode: {network_mode_str}')
432
+ # Using `kubectl port-forward` creates a direct tunnel to the pod and
433
+ # does not require a ssh jump pod.
434
+ kubernetes_utils.check_port_forward_mode_dependencies()
435
+ # TODO(romilb): This can be further optimized. Instead of using the
436
+ # head node as a jump pod for worker nodes, we can also directly
437
+ # set the ssh_target to the worker node. However, that requires
438
+ # changes in the downstream code to return a mapping of node IPs to
439
+ # pod names (to be used as ssh_target) and updating the upstream
440
+ # SSHConfigHelper to use a different ProxyCommand for each pod.
441
+ # This optimization can reduce SSH time from ~0.35s to ~0.25s, tested
442
+ # on GKE.
443
+ pod_name = config['cluster_name'] + '-head'
444
+ ssh_proxy_cmd = kubernetes_utils.get_ssh_proxy_command(
445
+ pod_name,
446
+ private_key_path=private_key_path,
447
+ context=context,
448
+ namespace=namespace)
540
449
  config['auth']['ssh_proxy_command'] = ssh_proxy_cmd
541
450
  config['auth']['ssh_private_key'] = private_key_path
542
451
 
543
- return config
452
+ # Add the user's public key to the SkyPilot cluster.
453
+ return configure_ssh_info(config)
544
454
 
545
455
 
546
456
  # ---------------------------------- RunPod ---------------------------------- #
sky/client/cli/command.py CHANGED
@@ -90,7 +90,6 @@ from sky.utils import ux_utils
90
90
  from sky.utils import volume as volume_utils
91
91
  from sky.utils import yaml_utils
92
92
  from sky.utils.cli_utils import status_utils
93
- from sky.volumes import utils as volumes_utils
94
93
  from sky.volumes.client import sdk as volumes_sdk
95
94
 
96
95
  if typing.TYPE_CHECKING:
@@ -4240,8 +4239,8 @@ def volumes_ls(verbose: bool):
4240
4239
  """List volumes managed by SkyPilot."""
4241
4240
  request_id = volumes_sdk.ls()
4242
4241
  all_volumes = sdk.stream_and_get(request_id)
4243
- volume_table = volumes_utils.format_volume_table(all_volumes,
4244
- show_all=verbose)
4242
+ volume_table = table_utils.format_volume_table(all_volumes,
4243
+ show_all=verbose)
4245
4244
  click.echo(volume_table)
4246
4245
 
4247
4246
 
@@ -1,11 +1,19 @@
1
1
  """Utilities for formatting tables for CLI output."""
2
- from typing import List, Optional
2
+ import abc
3
+ from datetime import datetime
4
+ from typing import Dict, List, Optional
3
5
 
6
+ import prettytable
7
+
8
+ from sky import sky_logging
4
9
  from sky.jobs import utils as managed_jobs
5
10
  from sky.schemas.api import responses
6
11
  from sky.skylet import constants
7
12
  from sky.utils import common_utils
8
13
  from sky.utils import log_utils
14
+ from sky.utils import volume
15
+
16
+ logger = sky_logging.init_logger(__name__)
9
17
 
10
18
 
11
19
  def format_job_queue(jobs: List[responses.ClusterJobRecord]):
@@ -89,3 +97,216 @@ def format_job_table(jobs: List[responses.ManagedJobRecord],
89
97
  show_all=show_all,
90
98
  show_user=show_user,
91
99
  max_jobs=max_jobs)
100
+
101
+
102
+ _BASIC_COLUMNS = [
103
+ 'NAME',
104
+ 'TYPE',
105
+ 'INFRA',
106
+ 'SIZE',
107
+ 'USER',
108
+ 'WORKSPACE',
109
+ 'AGE',
110
+ 'STATUS',
111
+ 'LAST_USE',
112
+ 'USED_BY',
113
+ ]
114
+
115
+
116
+ def _get_infra_str(cloud: Optional[str], region: Optional[str],
117
+ zone: Optional[str]) -> str:
118
+ """Get the infrastructure string for the volume."""
119
+ infra = ''
120
+ if cloud:
121
+ infra += cloud
122
+ if region:
123
+ infra += f'/{region}'
124
+ if zone:
125
+ infra += f'/{zone}'
126
+ return infra
127
+
128
+
129
+ class VolumeTable(abc.ABC):
130
+ """The volume table."""
131
+
132
+ def __init__(self,
133
+ volumes: List[responses.VolumeRecord],
134
+ show_all: bool = False):
135
+ super().__init__()
136
+ self.table = self._create_table(show_all)
137
+ self._add_rows(volumes, show_all)
138
+
139
+ def _get_row_base_columns(self,
140
+ row: responses.VolumeRecord,
141
+ show_all: bool = False) -> List[str]:
142
+ """Get the base columns for a row."""
143
+ # Convert last_attached_at timestamp to human readable string
144
+ last_attached_at = row.get('last_attached_at')
145
+ if last_attached_at is not None:
146
+ last_attached_at_str = datetime.fromtimestamp(
147
+ last_attached_at).strftime('%Y-%m-%d %H:%M:%S')
148
+ else:
149
+ last_attached_at_str = '-'
150
+ size = row.get('size', '')
151
+ if size:
152
+ size = f'{size}Gi'
153
+ usedby_str = '-'
154
+ usedby_clusters = row.get('usedby_clusters')
155
+ usedby_pods = row.get('usedby_pods')
156
+ if usedby_clusters:
157
+ usedby_str = f'{", ".join(usedby_clusters)}'
158
+ elif usedby_pods:
159
+ usedby_str = f'{", ".join(usedby_pods)}'
160
+ if show_all:
161
+ usedby = usedby_str
162
+ else:
163
+ usedby = common_utils.truncate_long_string(
164
+ usedby_str, constants.USED_BY_TRUNC_LENGTH)
165
+ infra = _get_infra_str(row.get('cloud'), row.get('region'),
166
+ row.get('zone'))
167
+ return [
168
+ row.get('name', ''),
169
+ row.get('type', ''),
170
+ infra,
171
+ size,
172
+ row.get('user_name', '-'),
173
+ row.get('workspace', '-'),
174
+ log_utils.human_duration(row.get('launched_at', 0)),
175
+ row.get('status', ''),
176
+ last_attached_at_str,
177
+ usedby,
178
+ ]
179
+
180
+ def _create_table(self, show_all: bool = False) -> prettytable.PrettyTable:
181
+ """Create the volume table."""
182
+ raise NotImplementedError
183
+
184
+ def _add_rows(self,
185
+ volumes: List[responses.VolumeRecord],
186
+ show_all: bool = False) -> None:
187
+ """Add rows to the volume table."""
188
+ raise NotImplementedError
189
+
190
+ @abc.abstractmethod
191
+ def format(self) -> str:
192
+ """Format the volume table for display."""
193
+ raise NotImplementedError
194
+
195
+
196
+ class PVCVolumeTable(VolumeTable):
197
+ """The PVC volume table."""
198
+
199
+ def _create_table(self, show_all: bool = False) -> prettytable.PrettyTable:
200
+ """Create the PVC volume table."""
201
+ # If show_all is False, show the table with the columns:
202
+ # NAME, TYPE, INFRA, SIZE, USER, WORKSPACE,
203
+ # AGE, STATUS, LAST_USE, USED_BY
204
+ # If show_all is True, show the table with the columns:
205
+ # NAME, TYPE, INFRA, SIZE, USER, WORKSPACE,
206
+ # AGE, STATUS, LAST_USE, USED_BY, NAME_ON_CLOUD
207
+ # STORAGE_CLASS, ACCESS_MODE
208
+
209
+ if show_all:
210
+ columns = _BASIC_COLUMNS + [
211
+ 'NAME_ON_CLOUD',
212
+ 'STORAGE_CLASS',
213
+ 'ACCESS_MODE',
214
+ ]
215
+ else:
216
+ columns = _BASIC_COLUMNS
217
+
218
+ table = log_utils.create_table(columns)
219
+ return table
220
+
221
+ def _add_rows(self,
222
+ volumes: List[responses.VolumeRecord],
223
+ show_all: bool = False) -> None:
224
+ """Add rows to the PVC volume table."""
225
+ for row in volumes:
226
+ table_row = self._get_row_base_columns(row, show_all)
227
+ if show_all:
228
+ table_row.append(row.get('name_on_cloud', ''))
229
+ table_row.append(
230
+ row.get('config', {}).get('storage_class_name', '-'))
231
+ table_row.append(row.get('config', {}).get('access_mode', ''))
232
+
233
+ self.table.add_row(table_row)
234
+
235
+ def format(self) -> str:
236
+ """Format the PVC volume table for display."""
237
+ return 'Kubernetes PVCs:\n' + str(self.table)
238
+
239
+
240
+ class RunPodVolumeTable(VolumeTable):
241
+ """The RunPod volume table."""
242
+
243
+ def _create_table(self, show_all: bool = False) -> prettytable.PrettyTable:
244
+ """Create the RunPod volume table."""
245
+ # If show_all is False, show the table with the columns:
246
+ # NAME, TYPE, INFRA, SIZE, USER, WORKSPACE,
247
+ # AGE, STATUS, LAST_USE, USED_BY
248
+ # If show_all is True, show the table with the columns:
249
+ # NAME, TYPE, INFRA, SIZE, USER, WORKSPACE,
250
+ # AGE, STATUS, LAST_USE, USED_BY, NAME_ON_CLOUD
251
+
252
+ if show_all:
253
+ columns = _BASIC_COLUMNS + ['NAME_ON_CLOUD']
254
+ else:
255
+ columns = _BASIC_COLUMNS
256
+
257
+ table = log_utils.create_table(columns)
258
+ return table
259
+
260
+ def _add_rows(self,
261
+ volumes: List[responses.VolumeRecord],
262
+ show_all: bool = False) -> None:
263
+ """Add rows to the RunPod volume table."""
264
+ for row in volumes:
265
+ table_row = self._get_row_base_columns(row, show_all)
266
+ if show_all:
267
+ table_row.append(row.get('name_on_cloud', ''))
268
+
269
+ self.table.add_row(table_row)
270
+
271
+ def format(self) -> str:
272
+ """Format the RunPod volume table for display."""
273
+ return 'RunPod Network Volumes:\n' + str(self.table)
274
+
275
+
276
+ def format_volume_table(volumes: List[responses.VolumeRecord],
277
+ show_all: bool = False) -> str:
278
+ """Format the volume table for display.
279
+
280
+ Args:
281
+ volume_table (dict): The volume table.
282
+
283
+ Returns:
284
+ str: The formatted volume table.
285
+ """
286
+ volumes_per_type: Dict[str, List[responses.VolumeRecord]] = {}
287
+ supported_volume_types = [
288
+ volume_type.value for volume_type in volume.VolumeType
289
+ ]
290
+ for row in volumes:
291
+ volume_type = row.get('type', '')
292
+ if volume_type in supported_volume_types:
293
+ if volume_type not in volumes_per_type:
294
+ volumes_per_type[volume_type] = []
295
+ volumes_per_type[volume_type].append(row)
296
+ else:
297
+ logger.warning(f'Unknown volume type: {volume_type}')
298
+ continue
299
+ table_str = ''
300
+ for volume_type, volume_list in volumes_per_type.items():
301
+ if table_str:
302
+ table_str += '\n\n'
303
+ if volume_type == volume.VolumeType.PVC.value:
304
+ pvc_table = PVCVolumeTable(volume_list, show_all)
305
+ table_str += pvc_table.format()
306
+ elif volume_type == volume.VolumeType.RUNPOD_NETWORK_VOLUME.value:
307
+ runpod_table = RunPodVolumeTable(volume_list, show_all)
308
+ table_str += runpod_table.format()
309
+ if table_str:
310
+ return table_str
311
+ else:
312
+ return 'No existing volumes.'
sky/clouds/cudo.py CHANGED
@@ -288,7 +288,7 @@ class Cudo(clouds.Cloud):
288
288
  cls) -> Tuple[bool, Optional[Union[str, Dict[str, str]]]]:
289
289
  """Checks if the user has access credentials to
290
290
  Cudo's compute service."""
291
- if not common.can_import_modules(['cudo_api']):
291
+ if not common.can_import_modules(['cudo_compute']):
292
292
  return False, (f'{cls._DEPENDENCY_HINT}\n'
293
293
  f'{cls._INDENT_PREFIX}')
294
294
 
sky/clouds/kubernetes.py CHANGED
@@ -25,6 +25,7 @@ from sky.provision.kubernetes.utils import normalize_tpu_accelerator_name
25
25
  from sky.skylet import constants
26
26
  from sky.utils import annotations
27
27
  from sky.utils import common_utils
28
+ from sky.utils import env_options
28
29
  from sky.utils import kubernetes_enums
29
30
  from sky.utils import registry
30
31
  from sky.utils import resources_utils
@@ -47,9 +48,6 @@ _FUSERMOUNT_SHARED_DIR = '/var/run/fusermount'
47
48
  class Kubernetes(clouds.Cloud):
48
49
  """Kubernetes."""
49
50
 
50
- SKY_SSH_KEY_SECRET_NAME = 'sky-ssh-keys'
51
- SKY_SSH_JUMP_NAME = 'sky-ssh-jump-pod'
52
-
53
51
  # Limit the length of the cluster name to avoid exceeding the limit of 63
54
52
  # characters for Kubernetes resources. We limit to 42 characters (63-21) to
55
53
  # allow additional characters for creating ingress services to expose ports.
@@ -98,14 +96,6 @@ class Kubernetes(clouds.Cloud):
98
96
  # Set of contexts that has logged as temporarily unreachable
99
97
  logged_unreachable_contexts: Set[str] = set()
100
98
 
101
- @property
102
- def ssh_key_secret_field_name(self):
103
- # Use a fresh user hash to avoid conflicts in the secret object naming.
104
- # This can happen when the controller is reusing the same user hash
105
- # through USER_ID_ENV_VAR but has a different SSH key.
106
- fresh_user_hash = common_utils.generate_user_hash()
107
- return f'ssh-publickey-{fresh_user_hash}'
108
-
109
99
  @classmethod
110
100
  def _unsupported_features_for_resources(
111
101
  cls, resources: 'resources_lib.Resources'
@@ -188,6 +178,12 @@ class Kubernetes(clouds.Cloud):
188
178
  ctx for ctx in all_contexts if not ctx.startswith('ssh-')
189
179
  ]
190
180
 
181
+ allow_all_contexts = allowed_contexts == 'all' or (
182
+ allowed_contexts is None and
183
+ env_options.Options.ALLOW_ALL_KUBERNETES_CONTEXTS.get())
184
+ if allow_all_contexts:
185
+ allowed_contexts = all_contexts
186
+
191
187
  if allowed_contexts is None:
192
188
  # Try kubeconfig if present
193
189
  current_context = (
@@ -517,9 +513,6 @@ class Kubernetes(clouds.Cloud):
517
513
  return image_id
518
514
 
519
515
  image_id = _get_image_id(resources)
520
- # TODO(romilb): Create a lightweight image for SSH jump host
521
- ssh_jump_image = catalog.get_image_id_from_tag(self.IMAGE_CPU,
522
- clouds='kubernetes')
523
516
 
524
517
  # Set environment variables for the pod. Note that SkyPilot env vars
525
518
  # are set separately when the task is run. These env vars are
@@ -693,13 +686,8 @@ class Kubernetes(clouds.Cloud):
693
686
  'accelerator_count': str(acc_count),
694
687
  'timeout': str(timeout),
695
688
  'k8s_port_mode': port_mode.value,
696
- 'k8s_networking_mode': network_utils.get_networking_mode(
697
- None, context=context).value,
698
- 'k8s_ssh_key_secret_name': self.SKY_SSH_KEY_SECRET_NAME,
699
689
  'k8s_acc_label_key': k8s_acc_label_key,
700
690
  'k8s_acc_label_values': k8s_acc_label_values,
701
- 'k8s_ssh_jump_name': self.SKY_SSH_JUMP_NAME,
702
- 'k8s_ssh_jump_image': ssh_jump_image,
703
691
  'k8s_service_account_name': k8s_service_account_name,
704
692
  'k8s_automount_sa_token': 'true',
705
693
  'k8s_fuse_device_required': fuse_device_required,
@@ -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-4f0c389a4ce5fd9c.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-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/m3YT2i5s6v4SsIdYc8WZa/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/m3YT2i5s6v4SsIdYc8WZa/_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":"m3YT2i5s6v4SsIdYc8WZa","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-3286453d56f3c0a0.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-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/Haazh5IQz6F8Wyiqxcaj8/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Haazh5IQz6F8Wyiqxcaj8/_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":"Haazh5IQz6F8Wyiqxcaj8","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- self.__BUILD_MANIFEST=function(s,c,a,t,e,f,b,u,n,o,j,i,r,k){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-469814d711d63b1b.js"],"/clusters/[cluster]":[s,c,a,f,b,"static/chunks/4676-9da7fdbde90b5549.js",o,t,e,u,j,n,i,"static/chunks/6856-5fdc9b851a18acdb.js",r,k,"static/chunks/9037-d0c00018a5ba198c.js","static/chunks/pages/clusters/[cluster]-e052384df65ef200.js"],"/clusters/[cluster]/[job]":[s,c,a,f,t,e,n,"static/chunks/pages/clusters/[cluster]/[job]-ad77b12fc736dca3.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-aabba60d57826e0f.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-6563820e094f68ca.js"],"/jobs":["static/chunks/pages/jobs-1f70d9faa564804f.js"],"/jobs/pools/[pool]":[s,c,a,b,o,t,e,u,"static/chunks/pages/jobs/pools/[pool]-509b2977a6373bf6.js"],"/jobs/[job]":[s,c,a,f,b,o,t,e,u,n,"static/chunks/pages/jobs/[job]-dd64309c3fe67ed2.js"],"/users":["static/chunks/pages/users-018bf31cda52e11b.js"],"/volumes":["static/chunks/pages/volumes-739726d6b823f532.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-7528cc0ef8c522c5.js"],"/workspaces/[name]":[s,c,a,f,b,"static/chunks/1836-37fede578e2da5f8.js",t,e,u,j,n,i,r,k,"static/chunks/1141-159df2d4c441a9d1.js","static/chunks/pages/workspaces/[name]-af76bb06dbb3954f.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-01359c57e018caa4.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-d8bc3a2b9cf839a9.js","static/chunks/6135-4b4d5e824b7f9d3c.js","static/chunks/754-d0da8ab45f9509e9.js","static/chunks/6990-f6818c84ed8f1c86.js","static/chunks/1121-d0782b9251f0fcd3.js","static/chunks/6601-06114c982db410b6.js","static/chunks/3015-88c7c8d69b0b6dba.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
1
+ self.__BUILD_MANIFEST=function(s,c,a,e,t,f,u,n,b,o,j,i,r,k){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-444f1804401f04ea.js"],"/_error":["static/chunks/pages/_error-c66a4e8afc46f17b.js"],"/clusters":["static/chunks/pages/clusters-469814d711d63b1b.js"],"/clusters/[cluster]":[s,c,a,f,u,"static/chunks/4676-9da7fdbde90b5549.js",o,e,t,n,j,b,i,"static/chunks/6856-5fdc9b851a18acdb.js",r,k,"static/chunks/9037-d0c00018a5ba198c.js","static/chunks/pages/clusters/[cluster]-e052384df65ef200.js"],"/clusters/[cluster]/[job]":[s,c,a,f,e,t,b,"static/chunks/pages/clusters/[cluster]/[job]-72794fc3fcdd517a.js"],"/config":["static/chunks/pages/config-dfb9bf07b13045f4.js"],"/infra":["static/chunks/pages/infra-aabba60d57826e0f.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-6563820e094f68ca.js"],"/jobs":["static/chunks/pages/jobs-1f70d9faa564804f.js"],"/jobs/pools/[pool]":[s,c,a,u,o,e,t,n,"static/chunks/pages/jobs/pools/[pool]-509b2977a6373bf6.js"],"/jobs/[job]":[s,c,a,f,u,o,e,t,n,b,"static/chunks/pages/jobs/[job]-dd64309c3fe67ed2.js"],"/users":["static/chunks/pages/users-018bf31cda52e11b.js"],"/volumes":["static/chunks/pages/volumes-739726d6b823f532.js"],"/workspace/new":["static/chunks/pages/workspace/new-3f88a1c7e86a3f86.js"],"/workspaces":["static/chunks/pages/workspaces-7528cc0ef8c522c5.js"],"/workspaces/[name]":[s,c,a,f,u,"static/chunks/1836-37fede578e2da5f8.js",e,t,n,j,b,i,r,k,"static/chunks/1141-159df2d4c441a9d1.js","static/chunks/pages/workspaces/[name]-af76bb06dbb3954f.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-01359c57e018caa4.js","static/chunks/3850-ff4a9a69d978632b.js","static/chunks/7411-b15471acd2cba716.js","static/chunks/1272-1ef0bf0237faccdb.js","static/chunks/8969-66237729cdf9749e.js","static/chunks/6135-4b4d5e824b7f9d3c.js","static/chunks/754-d0da8ab45f9509e9.js","static/chunks/6990-f6818c84ed8f1c86.js","static/chunks/1121-d0782b9251f0fcd3.js","static/chunks/6601-06114c982db410b6.js","static/chunks/3015-8d748834fcc60b46.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();