skypilot-nightly 1.0.0.dev20250107__py3-none-any.whl → 1.0.0.dev20250109__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 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 = '6cf98a3cfbed39984b106f95ec7209058c73570d'
8
+ _SKYPILOT_COMMIT_SHA = '544c34e2e7eb995530c05fe10148aad87a4d0501'
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.dev20250107'
38
+ __version__ = '1.0.0.dev20250109'
39
39
  __root_dir__ = os.path.dirname(os.path.abspath(__file__))
40
40
 
41
41
 
sky/authentication.py CHANGED
@@ -408,14 +408,26 @@ def setup_kubernetes_authentication(config: Dict[str, Any]) -> Dict[str, Any]:
408
408
  secret = k8s.client.V1Secret(
409
409
  metadata=k8s.client.V1ObjectMeta(**secret_metadata),
410
410
  string_data={secret_field_name: public_key})
411
- if kubernetes_utils.check_secret_exists(secret_name, namespace, context):
412
- logger.debug(f'Key {secret_name} exists in the cluster, patching it...')
413
- kubernetes.core_api(context).patch_namespaced_secret(
414
- secret_name, namespace, secret)
415
- else:
416
- logger.debug(
417
- f'Key {secret_name} does not exist in the cluster, creating it...')
418
- kubernetes.core_api(context).create_namespaced_secret(namespace, secret)
411
+ try:
412
+ if kubernetes_utils.check_secret_exists(secret_name, namespace,
413
+ context):
414
+ logger.debug(f'Key {secret_name} exists in the cluster, '
415
+ 'patching it...')
416
+ kubernetes.core_api(context).patch_namespaced_secret(
417
+ secret_name, namespace, secret)
418
+ else:
419
+ logger.debug(f'Key {secret_name} does not exist in the cluster, '
420
+ 'creating it...')
421
+ kubernetes.core_api(context).create_namespaced_secret(
422
+ namespace, secret)
423
+ except kubernetes.api_exception() as e:
424
+ if e.status == 409 and e.reason == 'AlreadyExists':
425
+ logger.debug(f'Key {secret_name} was created concurrently, '
426
+ 'patching it...')
427
+ kubernetes.core_api(context).patch_namespaced_secret(
428
+ secret_name, namespace, secret)
429
+ else:
430
+ raise e
419
431
 
420
432
  private_key_path, _ = get_or_generate_keys()
421
433
  if network_mode == nodeport_mode:
sky/clouds/aws.py CHANGED
@@ -95,6 +95,8 @@ class AWSIdentityType(enum.Enum):
95
95
 
96
96
  CONTAINER_ROLE = 'container-role'
97
97
 
98
+ CUSTOM_PROCESS = 'custom-process'
99
+
98
100
  # Name Value Type Location
99
101
  # ---- ----- ---- --------
100
102
  # profile <not set> None None
@@ -614,10 +616,16 @@ class AWS(clouds.Cloud):
614
616
  hints = f'AWS IAM role is set.{single_cloud_hint}'
615
617
  elif identity_type == AWSIdentityType.CONTAINER_ROLE:
616
618
  # Similar to the IAM ROLE, an ECS container may not store credentials
617
- # in the~/.aws/credentials file. So we don't check for the existence of
619
+ # in the ~/.aws/credentials file. So we don't check for the existence of
618
620
  # the file. i.e. the container will be assigned the IAM role of the
619
621
  # task: skypilot-v1.
620
622
  hints = f'AWS container-role is set.{single_cloud_hint}'
623
+ elif identity_type == AWSIdentityType.CUSTOM_PROCESS:
624
+ # Similar to the IAM ROLE, a custom process may not store credentials
625
+ # in the ~/.aws/credentials file. So we don't check for the existence of
626
+ # the file. i.e. the custom process will be assigned the IAM role of the
627
+ # task: skypilot-v1.
628
+ hints = f'AWS custom-process is set.{single_cloud_hint}'
621
629
  else:
622
630
  # This file is required because it is required by the VMs launched on
623
631
  # other clouds to access private s3 buckets and resources like EC2.
@@ -677,6 +685,8 @@ class AWS(clouds.Cloud):
677
685
  return AWSIdentityType.CONTAINER_ROLE
678
686
  elif _is_access_key_of_type(AWSIdentityType.ENV.value):
679
687
  return AWSIdentityType.ENV
688
+ elif _is_access_key_of_type(AWSIdentityType.CUSTOM_PROCESS.value):
689
+ return AWSIdentityType.CUSTOM_PROCESS
680
690
  else:
681
691
  return AWSIdentityType.SHARED_CREDENTIALS_FILE
682
692
 
@@ -383,10 +383,13 @@ def _usable_subnets(
383
383
  raise exc
384
384
 
385
385
  if not subnets:
386
+ vpc_msg = (f'Does a default VPC exist in region '
387
+ f'{ec2.meta.client.meta.region_name}? ') if (
388
+ vpc_id_of_sg is None) else ''
386
389
  _skypilot_log_error_and_exit_for_failover(
387
- 'No usable subnets found, try '
388
- 'manually creating an instance in your specified region to '
389
- 'populate the list of subnets and trying this again. '
390
+ f'No usable subnets found. {vpc_msg}'
391
+ 'Try manually creating an instance in your specified region to '
392
+ 'populate the list of subnets and try again. '
390
393
  'Note that the subnet must map public IPs '
391
394
  'on instance launch unless you set `use_internal_ips: true` in '
392
395
  'the `provider` config.')
@@ -495,6 +498,11 @@ def _get_subnet_and_vpc_id(ec2, security_group_ids: Optional[List[str]],
495
498
  vpc_id_of_sg = None
496
499
 
497
500
  all_subnets = list(ec2.subnets.all())
501
+ # If no VPC is specified, use the default VPC.
502
+ # We filter only for default VPCs to avoid using subnets that users may
503
+ # not want SkyPilot to use.
504
+ if vpc_id_of_sg is None:
505
+ all_subnets = [s for s in all_subnets if s.vpc.is_default]
498
506
  subnets, vpc_id = _usable_subnets(
499
507
  ec2,
500
508
  user_specified_subnets=None,
@@ -38,6 +38,13 @@ class DockerLoginConfig:
38
38
  password: str
39
39
  server: str
40
40
 
41
+ def format_image(self, image: str) -> str:
42
+ """Format the image name with the server prefix."""
43
+ server_prefix = f'{self.server}/'
44
+ if not image.startswith(server_prefix):
45
+ return f'{server_prefix}{image}'
46
+ return image
47
+
41
48
  @classmethod
42
49
  def from_env_vars(cls, d: Dict[str, str]) -> 'DockerLoginConfig':
43
50
  return cls(
@@ -220,9 +227,7 @@ class DockerInitializer:
220
227
  wait_for_docker_daemon=True)
221
228
  # We automatically add the server prefix to the image name if
222
229
  # the user did not add it.
223
- server_prefix = f'{docker_login_config.server}/'
224
- if not specific_image.startswith(server_prefix):
225
- specific_image = f'{server_prefix}{specific_image}'
230
+ specific_image = docker_login_config.format_image(specific_image)
226
231
 
227
232
  if self.docker_config.get('pull_before_run', True):
228
233
  assert specific_image, ('Image must be included in config if ' +
@@ -83,7 +83,8 @@ def run_instances(region: str, cluster_name_on_cloud: str,
83
83
  node_type = 'head' if head_instance_id is None else 'worker'
84
84
  try:
85
85
  instance_id = utils.launch(
86
- name=f'{cluster_name_on_cloud}-{node_type}',
86
+ cluster_name=cluster_name_on_cloud,
87
+ node_type=node_type,
87
88
  instance_type=config.node_config['InstanceType'],
88
89
  region=region,
89
90
  disk_size=config.node_config['DiskSize'],
@@ -92,6 +93,8 @@ def run_instances(region: str, cluster_name_on_cloud: str,
92
93
  public_key=config.node_config['PublicKey'],
93
94
  preemptible=config.node_config['Preemptible'],
94
95
  bid_per_gpu=config.node_config['BidPerGPU'],
96
+ docker_login_config=config.provider_config.get(
97
+ 'docker_login_config'),
95
98
  )
96
99
  except Exception as e: # pylint: disable=broad-except
97
100
  logger.warning(f'run_instances error: {e}')
@@ -145,6 +148,8 @@ def terminate_instances(
145
148
  """See sky/provision/__init__.py"""
146
149
  del provider_config # unused
147
150
  instances = _filter_instances(cluster_name_on_cloud, None)
151
+ template_name, registry_auth_id = utils.get_registry_auth_resources(
152
+ cluster_name_on_cloud)
148
153
  for inst_id, inst in instances.items():
149
154
  logger.debug(f'Terminating instance {inst_id}: {inst}')
150
155
  if worker_only and inst['name'].endswith('-head'):
@@ -157,6 +162,10 @@ def terminate_instances(
157
162
  f'Failed to terminate instance {inst_id}: '
158
163
  f'{common_utils.format_exception(e, use_bracket=False)}'
159
164
  ) from e
165
+ if template_name is not None:
166
+ utils.delete_pod_template(template_name)
167
+ if registry_auth_id is not None:
168
+ utils.delete_register_auth(registry_auth_id)
160
169
 
161
170
 
162
171
  def get_cluster_info(
@@ -2,10 +2,11 @@
2
2
 
3
3
  import base64
4
4
  import time
5
- from typing import Any, Dict, List, Optional
5
+ from typing import Any, Dict, List, Optional, Tuple
6
6
 
7
7
  from sky import sky_logging
8
8
  from sky.adaptors import runpod
9
+ from sky.provision import docker_utils
9
10
  import sky.provision.runpod.api.commands as runpod_commands
10
11
  from sky.skylet import constants
11
12
  from sky.utils import common_utils
@@ -47,6 +48,11 @@ GPU_NAME_MAP = {
47
48
  }
48
49
 
49
50
 
51
+ def _construct_docker_login_template_name(cluster_name: str) -> str:
52
+ """Constructs the registry auth template name."""
53
+ return f'{cluster_name}-docker-login-template'
54
+
55
+
50
56
  def retry(func):
51
57
  """Decorator to retry a function."""
52
58
 
@@ -66,9 +72,83 @@ def retry(func):
66
72
  return wrapper
67
73
 
68
74
 
75
+ # Adapted from runpod.api.queries.pods.py::QUERY_POD.
76
+ # Adding containerRegistryAuthId to the query.
77
+ _QUERY_POD = """
78
+ query myPods {
79
+ myself {
80
+ pods {
81
+ id
82
+ containerDiskInGb
83
+ containerRegistryAuthId
84
+ costPerHr
85
+ desiredStatus
86
+ dockerArgs
87
+ dockerId
88
+ env
89
+ gpuCount
90
+ imageName
91
+ lastStatusChange
92
+ machineId
93
+ memoryInGb
94
+ name
95
+ podType
96
+ port
97
+ ports
98
+ uptimeSeconds
99
+ vcpuCount
100
+ volumeInGb
101
+ volumeMountPath
102
+ runtime {
103
+ ports{
104
+ ip
105
+ isIpPublic
106
+ privatePort
107
+ publicPort
108
+ type
109
+ }
110
+ }
111
+ machine {
112
+ gpuDisplayName
113
+ }
114
+ }
115
+ }
116
+ }
117
+ """
118
+
119
+
120
+ def _sky_get_pods() -> dict:
121
+ """List all pods with extra registry auth information.
122
+
123
+ Adapted from runpod.get_pods() to include containerRegistryAuthId.
124
+ """
125
+ raw_return = runpod.runpod.api.graphql.run_graphql_query(_QUERY_POD)
126
+ cleaned_return = raw_return['data']['myself']['pods']
127
+ return cleaned_return
128
+
129
+
130
+ _QUERY_POD_TEMPLATE_WITH_REGISTRY_AUTH = """
131
+ query myself {
132
+ myself {
133
+ podTemplates {
134
+ name
135
+ containerRegistryAuthId
136
+ }
137
+ }
138
+ }
139
+ """
140
+
141
+
142
+ def _list_pod_templates_with_container_registry() -> dict:
143
+ """List all pod templates."""
144
+ raw_return = runpod.runpod.api.graphql.run_graphql_query(
145
+ _QUERY_POD_TEMPLATE_WITH_REGISTRY_AUTH)
146
+ return raw_return['data']['myself']['podTemplates']
147
+
148
+
69
149
  def list_instances() -> Dict[str, Dict[str, Any]]:
70
150
  """Lists instances associated with API key."""
71
- instances = runpod.runpod.get_pods()
151
+ instances = _sky_get_pods()
72
152
 
73
153
  instance_dict: Dict[str, Dict[str, Any]] = {}
74
154
  for instance in instances:
@@ -100,14 +180,75 @@ def list_instances() -> Dict[str, Dict[str, Any]]:
100
180
  return instance_dict
101
181
 
102
182
 
103
- def launch(name: str, instance_type: str, region: str, disk_size: int,
104
- image_name: str, ports: Optional[List[int]], public_key: str,
105
- preemptible: Optional[bool], bid_per_gpu: float) -> str:
183
+ def delete_pod_template(template_name: str) -> None:
184
+ """Deletes a pod template."""
185
+ try:
186
+ runpod.runpod.api.graphql.run_graphql_query(
187
+ f'mutation {{deleteTemplate(templateName: "{template_name}")}}')
188
+ except runpod.runpod.error.QueryError as e:
189
+ logger.warning(f'Failed to delete template {template_name}: {e}'
190
+ 'Please delete it manually.')
191
+
192
+
193
+ def delete_register_auth(registry_auth_id: str) -> None:
194
+ """Deletes a registry auth."""
195
+ try:
196
+ runpod.runpod.delete_container_registry_auth(registry_auth_id)
197
+ except runpod.runpod.error.QueryError as e:
198
+ logger.warning(f'Failed to delete registry auth {registry_auth_id}: {e}'
199
+ 'Please delete it manually.')
200
+
201
+
202
+ def _create_template_for_docker_login(
203
+ cluster_name: str,
204
+ image_name: str,
205
+ docker_login_config: Optional[Dict[str, str]],
206
+ ) -> Tuple[str, Optional[str]]:
207
+ """Creates a template for the given image with the docker login config.
208
+
209
+ Returns:
210
+ formatted_image_name: The formatted image name.
211
+ template_id: The template ID. None for no docker login config.
212
+ """
213
+ if docker_login_config is None:
214
+ return image_name, None
215
+ login_config = docker_utils.DockerLoginConfig(**docker_login_config)
216
+ container_registry_auth_name = f'{cluster_name}-registry-auth'
217
+ container_template_name = _construct_docker_login_template_name(
218
+ cluster_name)
219
+ # The `name` argument is only for display purpose and the registry server
220
+ # will be splitted from the docker image name (Tested with AWS ECR).
221
+ # Here we only need the username and password to create the registry auth.
222
+ # TODO(tian): Now we create a template and a registry auth for each cluster.
223
+ # Consider create one for each server and reuse them. Challenges including
224
+ # calculate the reference count and delete them when no longer needed.
225
+ create_auth_resp = runpod.runpod.create_container_registry_auth(
226
+ name=container_registry_auth_name,
227
+ username=login_config.username,
228
+ password=login_config.password,
229
+ )
230
+ registry_auth_id = create_auth_resp['id']
231
+ create_template_resp = runpod.runpod.create_template(
232
+ name=container_template_name,
233
+ image_name=None,
234
+ registry_auth_id=registry_auth_id,
235
+ )
236
+ return login_config.format_image(image_name), create_template_resp['id']
237
+
238
+
239
+ def launch(cluster_name: str, node_type: str, instance_type: str, region: str,
240
+ disk_size: int, image_name: str, ports: Optional[List[int]],
241
+ public_key: str, preemptible: Optional[bool], bid_per_gpu: float,
242
+ docker_login_config: Optional[Dict[str, str]]) -> str:
106
243
  """Launches an instance with the given parameters.
107
244
 
108
245
  Converts the instance_type to the RunPod GPU name, finds the specs for the
109
246
  GPU, and launches the instance.
247
+
248
+ Returns:
249
+ instance_id: The instance ID.
110
250
  """
251
+ name = f'{cluster_name}-{node_type}'
111
252
  gpu_type = GPU_NAME_MAP[instance_type.split('_')[1]]
112
253
  gpu_quantity = int(instance_type.split('_')[0].replace('x', ''))
113
254
  cloud_type = instance_type.split('_')[2]
@@ -139,21 +280,24 @@ def launch(name: str, instance_type: str, region: str, disk_size: int,
139
280
  # Use base64 to deal with the tricky quoting issues caused by runpod API.
140
281
  encoded = base64.b64encode(setup_cmd.encode('utf-8')).decode('utf-8')
141
282
 
283
+ docker_args = (f'bash -c \'echo {encoded} | base64 --decode > init.sh; '
284
+ f'bash init.sh\'')
285
+
142
286
  # Port 8081 is occupied for nginx in the base image.
143
287
  custom_ports_str = ''
144
288
  if ports is not None:
145
289
  custom_ports_str = ''.join([f'{p}/tcp,' for p in ports])
290
+ ports_str = (f'22/tcp,'
291
+ f'{custom_ports_str}'
292
+ f'{constants.SKY_REMOTE_RAY_DASHBOARD_PORT}/http,'
293
+ f'{constants.SKY_REMOTE_RAY_PORT}/http')
146
294
 
147
- docker_args = (f'bash -c \'echo {encoded} | base64 --decode > init.sh; '
148
- f'bash init.sh\'')
149
- ports = (f'22/tcp,'
150
- f'{custom_ports_str}'
151
- f'{constants.SKY_REMOTE_RAY_DASHBOARD_PORT}/http,'
152
- f'{constants.SKY_REMOTE_RAY_PORT}/http')
295
+ image_name_formatted, template_id = _create_template_for_docker_login(
296
+ cluster_name, image_name, docker_login_config)
153
297
 
154
298
  params = {
155
299
  'name': name,
156
- 'image_name': image_name,
300
+ 'image_name': image_name_formatted,
157
301
  'gpu_type_id': gpu_type,
158
302
  'cloud_type': cloud_type,
159
303
  'container_disk_in_gb': disk_size,
@@ -161,9 +305,10 @@ def launch(name: str, instance_type: str, region: str, disk_size: int,
161
305
  'min_memory_in_gb': gpu_specs['memoryInGb'] * gpu_quantity,
162
306
  'gpu_count': gpu_quantity,
163
307
  'country_code': region,
164
- 'ports': ports,
308
+ 'ports': ports_str,
165
309
  'support_public_ip': True,
166
310
  'docker_args': docker_args,
311
+ 'template_id': template_id,
167
312
  }
168
313
 
169
314
  if preemptible is None or not preemptible:
@@ -177,6 +322,18 @@ def launch(name: str, instance_type: str, region: str, disk_size: int,
177
322
  return new_instance['id']
178
323
 
179
324
 
325
+ def get_registry_auth_resources(
326
+ cluster_name: str) -> Tuple[Optional[str], Optional[str]]:
327
+ """Gets the registry auth resources."""
328
+ container_registry_auth_name = _construct_docker_login_template_name(
329
+ cluster_name)
330
+ for template in _list_pod_templates_with_container_registry():
331
+ if template['name'] == container_registry_auth_name:
332
+ return container_registry_auth_name, template[
333
+ 'containerRegistryAuthId']
334
+ return None, None
335
+
336
+
180
337
  def remove(instance_id: str) -> None:
181
338
  """Terminates the given instance."""
182
339
  runpod.runpod.terminate_pod(instance_id)
@@ -123,7 +123,9 @@ extras_require: Dict[str, List[str]] = {
123
123
  'oci': ['oci'] + local_ray,
124
124
  'kubernetes': ['kubernetes>=20.0.0'],
125
125
  'remote': remote,
126
- 'runpod': ['runpod>=1.5.1'],
126
+ # For the container registry auth api. Reference:
127
+ # https://github.com/runpod/runpod-python/releases/tag/1.6.1
128
+ 'runpod': ['runpod>=1.6.1'],
127
129
  'fluidstack': [], # No dependencies needed for fluidstack
128
130
  'cudo': ['cudo-compute>=0.1.10'],
129
131
  'paperspace': [], # No dependencies needed for paperspace
@@ -25,7 +25,7 @@ def docker_start_cmds(
25
25
  docker_cmd,
26
26
  ):
27
27
  """Generating docker start command without --rm.
28
-
28
+
29
29
  The code is borrowed from `ray.autoscaler._private.docker`.
30
30
 
31
31
  Changes we made:
@@ -159,19 +159,17 @@ class SkyDockerCommandRunner(DockerCommandRunner):
159
159
  return True
160
160
 
161
161
  # SkyPilot: Docker login if user specified a private docker registry.
162
- if "docker_login_config" in self.docker_config:
162
+ if 'docker_login_config' in self.docker_config:
163
163
  # TODO(tian): Maybe support a command to get the login password?
164
- docker_login_config: docker_utils.DockerLoginConfig = self.docker_config[
165
- "docker_login_config"]
164
+ docker_login_config: docker_utils.DockerLoginConfig = (
165
+ self.docker_config['docker_login_config'])
166
166
  self._run_with_retry(
167
167
  f'{self.docker_cmd} login --username '
168
168
  f'{docker_login_config.username} --password '
169
169
  f'{docker_login_config.password} {docker_login_config.server}')
170
170
  # We automatically add the server prefix to the image name if
171
171
  # the user did not add it.
172
- server_prefix = f'{docker_login_config.server}/'
173
- if not specific_image.startswith(server_prefix):
174
- specific_image = f'{server_prefix}{specific_image}'
172
+ specific_image = docker_login_config.format_image(specific_image)
175
173
 
176
174
  if self.docker_config.get('pull_before_run', True):
177
175
  assert specific_image, ('Image must be included in config if '
@@ -10,6 +10,19 @@ provider:
10
10
  module: sky.provision.runpod
11
11
  region: "{{region}}"
12
12
  disable_launch_config_check: true
13
+ # For RunPod, we directly set the image id for the docker as runtime environment
14
+ # support, thus we need to avoid the DockerInitializer detects the docker field
15
+ # and performs the initialization. Therefore we put the docker login config in
16
+ # the provider config here.
17
+ {%- if docker_login_config is not none %}
18
+ docker_login_config:
19
+ username: |-
20
+ {{docker_login_config.username}}
21
+ password: |-
22
+ {{docker_login_config.password}}
23
+ server: |-
24
+ {{docker_login_config.server}}
25
+ {%- endif %}
13
26
 
14
27
  auth:
15
28
  ssh_user: root
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: skypilot-nightly
3
- Version: 1.0.0.dev20250107
3
+ Version: 1.0.0.dev20250109
4
4
  Summary: SkyPilot: An intercloud broker for the clouds
5
5
  Author: SkyPilot Team
6
6
  License: Apache 2.0
@@ -90,7 +90,7 @@ Requires-Dist: grpcio!=1.48.0,<=1.51.3,>=1.42.0; (python_version >= "3.10" and s
90
90
  Requires-Dist: protobuf!=3.19.5,>=3.15.3; extra == "remote"
91
91
  Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3; extra == "remote"
92
92
  Provides-Extra: runpod
93
- Requires-Dist: runpod>=1.5.1; extra == "runpod"
93
+ Requires-Dist: runpod>=1.6.1; extra == "runpod"
94
94
  Provides-Extra: fluidstack
95
95
  Provides-Extra: cudo
96
96
  Requires-Dist: cudo-compute>=0.1.10; extra == "cudo"
@@ -140,12 +140,21 @@ Requires-Dist: grpcio!=1.48.0,<=1.51.3,>=1.32.0; (python_version < "3.10" and sy
140
140
  Requires-Dist: grpcio!=1.48.0,<=1.51.3,>=1.42.0; (python_version >= "3.10" and sys_platform != "darwin") and extra == "all"
141
141
  Requires-Dist: protobuf!=3.19.5,>=3.15.3; extra == "all"
142
142
  Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3; extra == "all"
143
- Requires-Dist: runpod>=1.5.1; extra == "all"
143
+ Requires-Dist: runpod>=1.6.1; extra == "all"
144
144
  Requires-Dist: cudo-compute>=0.1.10; extra == "all"
145
145
  Requires-Dist: pydo>=0.3.0; extra == "all"
146
146
  Requires-Dist: azure-core>=1.24.0; extra == "all"
147
147
  Requires-Dist: azure-common; extra == "all"
148
148
  Requires-Dist: pyvmomi==8.0.1.0.2; extra == "all"
149
+ Dynamic: author
150
+ Dynamic: classifier
151
+ Dynamic: description
152
+ Dynamic: description-content-type
153
+ Dynamic: license
154
+ Dynamic: project-url
155
+ Dynamic: provides-extra
156
+ Dynamic: requires-dist
157
+ Dynamic: summary
149
158
 
150
159
  <p align="center">
151
160
  <img alt="SkyPilot" src="https://raw.githubusercontent.com/skypilot-org/skypilot/master/docs/source/images/skypilot-wide-light-1k.png" width=55%>
@@ -1,6 +1,6 @@
1
- sky/__init__.py,sha256=hrWDistOqTlG6oaOm4PRKysqzbfeeYqb9MZGb4zqiMc,5944
1
+ sky/__init__.py,sha256=hTD_EweXO9PykuI558pLbxRiUikldWFXfOtq9aQeZ7c,5944
2
2
  sky/admin_policy.py,sha256=hPo02f_A32gCqhUueF0QYy1fMSSKqRwYEg_9FxScN_s,3248
3
- sky/authentication.py,sha256=kACHmiZgWgRpYd1wx1ofbXRMErfMcFmWrkw4a9NxYrY,20988
3
+ sky/authentication.py,sha256=LXUDABKP1FJCS256xTTDJa40WXwHKF5x49S-4hZbD1M,21501
4
4
  sky/check.py,sha256=s8deMVL-k9y8gd519K7NWZc3DqWsEySwiAr0uH3Vvcc,9459
5
5
  sky/cli.py,sha256=KbvwSMgQJyW-XuX-N_-JFvBRVAEvy295j4UcxypwbyU,214398
6
6
  sky/cloud_stores.py,sha256=PcLT57_8SZy7o6paAluElfBynaLkbaOq3l-8dNg1AVM,23672
@@ -41,7 +41,7 @@ sky/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  sky/benchmark/benchmark_state.py,sha256=X8CXmuU9KgsDRhKedhFgjeRMUFWtQsjFs1qECvPG2yg,8723
42
42
  sky/benchmark/benchmark_utils.py,sha256=mP8Ox2WiKfthq6LcUAZnHknFQ0n8v9o_rCh1LXLgkqc,26192
43
43
  sky/clouds/__init__.py,sha256=iORaV6auqMxa6-6FKgt1C9f3UqRk1GASUtakua3tb9A,1395
44
- sky/clouds/aws.py,sha256=K9U_nKb2_bJcZ3adarUjIaIzIr8fQiDu470I_yG3Syo,52893
44
+ sky/clouds/aws.py,sha256=bP7ZuHNE47pbCKXob3rxMhby92lbQVrpJk6dAbPIK9k,53474
45
45
  sky/clouds/azure.py,sha256=KtnnNZn4ZEr7xndBHxX91v0YXSI1QWPgIefuM1zDUBA,30784
46
46
  sky/clouds/cloud.py,sha256=5_ZduUcyCEY1JnX_h0PrJ5xwtPP4oor4jf6cICgSArc,35370
47
47
  sky/clouds/cloud_registry.py,sha256=oLoYFjm_SDTgdHokY7b6A5Utq80HXRQNxV0fLjDdVsQ,2361
@@ -109,13 +109,13 @@ sky/jobs/dashboard/templates/index.html,sha256=su1tqgcsXNl1lGl9hfIR6ig1f531OO57x
109
109
  sky/provision/__init__.py,sha256=rnuwL9x3qQGhX3EYW6KyZWfw_yBqGSiFBDz86T5xus4,6339
110
110
  sky/provision/common.py,sha256=E8AlSUFcn0FYQq1erNmoVfMAdsF9tP2yxfyk-9PLvQU,10286
111
111
  sky/provision/constants.py,sha256=oc_XDUkcoLQ_lwDy5yMeMSWviKS0j0s1c0pjlvpNeWY,800
112
- sky/provision/docker_utils.py,sha256=PKh866psTqix9PM1wBD0puUMqgdY5pvb5PUtQZUUdcM,19477
112
+ sky/provision/docker_utils.py,sha256=ENm0LkyrYWic3Ikyacho8X5uDMvGsbkZQsb6kNH1DuI,19629
113
113
  sky/provision/instance_setup.py,sha256=8Pudbpke6ah0xufr2UwtsDnNZ64-aAYkz8M44ZA0huI,23218
114
114
  sky/provision/logging.py,sha256=yZWgejrFBhhRjAtvFu5N5bRXIMK5TuwNjp1vKQqz2pw,2103
115
115
  sky/provision/metadata_utils.py,sha256=LrxeV4wD2QPzNdXV_npj8q-pr35FatxBBjF_jSbpOT0,4013
116
116
  sky/provision/provisioner.py,sha256=ZOgFOO0NB4QZVPwd4qikRqi615Bq67n0Vcl3cTDVxNE,29153
117
117
  sky/provision/aws/__init__.py,sha256=mxq8PeWJqUtalDozTNpbtENErRZ1ktEs8uf2aG9UUgU,731
118
- sky/provision/aws/config.py,sha256=X0yChaZTBjx0IR7lsJwhzhb0Zcbz5w7nNpe1HMYBOfM,24196
118
+ sky/provision/aws/config.py,sha256=_8jvi8UVMtIVChDDnv5uHV2CoPyKvKqvxJ4xIEBYdDc,24629
119
119
  sky/provision/aws/instance.py,sha256=eCslJ2XfJo_pkQMnKFQqhGnUIRvwKiT12oxBY5-klss,40750
120
120
  sky/provision/aws/utils.py,sha256=m49pS-SHGW7Au3bhDeTPsL8N5iRzbwOXzyEWRCc1Vho,3238
121
121
  sky/provision/azure/__init__.py,sha256=87cgk1_Ws7n9rqaDDPv-HpfrkVeSQMdFQnhnXwyx9g4,548
@@ -166,8 +166,8 @@ sky/provision/paperspace/instance.py,sha256=YAIzHEYdO8MRK8iLdweMpY2U28OMCoUvPEwf
166
166
  sky/provision/paperspace/utils.py,sha256=uOmxbDKjV6skFizC4gYXSxRuEqso5ck2kF7MbtNmhEs,9580
167
167
  sky/provision/runpod/__init__.py,sha256=6HYvHI27EaLrX1SS0vWVhdLu5HDBeZCdvAeDJuwM5pk,556
168
168
  sky/provision/runpod/config.py,sha256=9ulZJVL7nHuxhTdoj8D7lNn7SdicJ5zc6FIcHIG9tcg,321
169
- sky/provision/runpod/instance.py,sha256=S8GP00dQgp55oP4Hq3K-LUsYg36oJGMxeRhQwFFt7EA,9945
170
- sky/provision/runpod/utils.py,sha256=yWI4rjdjAp23-Zc-kr76qkt2KsMdU2wtNrn2ATOEibE,7227
169
+ sky/provision/runpod/instance.py,sha256=FNalpTQMvnmACdtFsGvVPVhEkzdqrlmd_pExn33bIQ8,10358
170
+ sky/provision/runpod/utils.py,sha256=2L4MUrFi4rQOP26IeAkPNQ9oWGPJhH5fvz7NAbL3nNQ,12421
171
171
  sky/provision/runpod/api/__init__.py,sha256=eJwjPeQZ5B7chf4-Bl4YeI2Uo9aLX4M1rr2NmPk89_E,112
172
172
  sky/provision/runpod/api/commands.py,sha256=oh77PS0H0wZudHV8II9ceRuaFQ8FN4NJ4S3-6_PeqPM,4238
173
173
  sky/provision/runpod/api/pods.py,sha256=GMwxgNr9NnHPfyh2Y9b8S_vLhrLY4h7LybFBBQNAyfw,4948
@@ -199,7 +199,7 @@ sky/serve/serve_utils.py,sha256=WgPcqEw3WyMOdgRTFg8DSsWyIG1xnRbRkI1-f09tNKg,3974
199
199
  sky/serve/service.py,sha256=7bvK9R9D48PZSYcOKSievXQ2mHUMk1d3AAIxtra7WOI,12083
200
200
  sky/serve/service_spec.py,sha256=mph-IRhamiFls4RX_8yhC0lTLzbIxGYbnvosy7VZTi4,14999
201
201
  sky/setup_files/MANIFEST.in,sha256=WF0T89NLichHxZDDSQzvSpiONtAEFyur2MPmGczgTIo,555
202
- sky/setup_files/dependencies.py,sha256=cF_mLf8DTFrK8eCH6EAB6ggkW2hChX0X1jh8GnqePFY,5968
202
+ sky/setup_files/dependencies.py,sha256=ujGG0rFG8TWGgJv21N-xD0fetYRlaf_xV8ILdsCQDiU,6087
203
203
  sky/setup_files/setup.py,sha256=HMqAIxHrhtQUOlm6_Iz5E_bL4dUvsYgXc9YVQIFayPs,7417
204
204
  sky/skylet/LICENSE,sha256=BnFrJSvUFpMUoH5mOpWnEvaC5R6Uux8W6WXgrte8iYg,12381
205
205
  sky/skylet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -214,7 +214,7 @@ sky/skylet/log_lib.pyi,sha256=VpA_VoL970Noj-YrBkKqLxFi34JVMY7KLrOQ3o4AqEI,4336
214
214
  sky/skylet/skylet.py,sha256=U9plr5hmhD9-Nyy0LMCymlE8DWtRXTFXQvfbFsS746Y,1153
215
215
  sky/skylet/subprocess_daemon.py,sha256=gcL-_Hea7-SrBUyZfAbo40RBFbaeuBmPCW0dm4YYkPo,3537
216
216
  sky/skylet/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
217
- sky/skylet/providers/command_runner.py,sha256=z60lOGeG07GwEdPYWvcXFbW615zyAz3FV4vFsKP8ULs,16373
217
+ sky/skylet/providers/command_runner.py,sha256=DdBKP0QX325_N3zAVYwnmXmfbfXNqkzWQZpF9DSR7Go,16259
218
218
  sky/skylet/providers/ibm/__init__.py,sha256=GXo5F9ztvs0qMDI_G9wM5KvzySfYugslJMHHAnBENRc,94
219
219
  sky/skylet/providers/ibm/node_provider.py,sha256=PoKp-lyIT2eE6BLqljufhZtGlTrJLe8ebk6mMj2KMdU,38265
220
220
  sky/skylet/providers/ibm/utils.py,sha256=63vhKqLLOhAZdibSp8VWWONeyCER9F6U2VLrSpzlizk,1292
@@ -247,7 +247,7 @@ sky/templates/lambda-ray.yml.j2,sha256=HyvO_tX2vxwSsc4IFVSqGuIbjLMk0bevP9bcxb8ZQ
247
247
  sky/templates/local-ray.yml.j2,sha256=FNHeyHF6nW9nU9QLIZceUWfvrFTTcO51KqhTnYCEFaA,1185
248
248
  sky/templates/oci-ray.yml.j2,sha256=92dvXGaUd2Kwep9fgTjOsAPJiBLr8GQTjy7pFvuPAyE,4562
249
249
  sky/templates/paperspace-ray.yml.j2,sha256=HQjZNamrB_a4fOMCxQXSVdV5JIHtbGtAE0JzEO8uuVQ,4021
250
- sky/templates/runpod-ray.yml.j2,sha256=9rOgWHrvzxSKRuh3hmFlWprpVKLFMLbH6vpM5eY73KE,3762
250
+ sky/templates/runpod-ray.yml.j2,sha256=bUiF4Y_EkCA_GKLtTzPXbajdL-NOUiJ38Pe4dZd2dys,4284
251
251
  sky/templates/scp-ray.yml.j2,sha256=I9u8Ax-lit-d6UrCC9BVU8avst8w1cwK6TrzZBcz_JM,5608
252
252
  sky/templates/sky-serve-controller.yaml.j2,sha256=V1IiYhArv_D_7JzC3sVN4nKlSCCCL1AYtIdxFSa-f4c,1628
253
253
  sky/templates/vsphere-ray.yml.j2,sha256=cOQ-qdpxGA2FHajMMhTJI-SmlYzdPterX4Gsiq-nkb0,3587
@@ -288,9 +288,9 @@ sky/utils/kubernetes/k8s_gpu_labeler_job.yaml,sha256=k0TBoQ4zgf79-sVkixKSGYFHQ7Z
288
288
  sky/utils/kubernetes/k8s_gpu_labeler_setup.yaml,sha256=VLKT2KKimZu1GDg_4AIlIt488oMQvhRZWwsj9vBbPUg,3812
289
289
  sky/utils/kubernetes/rsync_helper.sh,sha256=h4YwrPFf9727CACnMJvF3EyK_0OeOYKKt4su_daKekw,1256
290
290
  sky/utils/kubernetes/ssh_jump_lifecycle_manager.py,sha256=Kq1MDygF2IxFmu9FXpCxqucXLmeUrvs6OtRij6XTQbo,6554
291
- skypilot_nightly-1.0.0.dev20250107.dist-info/LICENSE,sha256=emRJAvE7ngL6x0RhQvlns5wJzGI3NEQ_WMjNmd9TZc4,12170
292
- skypilot_nightly-1.0.0.dev20250107.dist-info/METADATA,sha256=i8irPjzNj_jQfGim8w2tbF7rrbwS-FlTxIOdizEx3Dc,20439
293
- skypilot_nightly-1.0.0.dev20250107.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
294
- skypilot_nightly-1.0.0.dev20250107.dist-info/entry_points.txt,sha256=StA6HYpuHj-Y61L2Ze-hK2IcLWgLZcML5gJu8cs6nU4,36
295
- skypilot_nightly-1.0.0.dev20250107.dist-info/top_level.txt,sha256=qA8QuiNNb6Y1OF-pCUtPEr6sLEwy2xJX06Bd_CrtrHY,4
296
- skypilot_nightly-1.0.0.dev20250107.dist-info/RECORD,,
291
+ skypilot_nightly-1.0.0.dev20250109.dist-info/LICENSE,sha256=emRJAvE7ngL6x0RhQvlns5wJzGI3NEQ_WMjNmd9TZc4,12170
292
+ skypilot_nightly-1.0.0.dev20250109.dist-info/METADATA,sha256=3esWriJs7mn5M_6alzm4FmYsK8_6E-X60jkRwSdODtY,20632
293
+ skypilot_nightly-1.0.0.dev20250109.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
294
+ skypilot_nightly-1.0.0.dev20250109.dist-info/entry_points.txt,sha256=StA6HYpuHj-Y61L2Ze-hK2IcLWgLZcML5gJu8cs6nU4,36
295
+ skypilot_nightly-1.0.0.dev20250109.dist-info/top_level.txt,sha256=qA8QuiNNb6Y1OF-pCUtPEr6sLEwy2xJX06Bd_CrtrHY,4
296
+ skypilot_nightly-1.0.0.dev20250109.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.7.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5