skypilot-nightly 1.0.0.dev20250621__py3-none-any.whl → 1.0.0.dev20250624__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/admin_policy.py +16 -5
- sky/backends/__init__.py +2 -1
- sky/backends/backend_utils.py +12 -0
- sky/backends/cloud_vm_ray_backend.py +36 -13
- sky/client/cli/command.py +42 -21
- sky/client/sdk.py +12 -6
- sky/clouds/kubernetes.py +1 -0
- sky/core.py +88 -15
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/37-4650f214e2119168.js +6 -0
- sky/dashboard/out/_next/static/chunks/42.2273cc2415291ceb.js +6 -0
- sky/dashboard/out/_next/static/chunks/470-1494c899266cf5c9.js +1 -0
- sky/dashboard/out/_next/static/chunks/{513.211357a2914a34b2.js → 513.309df9e18a9ff005.js} +1 -1
- sky/dashboard/out/_next/static/chunks/856-bfddc18e16f3873c.js +1 -0
- sky/dashboard/out/_next/static/chunks/938-ce7991c156584b06.js +1 -0
- sky/dashboard/out/_next/static/chunks/969-d3a0b53f728d280a.js +1 -0
- sky/dashboard/out/_next/static/chunks/989-db34c16ad7ea6155.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/{_app-c416e87d5c2715cf.js → _app-ce31493da9747ef4.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-4e065c812a52460b.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-520ec1ab65e2f2a4.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/clusters-7e9736af1c6345a6.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/config-e4f473661889e7cd.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-00fd23b9577492ca.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/infra-8a4bf7370d4d9bb7.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs/{[job]-cf490d1fa38f3740.js → [job]-171c27f4ca94861c.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs-55e5bcb16d563231.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/users-c9f4d785cdaa52d8.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-c4ff1ec05e2f3daf.js → [name]-ecc5a7003776cfa7.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-f00cba35691483b1.js +1 -0
- sky/dashboard/out/_next/static/chunks/webpack-c85998e6a5722f21.js +1 -0
- sky/dashboard/out/_next/static/css/6ab927686b492a4a.css +3 -0
- sky/dashboard/out/_next/static/zsALxITkbP8J8NVwSDwMo/_buildManifest.js +1 -0
- sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
- sky/dashboard/out/clusters/[cluster].html +1 -1
- sky/dashboard/out/clusters.html +1 -1
- sky/dashboard/out/config.html +1 -1
- sky/dashboard/out/index.html +1 -1
- sky/dashboard/out/infra/[context].html +1 -1
- sky/dashboard/out/infra.html +1 -1
- sky/dashboard/out/jobs/[job].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/exceptions.py +11 -0
- sky/global_user_state.py +134 -20
- sky/jobs/client/sdk.py +0 -1
- sky/jobs/controller.py +5 -1
- sky/jobs/scheduler.py +4 -3
- sky/jobs/server/core.py +117 -51
- sky/jobs/state.py +15 -0
- sky/jobs/utils.py +114 -8
- sky/resources.py +1 -1
- sky/server/requests/payloads.py +6 -3
- sky/server/requests/requests.py +24 -1
- sky/server/server.py +4 -3
- sky/skylet/constants.py +5 -11
- sky/task.py +1 -26
- sky/templates/jobs-controller.yaml.j2 +12 -1
- sky/templates/kubernetes-ray.yml.j2 +1 -1
- sky/utils/admin_policy_utils.py +5 -1
- sky/utils/cli_utils/status_utils.py +25 -17
- sky/utils/command_runner.py +118 -12
- sky/utils/command_runner.pyi +57 -0
- sky/utils/common_utils.py +9 -1
- sky/utils/controller_utils.py +1 -2
- sky/utils/schemas.py +34 -35
- {skypilot_nightly-1.0.0.dev20250621.dist-info → skypilot_nightly-1.0.0.dev20250624.dist-info}/METADATA +1 -1
- {skypilot_nightly-1.0.0.dev20250621.dist-info → skypilot_nightly-1.0.0.dev20250624.dist-info}/RECORD +78 -77
- sky/dashboard/out/_next/static/PZWXta2b3IpViuIKI97hg/_buildManifest.js +0 -1
- sky/dashboard/out/_next/static/chunks/37-3a4d77ad62932eaf.js +0 -6
- sky/dashboard/out/_next/static/chunks/42.d39e24467181b06b.js +0 -6
- sky/dashboard/out/_next/static/chunks/470-4d1a5dbe58a8a2b9.js +0 -1
- sky/dashboard/out/_next/static/chunks/856-c2c39c0912285e54.js +0 -1
- sky/dashboard/out/_next/static/chunks/938-1493ac755eadeb35.js +0 -1
- sky/dashboard/out/_next/static/chunks/969-20d54a9d998dc102.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-89216c616dbaa9c5.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-36bc0962129f72df.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/clusters-82a651dbad53ec6e.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/config-497a35a7ed49734a.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/infra/[context]-d2910be98e9227cb.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/infra-780860bcc1103945.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/jobs-336ab80e270ce2ce.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/users-928edf039219e47b.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/workspaces-82e6601baa5dd280.js +0 -1
- sky/dashboard/out/_next/static/chunks/webpack-0263b00d6a10e64a.js +0 -1
- sky/dashboard/out/_next/static/css/6c12ecc3bd2239b6.css +0 -3
- /sky/dashboard/out/_next/static/chunks/{843-b3040e493f6e7947.js → 843-bde186946d353355.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{973-db3c97c2bfbceb65.js → 973-56412c7976b4655b.js} +0 -0
- /sky/dashboard/out/_next/static/{PZWXta2b3IpViuIKI97hg → zsALxITkbP8J8NVwSDwMo}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250621.dist-info → skypilot_nightly-1.0.0.dev20250624.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250621.dist-info → skypilot_nightly-1.0.0.dev20250624.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250621.dist-info → skypilot_nightly-1.0.0.dev20250624.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250621.dist-info → skypilot_nightly-1.0.0.dev20250624.dist-info}/top_level.txt +0 -0
sky/utils/command_runner.py
CHANGED
@@ -4,6 +4,7 @@ import hashlib
|
|
4
4
|
import os
|
5
5
|
import pathlib
|
6
6
|
import shlex
|
7
|
+
import sys
|
7
8
|
import time
|
8
9
|
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type, Union
|
9
10
|
|
@@ -231,9 +232,9 @@ class CommandRunner:
|
|
231
232
|
self,
|
232
233
|
source: str,
|
233
234
|
target: str,
|
234
|
-
node_destination: str,
|
235
|
+
node_destination: Optional[str],
|
235
236
|
up: bool,
|
236
|
-
rsh_option: str,
|
237
|
+
rsh_option: Optional[str],
|
237
238
|
# Advanced options.
|
238
239
|
log_path: str = os.devnull,
|
239
240
|
stream_logs: bool = True,
|
@@ -283,28 +284,43 @@ class CommandRunner:
|
|
283
284
|
RSYNC_EXCLUDE_OPTION.format(
|
284
285
|
shlex.quote(str(resolved_source / GIT_EXCLUDE))))
|
285
286
|
|
286
|
-
|
287
|
+
if rsh_option is not None:
|
288
|
+
rsync_command.append(f'-e {shlex.quote(rsh_option)}')
|
289
|
+
maybe_dest_prefix = ('' if node_destination is None else
|
290
|
+
f'{node_destination}:')
|
287
291
|
|
288
292
|
if up:
|
289
293
|
resolved_target = target
|
290
|
-
if
|
291
|
-
|
292
|
-
resolved_target =
|
294
|
+
if node_destination is None:
|
295
|
+
# Is a local rsync. Directly resolve the target.
|
296
|
+
resolved_target = str(
|
297
|
+
pathlib.Path(target).expanduser().resolve())
|
298
|
+
else:
|
299
|
+
if target.startswith('~'):
|
300
|
+
remote_home_dir = _get_remote_home_dir_with_retry()
|
301
|
+
resolved_target = target.replace('~', remote_home_dir)
|
293
302
|
full_source_str = str(resolved_source)
|
294
303
|
if resolved_source.is_dir():
|
295
304
|
full_source_str = os.path.join(full_source_str, '')
|
296
305
|
rsync_command.extend([
|
297
306
|
f'{full_source_str!r}',
|
298
|
-
f'{
|
307
|
+
f'{maybe_dest_prefix}{resolved_target!r}',
|
299
308
|
])
|
300
309
|
else:
|
301
310
|
resolved_source = source
|
302
|
-
if
|
303
|
-
|
304
|
-
|
311
|
+
if node_destination is None:
|
312
|
+
resolved_target = str(
|
313
|
+
pathlib.Path(target).expanduser().resolve())
|
314
|
+
resolved_source = str(
|
315
|
+
pathlib.Path(source).expanduser().resolve())
|
316
|
+
else:
|
317
|
+
resolved_target = os.path.expanduser(target)
|
318
|
+
if source.startswith('~'):
|
319
|
+
remote_home_dir = _get_remote_home_dir_with_retry()
|
320
|
+
resolved_source = source.replace('~', remote_home_dir)
|
305
321
|
rsync_command.extend([
|
306
|
-
f'{
|
307
|
-
f'{
|
322
|
+
f'{maybe_dest_prefix}{resolved_source!r}',
|
323
|
+
f'{resolved_target!r}',
|
308
324
|
])
|
309
325
|
command = ' '.join(rsync_command)
|
310
326
|
logger.debug(f'Running rsync command: {command}')
|
@@ -964,3 +980,93 @@ class KubernetesCommandRunner(CommandRunner):
|
|
964
980
|
# /~/xx, so we need to replace ~ with the remote home directory. We
|
965
981
|
# only need to do this when ~ is at the beginning of the path.
|
966
982
|
get_remote_home_dir=get_remote_home_dir)
|
983
|
+
|
984
|
+
|
985
|
+
class LocalProcessCommandRunner(CommandRunner):
|
986
|
+
"""Runner for local process commands."""
|
987
|
+
|
988
|
+
def __init__(self):
|
989
|
+
super().__init__('local')
|
990
|
+
|
991
|
+
@timeline.event
|
992
|
+
@context_utils.cancellation_guard
|
993
|
+
def run(
|
994
|
+
self,
|
995
|
+
cmd: Union[str, List[str]],
|
996
|
+
*,
|
997
|
+
require_outputs: bool = False,
|
998
|
+
port_forward: Optional[List[Tuple[int, int]]] = None,
|
999
|
+
# Advanced options.
|
1000
|
+
log_path: str = os.devnull,
|
1001
|
+
# If False, do not redirect stdout/stderr to optimize performance.
|
1002
|
+
process_stream: bool = True,
|
1003
|
+
stream_logs: bool = True,
|
1004
|
+
ssh_mode: SshMode = SshMode.NON_INTERACTIVE,
|
1005
|
+
separate_stderr: bool = False,
|
1006
|
+
connect_timeout: Optional[int] = None,
|
1007
|
+
source_bashrc: bool = False,
|
1008
|
+
skip_num_lines: int = 0,
|
1009
|
+
**kwargs) -> Union[int, Tuple[int, str, str]]:
|
1010
|
+
"""Use subprocess to run the command."""
|
1011
|
+
del port_forward, ssh_mode, connect_timeout # Unused.
|
1012
|
+
|
1013
|
+
command_str = self._get_command_to_run(cmd,
|
1014
|
+
process_stream,
|
1015
|
+
separate_stderr,
|
1016
|
+
skip_num_lines=skip_num_lines,
|
1017
|
+
source_bashrc=source_bashrc)
|
1018
|
+
|
1019
|
+
log_dir = os.path.expanduser(os.path.dirname(log_path))
|
1020
|
+
os.makedirs(log_dir, exist_ok=True)
|
1021
|
+
|
1022
|
+
executable = None
|
1023
|
+
command = [command_str]
|
1024
|
+
if not process_stream:
|
1025
|
+
if stream_logs:
|
1026
|
+
command += [
|
1027
|
+
f'| tee {log_path}',
|
1028
|
+
# This also requires the executor to be '/bin/bash' instead
|
1029
|
+
# of the default '/bin/sh'.
|
1030
|
+
'; exit ${PIPESTATUS[0]}'
|
1031
|
+
]
|
1032
|
+
else:
|
1033
|
+
command += [f'> {log_path}']
|
1034
|
+
executable = '/bin/bash'
|
1035
|
+
command_str = ' '.join(command)
|
1036
|
+
# For local process, the API server might not have this python path
|
1037
|
+
# setup. But this command runner should only be triggered from the API
|
1038
|
+
# server (in controller consolidation mode), so we can safely replace
|
1039
|
+
# the python path with the executable of the API server.
|
1040
|
+
command_str = command_str.replace(constants.SKY_PYTHON_CMD,
|
1041
|
+
sys.executable)
|
1042
|
+
logger.debug(f'Running command locally: {command_str}')
|
1043
|
+
return log_lib.run_with_log(command_str,
|
1044
|
+
log_path,
|
1045
|
+
require_outputs=require_outputs,
|
1046
|
+
stream_logs=stream_logs,
|
1047
|
+
process_stream=process_stream,
|
1048
|
+
shell=True,
|
1049
|
+
executable=executable,
|
1050
|
+
**kwargs)
|
1051
|
+
|
1052
|
+
@timeline.event
|
1053
|
+
def rsync(
|
1054
|
+
self,
|
1055
|
+
source: str,
|
1056
|
+
target: str,
|
1057
|
+
*,
|
1058
|
+
up: bool,
|
1059
|
+
# Advanced options.
|
1060
|
+
log_path: str = os.devnull,
|
1061
|
+
stream_logs: bool = True,
|
1062
|
+
max_retry: int = 1,
|
1063
|
+
) -> None:
|
1064
|
+
"""Use rsync to sync the source to the target."""
|
1065
|
+
self._rsync(source,
|
1066
|
+
target,
|
1067
|
+
node_destination=None,
|
1068
|
+
up=up,
|
1069
|
+
rsh_option=None,
|
1070
|
+
log_path=log_path,
|
1071
|
+
stream_logs=stream_logs,
|
1072
|
+
max_retry=max_retry)
|
sky/utils/command_runner.pyi
CHANGED
@@ -271,3 +271,60 @@ class KubernetesCommandRunner(CommandRunner):
|
|
271
271
|
stream_logs: bool = ...,
|
272
272
|
max_retry: int = ...) -> None:
|
273
273
|
...
|
274
|
+
|
275
|
+
|
276
|
+
class LocalProcessCommandRunner(CommandRunner):
|
277
|
+
|
278
|
+
def __init__(self) -> None:
|
279
|
+
...
|
280
|
+
|
281
|
+
@typing.overload
|
282
|
+
def run(self,
|
283
|
+
cmd: Union[str, List[str]],
|
284
|
+
*,
|
285
|
+
port_forward: Optional[List[int]] = ...,
|
286
|
+
require_outputs: Literal[False] = ...,
|
287
|
+
log_path: str = ...,
|
288
|
+
process_stream: bool = ...,
|
289
|
+
stream_logs: bool = ...,
|
290
|
+
ssh_mode: SshMode = ...,
|
291
|
+
separate_stderr: bool = ...,
|
292
|
+
connect_timeout: Optional[int] = ...,
|
293
|
+
source_bashrc: bool = ...,
|
294
|
+
skip_lines: int = ...,
|
295
|
+
**kwargs) -> int:
|
296
|
+
...
|
297
|
+
|
298
|
+
@typing.overload
|
299
|
+
def run(self,
|
300
|
+
cmd: Union[str, List[str]],
|
301
|
+
*,
|
302
|
+
port_forward: Optional[List[int]] = ...,
|
303
|
+
require_outputs: Literal[True],
|
304
|
+
log_path: str = ...,
|
305
|
+
process_stream: bool = ...,
|
306
|
+
stream_logs: bool = ...,
|
307
|
+
ssh_mode: SshMode = ...,
|
308
|
+
separate_stderr: bool = ...,
|
309
|
+
connect_timeout: Optional[int] = ...,
|
310
|
+
source_bashrc: bool = ...,
|
311
|
+
skip_lines: int = ...,
|
312
|
+
**kwargs) -> Tuple[int, str, str]:
|
313
|
+
...
|
314
|
+
|
315
|
+
@typing.overload
|
316
|
+
def run(self,
|
317
|
+
cmd: Union[str, List[str]],
|
318
|
+
*,
|
319
|
+
port_forward: Optional[List[int]] = ...,
|
320
|
+
require_outputs: bool = ...,
|
321
|
+
log_path: str = ...,
|
322
|
+
process_stream: bool = ...,
|
323
|
+
stream_logs: bool = ...,
|
324
|
+
ssh_mode: SshMode = ...,
|
325
|
+
separate_stderr: bool = ...,
|
326
|
+
connect_timeout: Optional[int] = ...,
|
327
|
+
source_bashrc: bool = ...,
|
328
|
+
skip_lines: int = ...,
|
329
|
+
**kwargs) -> Union[Tuple[int, str, str], int]:
|
330
|
+
...
|
sky/utils/common_utils.py
CHANGED
@@ -26,6 +26,7 @@ from sky.adaptors import common as adaptors_common
|
|
26
26
|
from sky.skylet import constants
|
27
27
|
from sky.usage import constants as usage_constants
|
28
28
|
from sky.utils import annotations
|
29
|
+
from sky.utils import common_utils
|
29
30
|
from sky.utils import ux_utils
|
30
31
|
from sky.utils import validator
|
31
32
|
|
@@ -298,6 +299,13 @@ def get_current_user() -> 'models.User':
|
|
298
299
|
return models.User.get_current_user()
|
299
300
|
|
300
301
|
|
302
|
+
def get_current_user_name() -> str:
|
303
|
+
"""Returns the current user name."""
|
304
|
+
name = common_utils.get_current_user().name
|
305
|
+
assert name is not None
|
306
|
+
return name
|
307
|
+
|
308
|
+
|
301
309
|
def set_current_user(user: 'models.User'):
|
302
310
|
"""Sets the current user."""
|
303
311
|
global _current_user
|
@@ -754,7 +762,7 @@ def get_cleaned_username(username: str = '') -> str:
|
|
754
762
|
Returns:
|
755
763
|
A cleaned username.
|
756
764
|
"""
|
757
|
-
username = username or
|
765
|
+
username = username or common_utils.get_current_user_name()
|
758
766
|
username = username.lower()
|
759
767
|
username = re.sub(r'[^a-z0-9-_]', '', username)
|
760
768
|
username = re.sub(r'^[0-9-]+', '', username)
|
sky/utils/controller_utils.py
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
import copy
|
3
3
|
import dataclasses
|
4
4
|
import enum
|
5
|
-
import getpass
|
6
5
|
import os
|
7
6
|
import tempfile
|
8
7
|
import typing
|
@@ -498,7 +497,7 @@ def shared_controller_vars_to_fill(
|
|
498
497
|
env_vars.update({
|
499
498
|
# Should not use $USER here, as that env var can be empty when
|
500
499
|
# running in a container.
|
501
|
-
constants.USER_ENV_VAR:
|
500
|
+
constants.USER_ENV_VAR: common_utils.get_current_user_name(),
|
502
501
|
constants.USER_ID_ENV_VAR: common_utils.get_user_hash(),
|
503
502
|
# Skip cloud identity check to avoid the overhead.
|
504
503
|
env_options.Options.SKIP_CLOUD_IDENTITY_CHECK.env_key: '1',
|
sky/utils/schemas.py
CHANGED
@@ -672,18 +672,6 @@ def get_task_schema():
|
|
672
672
|
'service': {
|
673
673
|
'type': 'object',
|
674
674
|
},
|
675
|
-
'job': {
|
676
|
-
'type': 'object',
|
677
|
-
'required': [],
|
678
|
-
'additionalProperties': False,
|
679
|
-
'properties': {
|
680
|
-
'priority': {
|
681
|
-
'type': 'integer',
|
682
|
-
'minimum': 0,
|
683
|
-
'maximum': 1000,
|
684
|
-
},
|
685
|
-
},
|
686
|
-
},
|
687
675
|
'setup': {
|
688
676
|
'type': 'string',
|
689
677
|
},
|
@@ -899,30 +887,41 @@ def get_config_schema():
|
|
899
887
|
if k != '$schema'
|
900
888
|
}
|
901
889
|
resources_schema['properties'].pop('ports')
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
'
|
909
|
-
'required': [],
|
910
|
-
'additionalProperties': False,
|
911
|
-
'properties': {
|
912
|
-
'resources': resources_schema,
|
913
|
-
'high_availability': {
|
914
|
-
'type': 'boolean',
|
915
|
-
},
|
916
|
-
'autostop': _AUTOSTOP_SCHEMA,
|
917
|
-
}
|
890
|
+
|
891
|
+
def _get_controller_schema(add_consolidation_mode: bool = False):
|
892
|
+
controller_properties = {
|
893
|
+
'resources': resources_schema,
|
894
|
+
'high_availability': {
|
895
|
+
'type': 'boolean',
|
896
|
+
'default': False,
|
918
897
|
},
|
919
|
-
'
|
920
|
-
|
921
|
-
|
922
|
-
|
898
|
+
'autostop': _AUTOSTOP_SCHEMA,
|
899
|
+
}
|
900
|
+
if add_consolidation_mode:
|
901
|
+
controller_properties['consolidation_mode'] = {
|
902
|
+
'type': 'boolean',
|
903
|
+
'default': False,
|
904
|
+
}
|
905
|
+
|
906
|
+
return {
|
907
|
+
'type': 'object',
|
908
|
+
'required': [],
|
909
|
+
'additionalProperties': False,
|
910
|
+
'properties': {
|
911
|
+
'controller': {
|
912
|
+
'type': 'object',
|
913
|
+
'required': [],
|
914
|
+
'additionalProperties': False,
|
915
|
+
'properties': controller_properties,
|
916
|
+
},
|
917
|
+
'bucket': {
|
918
|
+
'type': 'string',
|
919
|
+
'pattern': '^(https|s3|gs|r2|cos)://.+',
|
920
|
+
'required': [],
|
921
|
+
}
|
923
922
|
}
|
924
923
|
}
|
925
|
-
|
924
|
+
|
926
925
|
cloud_configs = {
|
927
926
|
'aws': {
|
928
927
|
'type': 'object',
|
@@ -1440,8 +1439,8 @@ def get_config_schema():
|
|
1440
1439
|
'db': {
|
1441
1440
|
'type': 'string',
|
1442
1441
|
},
|
1443
|
-
'jobs':
|
1444
|
-
'serve':
|
1442
|
+
'jobs': _get_controller_schema(add_consolidation_mode=True),
|
1443
|
+
'serve': _get_controller_schema(add_consolidation_mode=False),
|
1445
1444
|
'allowed_clouds': allowed_clouds,
|
1446
1445
|
'admin_policy': admin_policy_schema,
|
1447
1446
|
'docker': docker_configs,
|