skypilot-nightly 1.0.0.dev20250408__py3-none-any.whl → 1.0.0.dev20250411__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sky/__init__.py +2 -2
- sky/adaptors/azure.py +1 -1
- sky/adaptors/nebius.py +5 -27
- sky/backends/backend.py +9 -7
- sky/backends/cloud_vm_ray_backend.py +7 -7
- sky/backends/local_docker_backend.py +3 -3
- sky/client/common.py +4 -2
- sky/client/sdk.py +58 -26
- sky/cloud_stores.py +0 -4
- sky/clouds/do.py +4 -5
- sky/clouds/gcp.py +5 -3
- sky/clouds/nebius.py +22 -12
- sky/clouds/service_catalog/data_fetchers/fetch_ibm.py +1 -2
- sky/clouds/service_catalog/gcp_catalog.py +37 -10
- sky/core.py +6 -6
- sky/data/data_utils.py +5 -9
- sky/data/mounting_utils.py +1 -1
- sky/data/storage.py +25 -31
- sky/data/storage_utils.py +27 -18
- sky/execution.py +11 -4
- sky/jobs/client/sdk.py +5 -0
- sky/jobs/server/server.py +5 -1
- sky/optimizer.py +1 -2
- sky/provision/do/utils.py +19 -16
- sky/provision/gcp/config.py +30 -20
- sky/serve/client/sdk.py +6 -0
- sky/server/common.py +16 -1
- sky/server/constants.py +5 -0
- sky/setup_files/dependencies.py +1 -1
- sky/skylet/log_lib.py +4 -0
- sky/skypilot_config.py +19 -30
- sky/task.py +27 -7
- sky/utils/schemas.py +25 -7
- {skypilot_nightly-1.0.0.dev20250408.dist-info → skypilot_nightly-1.0.0.dev20250411.dist-info}/METADATA +2 -2
- {skypilot_nightly-1.0.0.dev20250408.dist-info → skypilot_nightly-1.0.0.dev20250411.dist-info}/RECORD +39 -39
- {skypilot_nightly-1.0.0.dev20250408.dist-info → skypilot_nightly-1.0.0.dev20250411.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250408.dist-info → skypilot_nightly-1.0.0.dev20250411.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250408.dist-info → skypilot_nightly-1.0.0.dev20250411.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250408.dist-info → skypilot_nightly-1.0.0.dev20250411.dist-info}/top_level.txt +0 -0
sky/provision/do/utils.py
CHANGED
@@ -15,6 +15,7 @@ from sky.adaptors import do
|
|
15
15
|
from sky.provision import common
|
16
16
|
from sky.provision import constants as provision_constants
|
17
17
|
from sky.provision.do import constants
|
18
|
+
from sky.utils import annotations
|
18
19
|
from sky.utils import common_utils
|
19
20
|
|
20
21
|
logger = sky_logging.init_logger(__name__)
|
@@ -31,7 +32,6 @@ MAX_BACKOFF_FACTOR = 10
|
|
31
32
|
MAX_ATTEMPTS = 6
|
32
33
|
SSH_KEY_NAME_ON_DO = f'sky-key-{common_utils.get_user_hash()}'
|
33
34
|
|
34
|
-
CREDENTIALS_PATH = '~/.config/doctl/config.yaml'
|
35
35
|
_client = None
|
36
36
|
_ssh_key_id = None
|
37
37
|
|
@@ -40,31 +40,34 @@ class DigitalOceanError(Exception):
|
|
40
40
|
pass
|
41
41
|
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
CREDENTIALS_PATH = None
|
43
|
+
@annotations.lru_cache(scope='request')
|
44
|
+
def get_credentials_path():
|
45
|
+
credentials_path = None
|
47
46
|
credentials_found = 0
|
48
47
|
for path in POSSIBLE_CREDENTIALS_PATHS:
|
49
48
|
if os.path.exists(path):
|
50
|
-
CREDENTIALS_PATH = path
|
51
|
-
credentials_found += 1
|
52
49
|
logger.debug(f'Digital Ocean credential path found at {path}')
|
53
|
-
|
54
|
-
|
55
|
-
if
|
56
|
-
|
57
|
-
|
58
|
-
f'the following paths {POSSIBLE_CREDENTIALS_PATHS}')
|
50
|
+
credentials_path = path
|
51
|
+
credentials_found += 1
|
52
|
+
if credentials_found > 1:
|
53
|
+
logger.debug('More than 1 credential file found')
|
54
|
+
return credentials_path
|
59
55
|
|
56
|
+
|
57
|
+
def _init_client():
|
58
|
+
global _client
|
59
|
+
assert _client is None
|
60
60
|
# attempt default context
|
61
|
-
|
61
|
+
if get_credentials_path() is None:
|
62
|
+
raise DigitalOceanError(
|
63
|
+
'No credentials found, please run `doctl auth init`')
|
64
|
+
credentials = common_utils.read_yaml(get_credentials_path())
|
62
65
|
default_token = credentials.get('access-token', None)
|
63
66
|
if default_token is not None:
|
64
67
|
try:
|
65
68
|
test_client = do.pydo.Client(token=default_token)
|
66
69
|
test_client.droplets.list()
|
67
|
-
logger.debug('
|
70
|
+
logger.debug('Trying `default` context')
|
68
71
|
_client = test_client
|
69
72
|
return _client
|
70
73
|
except do.exceptions().HttpResponseError:
|
@@ -76,7 +79,7 @@ def _init_client():
|
|
76
79
|
try:
|
77
80
|
test_client = do.pydo.Client(token=api_token)
|
78
81
|
test_client.droplets.list()
|
79
|
-
logger.debug(f'
|
82
|
+
logger.debug(f'Using "{context}" context')
|
80
83
|
_client = test_client
|
81
84
|
break
|
82
85
|
except do.exceptions().HttpResponseError:
|
sky/provision/gcp/config.py
CHANGED
@@ -571,35 +571,45 @@ def get_usable_vpc_and_subnet(
|
|
571
571
|
|
572
572
|
specific_vpc_to_use = config.provider_config.get('vpc_name', None)
|
573
573
|
if specific_vpc_to_use is not None:
|
574
|
+
if '/' in specific_vpc_to_use:
|
575
|
+
# VPC can also be specified in the format PROJECT_ID/VPC_NAME.
|
576
|
+
# This enables use of shared VPCs.
|
577
|
+
split_vpc_value = specific_vpc_to_use.split('/')
|
578
|
+
if len(split_vpc_value) != 2:
|
579
|
+
raise ValueError(f'Invalid VPC name: {specific_vpc_to_use}. '
|
580
|
+
'Please specify the VPC name in the format '
|
581
|
+
'PROJECT_ID/VPC_NAME.')
|
582
|
+
project_id = split_vpc_value[0]
|
583
|
+
specific_vpc_to_use = split_vpc_value[1]
|
584
|
+
|
574
585
|
vpcnets_all = _list_vpcnets(project_id,
|
575
586
|
compute,
|
576
587
|
filter=f'name={specific_vpc_to_use}')
|
577
|
-
|
578
|
-
assert (len(vpcnets_all) <=
|
579
|
-
1), (f'{len(vpcnets_all)} VPCs found with the same name '
|
580
|
-
f'{specific_vpc_to_use}')
|
581
|
-
if len(vpcnets_all) == 1:
|
582
|
-
# Skip checking any firewall rules if the user has specified a VPC.
|
583
|
-
logger.info(f'Using user-specified VPC {specific_vpc_to_use!r}.')
|
584
|
-
subnets = _list_subnets(project_id,
|
585
|
-
region,
|
586
|
-
compute,
|
587
|
-
network=specific_vpc_to_use)
|
588
|
-
if not subnets:
|
589
|
-
_skypilot_log_error_and_exit_for_failover(
|
590
|
-
'SUBNET_NOT_FOUND_FOR_VPC',
|
591
|
-
f'No subnet for region {region} found for specified VPC '
|
592
|
-
f'{specific_vpc_to_use!r}. '
|
593
|
-
f'Check the subnets of VPC {specific_vpc_to_use!r} at '
|
594
|
-
'https://console.cloud.google.com/networking/networks')
|
595
|
-
return specific_vpc_to_use, subnets[0]
|
596
|
-
else:
|
588
|
+
if not vpcnets_all:
|
597
589
|
# VPC with this name not found. Error out and let SkyPilot failover.
|
598
590
|
_skypilot_log_error_and_exit_for_failover(
|
599
591
|
'VPC_NOT_FOUND',
|
600
592
|
f'No VPC with name {specific_vpc_to_use!r} is found. '
|
601
593
|
'To fix: specify a correct VPC name.')
|
602
594
|
# Should not reach here.
|
595
|
+
assert False
|
596
|
+
|
597
|
+
# On GCP, VPC names are unique within a project.
|
598
|
+
assert len(vpcnets_all) == 1, (vpcnets_all, specific_vpc_to_use)
|
599
|
+
# Skip checking any firewall rules if the user has specified a VPC.
|
600
|
+
logger.info(f'Using user-specified VPC {specific_vpc_to_use!r}.')
|
601
|
+
subnets = _list_subnets(project_id,
|
602
|
+
region,
|
603
|
+
compute,
|
604
|
+
network=specific_vpc_to_use)
|
605
|
+
if not subnets:
|
606
|
+
_skypilot_log_error_and_exit_for_failover(
|
607
|
+
'SUBNET_NOT_FOUND_FOR_VPC',
|
608
|
+
f'No subnet for region {region} found for specified VPC '
|
609
|
+
f'{specific_vpc_to_use!r}. '
|
610
|
+
f'Check the subnets of VPC {specific_vpc_to_use!r} at '
|
611
|
+
'https://console.cloud.google.com/networking/networks')
|
612
|
+
return specific_vpc_to_use, subnets[0]
|
603
613
|
|
604
614
|
subnets_all = _list_subnets(project_id, region, compute)
|
605
615
|
|
sky/serve/client/sdk.py
CHANGED
@@ -74,6 +74,7 @@ def up(
|
|
74
74
|
f'{server_common.get_server_url()}/serve/up',
|
75
75
|
json=json.loads(body.model_dump_json()),
|
76
76
|
timeout=(5, None),
|
77
|
+
cookies=server_common.get_api_cookie_jar(),
|
77
78
|
)
|
78
79
|
return server_common.get_request_id(response)
|
79
80
|
|
@@ -132,6 +133,7 @@ def update(
|
|
132
133
|
f'{server_common.get_server_url()}/serve/update',
|
133
134
|
json=json.loads(body.model_dump_json()),
|
134
135
|
timeout=(5, None),
|
136
|
+
cookies=server_common.get_api_cookie_jar(),
|
135
137
|
)
|
136
138
|
return server_common.get_request_id(response)
|
137
139
|
|
@@ -173,6 +175,7 @@ def down(
|
|
173
175
|
f'{server_common.get_server_url()}/serve/down',
|
174
176
|
json=json.loads(body.model_dump_json()),
|
175
177
|
timeout=(5, None),
|
178
|
+
cookies=server_common.get_api_cookie_jar(),
|
176
179
|
)
|
177
180
|
return server_common.get_request_id(response)
|
178
181
|
|
@@ -207,6 +210,7 @@ def terminate_replica(service_name: str, replica_id: int,
|
|
207
210
|
f'{server_common.get_server_url()}/serve/terminate-replica',
|
208
211
|
json=json.loads(body.model_dump_json()),
|
209
212
|
timeout=(5, None),
|
213
|
+
cookies=server_common.get_api_cookie_jar(),
|
210
214
|
)
|
211
215
|
return server_common.get_request_id(response)
|
212
216
|
|
@@ -279,6 +283,7 @@ def status(
|
|
279
283
|
f'{server_common.get_server_url()}/serve/status',
|
280
284
|
json=json.loads(body.model_dump_json()),
|
281
285
|
timeout=(5, None),
|
286
|
+
cookies=server_common.get_api_cookie_jar(),
|
282
287
|
)
|
283
288
|
return server_common.get_request_id(response)
|
284
289
|
|
@@ -365,6 +370,7 @@ def tail_logs(service_name: str,
|
|
365
370
|
json=json.loads(body.model_dump_json()),
|
366
371
|
timeout=(5, None),
|
367
372
|
stream=True,
|
373
|
+
cookies=server_common.get_api_cookie_jar(),
|
368
374
|
)
|
369
375
|
request_id = server_common.get_request_id(response)
|
370
376
|
sdk.stream_response(request_id, response, output_stream)
|
sky/server/common.py
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
import dataclasses
|
4
4
|
import enum
|
5
5
|
import functools
|
6
|
+
from http.cookiejar import MozillaCookieJar
|
6
7
|
import json
|
7
8
|
import os
|
8
9
|
import pathlib
|
@@ -80,6 +81,18 @@ class ApiServerInfo:
|
|
80
81
|
api_version: ApiVersion
|
81
82
|
|
82
83
|
|
84
|
+
def get_api_cookie_jar() -> requests.cookies.RequestsCookieJar:
|
85
|
+
"""Returns the cookie jar used by the client to access the API server."""
|
86
|
+
cookie_file = os.environ.get(server_constants.API_COOKIE_FILE_ENV_VAR)
|
87
|
+
cookie_jar = requests.cookies.RequestsCookieJar()
|
88
|
+
if cookie_file and os.path.exists(cookie_file):
|
89
|
+
cookie_path = pathlib.Path(cookie_file).expanduser().resolve()
|
90
|
+
file_cookie_jar = MozillaCookieJar(cookie_path)
|
91
|
+
file_cookie_jar.load()
|
92
|
+
cookie_jar.update(file_cookie_jar)
|
93
|
+
return cookie_jar
|
94
|
+
|
95
|
+
|
83
96
|
@annotations.lru_cache(scope='global')
|
84
97
|
def get_server_url(host: Optional[str] = None) -> str:
|
85
98
|
endpoint = DEFAULT_SERVER_URL
|
@@ -117,7 +130,9 @@ def get_api_server_status(endpoint: Optional[str] = None) -> ApiServerInfo:
|
|
117
130
|
server_url = endpoint if endpoint is not None else get_server_url()
|
118
131
|
while time_out_try_count <= RETRY_COUNT_ON_TIMEOUT:
|
119
132
|
try:
|
120
|
-
response = requests.get(f'{server_url}/api/health',
|
133
|
+
response = requests.get(f'{server_url}/api/health',
|
134
|
+
timeout=2.5,
|
135
|
+
cookies=get_api_cookie_jar())
|
121
136
|
if response.status_code == 200:
|
122
137
|
try:
|
123
138
|
result = response.json()
|
sky/server/constants.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
"""Constants for the API servers."""
|
2
2
|
|
3
|
+
from sky.skylet import constants
|
4
|
+
|
3
5
|
# API server version, whenever there is a change in API server that requires a
|
4
6
|
# restart of the local API server or error out when the client does not match
|
5
7
|
# the server version.
|
@@ -19,3 +21,6 @@ API_SERVER_REQUEST_DB_PATH = '~/.sky/api_server/requests.db'
|
|
19
21
|
# The interval (seconds) for the cluster status to be refreshed in the
|
20
22
|
# background.
|
21
23
|
CLUSTER_REFRESH_DAEMON_INTERVAL_SECONDS = 60
|
24
|
+
|
25
|
+
# Environment variable for a file path to the API cookie file.
|
26
|
+
API_COOKIE_FILE_ENV_VAR = f'{constants.SKYPILOT_ENV_VAR_PREFIX}API_COOKIE_FILE'
|
sky/setup_files/dependencies.py
CHANGED
sky/skylet/log_lib.py
CHANGED
@@ -149,6 +149,7 @@ def run_with_log(
|
|
149
149
|
process_stream: bool = True,
|
150
150
|
line_processor: Optional[log_utils.LineProcessor] = None,
|
151
151
|
streaming_prefix: Optional[str] = None,
|
152
|
+
log_cmd: bool = False,
|
152
153
|
**kwargs,
|
153
154
|
) -> Union[int, Tuple[int, str, str]]:
|
154
155
|
"""Runs a command and logs its output to a file.
|
@@ -182,6 +183,9 @@ def run_with_log(
|
|
182
183
|
# the terminal output when typing in the terminal that starts the API
|
183
184
|
# server.
|
184
185
|
stdin = kwargs.pop('stdin', subprocess.DEVNULL)
|
186
|
+
if log_cmd:
|
187
|
+
with open(log_path, 'a', encoding='utf-8') as f:
|
188
|
+
print(f'Running command: {cmd}', file=f)
|
185
189
|
with subprocess.Popen(cmd,
|
186
190
|
stdout=stdout_arg,
|
187
191
|
stderr=stderr_arg,
|
sky/skypilot_config.py
CHANGED
@@ -52,7 +52,6 @@ import contextlib
|
|
52
52
|
import copy
|
53
53
|
import os
|
54
54
|
import pprint
|
55
|
-
import tempfile
|
56
55
|
import typing
|
57
56
|
from typing import Any, Dict, Iterator, Optional, Tuple
|
58
57
|
|
@@ -92,6 +91,7 @@ CONFIG_PATH = '~/.sky/config.yaml'
|
|
92
91
|
# The loaded config.
|
93
92
|
_dict = config_utils.Config()
|
94
93
|
_loaded_config_path: Optional[str] = None
|
94
|
+
_config_overridden: bool = False
|
95
95
|
|
96
96
|
|
97
97
|
def get_nested(keys: Tuple[str, ...],
|
@@ -178,7 +178,10 @@ def _reload_config() -> None:
|
|
178
178
|
|
179
179
|
|
180
180
|
def loaded_config_path() -> Optional[str]:
|
181
|
-
"""Returns the path to the loaded config file
|
181
|
+
"""Returns the path to the loaded config file, or
|
182
|
+
'<overridden>' if the config is overridden."""
|
183
|
+
if _config_overridden:
|
184
|
+
return '<overridden>'
|
182
185
|
return _loaded_config_path
|
183
186
|
|
184
187
|
|
@@ -195,31 +198,30 @@ def loaded() -> bool:
|
|
195
198
|
def override_skypilot_config(
|
196
199
|
override_configs: Optional[Dict[str, Any]]) -> Iterator[None]:
|
197
200
|
"""Overrides the user configurations."""
|
201
|
+
global _dict, _config_overridden
|
198
202
|
# TODO(SKY-1215): allow admin user to extend the disallowed keys or specify
|
199
203
|
# allowed keys.
|
200
204
|
if not override_configs:
|
201
205
|
# If no override configs (None or empty dict), do nothing.
|
202
206
|
yield
|
203
207
|
return
|
204
|
-
|
205
|
-
original_config = dict(_dict)
|
208
|
+
original_config = _dict
|
206
209
|
config = _dict.get_nested(
|
207
210
|
keys=tuple(),
|
208
211
|
default_value=None,
|
209
212
|
override_configs=override_configs,
|
210
213
|
allowed_override_keys=None,
|
211
214
|
disallowed_override_keys=constants.SKIPPED_CLIENT_OVERRIDE_KEYS)
|
212
|
-
with tempfile.NamedTemporaryFile(
|
213
|
-
mode='w',
|
214
|
-
prefix='skypilot_config',
|
215
|
-
# Have to avoid deleting the file as the underlying function needs
|
216
|
-
# to read the config file, and we need to close the file mode='w'
|
217
|
-
# to enable reading.
|
218
|
-
delete=False) as f:
|
219
|
-
common_utils.dump_yaml(f.name, dict(config))
|
220
|
-
os.environ[ENV_VAR_SKYPILOT_CONFIG] = f.name
|
221
215
|
try:
|
222
|
-
|
216
|
+
common_utils.validate_schema(
|
217
|
+
config,
|
218
|
+
schemas.get_config_schema(),
|
219
|
+
f'Invalid config {config}. See: '
|
220
|
+
'https://docs.skypilot.co/en/latest/reference/config.html. ' # pylint: disable=line-too-long
|
221
|
+
'Error: ',
|
222
|
+
skip_none=False)
|
223
|
+
_config_overridden = True
|
224
|
+
_dict = config
|
223
225
|
yield
|
224
226
|
except exceptions.InvalidSkyPilotConfigError as e:
|
225
227
|
with ux_utils.print_exception_no_traceback():
|
@@ -227,23 +229,10 @@ def override_skypilot_config(
|
|
227
229
|
'Failed to override the SkyPilot config on API '
|
228
230
|
'server with your local SkyPilot config:\n'
|
229
231
|
'=== SkyPilot config on API server ===\n'
|
230
|
-
f'{common_utils.dump_yaml_str(original_config)}\n'
|
232
|
+
f'{common_utils.dump_yaml_str(dict(original_config))}\n'
|
231
233
|
'=== Your local SkyPilot config ===\n'
|
232
234
|
f'{common_utils.dump_yaml_str(override_configs)}\n'
|
233
235
|
f'Details: {e}') from e
|
234
|
-
|
235
236
|
finally:
|
236
|
-
|
237
|
-
|
238
|
-
else:
|
239
|
-
os.environ.pop(ENV_VAR_SKYPILOT_CONFIG, None)
|
240
|
-
# Reload the config to restore the original config to avoid the next
|
241
|
-
# request reusing the same process to use the config for the current
|
242
|
-
# request.
|
243
|
-
_reload_config()
|
244
|
-
|
245
|
-
try:
|
246
|
-
os.remove(f.name)
|
247
|
-
except Exception: # pylint: disable=broad-except
|
248
|
-
# Failing to delete the file is not critical.
|
249
|
-
pass
|
237
|
+
_dict = original_config
|
238
|
+
_config_overridden = False
|
sky/task.py
CHANGED
@@ -552,15 +552,35 @@ class Task:
|
|
552
552
|
estimated_size_gigabytes=estimated_size_gigabytes)
|
553
553
|
|
554
554
|
# Experimental configs.
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
555
|
+
experimental_configs = config.pop('experimental', None)
|
556
|
+
|
557
|
+
# Handle the top-level config field
|
558
|
+
config_override = config.pop('config', None)
|
559
|
+
|
560
|
+
# Handle backward compatibility with experimental.config_overrides
|
561
|
+
# TODO: Remove experimental.config_overrides in 0.11.0.
|
562
|
+
if experimental_configs is not None:
|
563
|
+
exp_config_override = experimental_configs.pop(
|
559
564
|
'config_overrides', None)
|
565
|
+
if exp_config_override is not None:
|
566
|
+
logger.warning(
|
567
|
+
f'{colorama.Fore.YELLOW}`experimental.config_overrides` '
|
568
|
+
'field is deprecated in the task YAML. Use the `config` '
|
569
|
+
f'field to set config overrides.{colorama.Style.RESET_ALL}')
|
570
|
+
if config_override is not None:
|
571
|
+
logger.warning(
|
572
|
+
f'{colorama.Fore.YELLOW}Both top-level `config` and '
|
573
|
+
f'`experimental.config_overrides` are specified. '
|
574
|
+
f'Using top-level `config`.{colorama.Style.RESET_ALL}')
|
575
|
+
else:
|
576
|
+
config_override = exp_config_override
|
560
577
|
logger.debug('Overriding skypilot config with task-level config: '
|
561
|
-
f'{
|
562
|
-
|
563
|
-
|
578
|
+
f'{config_override}')
|
579
|
+
assert not experimental_configs, ('Invalid task args: '
|
580
|
+
f'{experimental_configs.keys()}')
|
581
|
+
|
582
|
+
# Store the final config override for use in resource setup
|
583
|
+
cluster_config_override = config_override
|
564
584
|
|
565
585
|
# Parse resources field.
|
566
586
|
resources_config = config.pop('resources', {})
|
sky/utils/schemas.py
CHANGED
@@ -473,6 +473,8 @@ def _filter_schema(schema: dict, keys_to_keep: List[Tuple[str, ...]]) -> dict:
|
|
473
473
|
|
474
474
|
|
475
475
|
def _experimental_task_schema() -> dict:
|
476
|
+
# TODO: experimental.config_overrides has been deprecated in favor of the
|
477
|
+
# top-level `config` field. Remove in v0.11.0.
|
476
478
|
config_override_schema = _filter_schema(
|
477
479
|
get_config_schema(), constants.OVERRIDEABLE_CONFIG_KEYS_IN_TASK)
|
478
480
|
return {
|
@@ -555,6 +557,9 @@ def get_task_schema():
|
|
555
557
|
'file_mounts_mapping': {
|
556
558
|
'type': 'object',
|
557
559
|
},
|
560
|
+
'config': _filter_schema(
|
561
|
+
get_config_schema(),
|
562
|
+
constants.OVERRIDEABLE_CONFIG_KEYS_IN_TASK),
|
558
563
|
**_experimental_task_schema(),
|
559
564
|
}
|
560
565
|
}
|
@@ -604,13 +609,6 @@ def get_cluster_schema():
|
|
604
609
|
|
605
610
|
|
606
611
|
_NETWORK_CONFIG_SCHEMA = {
|
607
|
-
'vpc_name': {
|
608
|
-
'oneOf': [{
|
609
|
-
'type': 'string',
|
610
|
-
}, {
|
611
|
-
'type': 'null',
|
612
|
-
}],
|
613
|
-
},
|
614
612
|
'use_internal_ips': {
|
615
613
|
'type': 'boolean',
|
616
614
|
},
|
@@ -767,6 +765,13 @@ def get_config_schema():
|
|
767
765
|
},
|
768
766
|
'security_group_name':
|
769
767
|
(_PRORPERTY_NAME_OR_CLUSTER_NAME_TO_PROPERTY),
|
768
|
+
'vpc_name': {
|
769
|
+
'oneOf': [{
|
770
|
+
'type': 'string',
|
771
|
+
}, {
|
772
|
+
'type': 'null',
|
773
|
+
}],
|
774
|
+
},
|
770
775
|
**_LABELS_SCHEMA,
|
771
776
|
**_NETWORK_CONFIG_SCHEMA,
|
772
777
|
},
|
@@ -805,6 +810,19 @@ def get_config_schema():
|
|
805
810
|
'enable_gvnic': {
|
806
811
|
'type': 'boolean'
|
807
812
|
},
|
813
|
+
'vpc_name': {
|
814
|
+
'oneOf': [
|
815
|
+
{
|
816
|
+
'type': 'string',
|
817
|
+
# vpc-name or project-id/vpc-name
|
818
|
+
# VPC name and Project ID have -, a-z, and 0-9.
|
819
|
+
'pattern': '^(?:[-a-z0-9]+/)?[-a-z0-9]+$'
|
820
|
+
},
|
821
|
+
{
|
822
|
+
'type': 'null',
|
823
|
+
}
|
824
|
+
],
|
825
|
+
},
|
808
826
|
**_LABELS_SCHEMA,
|
809
827
|
**_NETWORK_CONFIG_SCHEMA,
|
810
828
|
},
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: skypilot-nightly
|
3
|
-
Version: 1.0.0.
|
3
|
+
Version: 1.0.0.dev20250411
|
4
4
|
Summary: SkyPilot: An intercloud broker for the clouds
|
5
5
|
Author: SkyPilot Team
|
6
6
|
License: Apache 2.0
|
@@ -19,7 +19,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
19
|
Classifier: Topic :: System :: Distributed Computing
|
20
20
|
Description-Content-Type: text/markdown
|
21
21
|
License-File: LICENSE
|
22
|
-
Requires-Dist: wheel
|
22
|
+
Requires-Dist: wheel<0.46.0
|
23
23
|
Requires-Dist: cachetools
|
24
24
|
Requires-Dist: click>=7.0
|
25
25
|
Requires-Dist: colorama
|