skypilot-nightly 1.0.0.dev20250826__py3-none-any.whl → 1.0.0.dev20250828__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.
- sky/__init__.py +2 -2
- sky/admin_policy.py +11 -10
- sky/authentication.py +4 -10
- sky/backends/backend.py +3 -5
- sky/backends/backend_utils.py +41 -56
- sky/backends/cloud_vm_ray_backend.py +13 -24
- sky/backends/local_docker_backend.py +3 -8
- sky/client/cli/command.py +43 -10
- sky/client/common.py +41 -14
- sky/client/sdk.py +24 -9
- sky/client/sdk_async.py +6 -2
- sky/clouds/aws.py +1 -1
- sky/clouds/cloud.py +15 -0
- sky/clouds/kubernetes.py +27 -0
- sky/clouds/ssh.py +2 -3
- sky/core.py +1 -4
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/chunks/{webpack-6e76f636a048e145.js → webpack-6dae1cd599a34def.js} +1 -1
- 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/pools/[pool].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/volumes.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/global_user_state.py +127 -23
- sky/jobs/client/sdk.py +5 -2
- sky/jobs/recovery_strategy.py +9 -4
- sky/logs/agent.py +2 -2
- sky/logs/aws.py +6 -3
- sky/provision/do/utils.py +2 -1
- sky/provision/kubernetes/config.py +2 -8
- sky/provision/kubernetes/instance.py +58 -8
- sky/provision/kubernetes/network_utils.py +3 -4
- sky/provision/kubernetes/utils.py +8 -7
- sky/provision/nebius/utils.py +51 -9
- sky/provision/vsphere/vsphere_utils.py +2 -8
- sky/schemas/api/responses.py +7 -0
- sky/serve/client/impl.py +5 -4
- sky/serve/replica_managers.py +4 -3
- sky/serve/serve_utils.py +4 -4
- sky/serve/server/impl.py +3 -2
- sky/serve/service_spec.py +2 -8
- sky/server/auth/authn.py +4 -0
- sky/server/auth/oauth2_proxy.py +10 -4
- sky/server/common.py +10 -3
- sky/server/daemons.py +10 -5
- sky/server/requests/executor.py +6 -1
- sky/server/requests/requests.py +21 -0
- sky/server/server.py +34 -33
- sky/server/uvicorn.py +33 -0
- sky/setup_files/dependencies.py +1 -0
- sky/sky_logging.py +4 -1
- sky/skylet/events.py +4 -5
- sky/skypilot_config.py +14 -12
- sky/ssh_node_pools/core.py +3 -1
- sky/task.py +4 -10
- sky/templates/nebius-ray.yml.j2 +4 -8
- sky/usage/usage_lib.py +3 -2
- sky/users/server.py +6 -6
- sky/utils/common_utils.py +0 -71
- sky/utils/controller_utils.py +4 -3
- sky/utils/dag_utils.py +4 -4
- sky/utils/kubernetes/config_map_utils.py +3 -3
- sky/utils/schemas.py +3 -0
- sky/utils/yaml_utils.py +102 -0
- sky/volumes/volume.py +8 -3
- {skypilot_nightly-1.0.0.dev20250826.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/METADATA +2 -1
- {skypilot_nightly-1.0.0.dev20250826.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/RECORD +83 -82
- /sky/dashboard/out/_next/static/{TPMkEeuj85tHTmIW7Gu3S → 9DW6d9jaP2kZt0NcgIfFa}/_buildManifest.js +0 -0
- /sky/dashboard/out/_next/static/{TPMkEeuj85tHTmIW7Gu3S → 9DW6d9jaP2kZt0NcgIfFa}/_ssgManifest.js +0 -0
- {skypilot_nightly-1.0.0.dev20250826.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250826.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250826.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250826.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/top_level.txt +0 -0
sky/utils/controller_utils.py
CHANGED
|
@@ -38,6 +38,7 @@ from sky.utils import env_options
|
|
|
38
38
|
from sky.utils import registry
|
|
39
39
|
from sky.utils import rich_utils
|
|
40
40
|
from sky.utils import ux_utils
|
|
41
|
+
from sky.utils import yaml_utils
|
|
41
42
|
|
|
42
43
|
if typing.TYPE_CHECKING:
|
|
43
44
|
import psutil
|
|
@@ -497,7 +498,7 @@ def shared_controller_vars_to_fill(
|
|
|
497
498
|
with tempfile.NamedTemporaryFile(
|
|
498
499
|
delete=False,
|
|
499
500
|
suffix=_LOCAL_SKYPILOT_CONFIG_PATH_SUFFIX) as temp_file:
|
|
500
|
-
|
|
501
|
+
yaml_utils.dump_yaml(temp_file.name, dict(**local_user_config))
|
|
501
502
|
local_user_config_path = temp_file.name
|
|
502
503
|
|
|
503
504
|
vars_to_fill: Dict[str, Any] = {
|
|
@@ -786,9 +787,9 @@ def replace_skypilot_config_path_in_file_mounts(
|
|
|
786
787
|
continue
|
|
787
788
|
if local_path.endswith(_LOCAL_SKYPILOT_CONFIG_PATH_SUFFIX):
|
|
788
789
|
with tempfile.NamedTemporaryFile('w', delete=False) as f:
|
|
789
|
-
user_config =
|
|
790
|
+
user_config = yaml_utils.read_yaml(local_path)
|
|
790
791
|
config = _setup_proxy_command_on_controller(cloud, user_config)
|
|
791
|
-
|
|
792
|
+
yaml_utils.dump_yaml(f.name, dict(**config))
|
|
792
793
|
file_mounts[remote_path] = f.name
|
|
793
794
|
replaced = True
|
|
794
795
|
if replaced:
|
sky/utils/dag_utils.py
CHANGED
|
@@ -6,9 +6,9 @@ from sky import dag as dag_lib
|
|
|
6
6
|
from sky import sky_logging
|
|
7
7
|
from sky import task as task_lib
|
|
8
8
|
from sky.utils import cluster_utils
|
|
9
|
-
from sky.utils import common_utils
|
|
10
9
|
from sky.utils import registry
|
|
11
10
|
from sky.utils import ux_utils
|
|
11
|
+
from sky.utils import yaml_utils
|
|
12
12
|
|
|
13
13
|
logger = sky_logging.init_logger(__name__)
|
|
14
14
|
|
|
@@ -117,7 +117,7 @@ def load_chain_dag_from_yaml(
|
|
|
117
117
|
A chain Dag with 1 or more tasks (an empty entrypoint would create a
|
|
118
118
|
trivial task).
|
|
119
119
|
"""
|
|
120
|
-
configs =
|
|
120
|
+
configs = yaml_utils.read_yaml_all(path)
|
|
121
121
|
return _load_chain_dag(configs, env_overrides, secret_overrides)
|
|
122
122
|
|
|
123
123
|
|
|
@@ -143,7 +143,7 @@ def load_chain_dag_from_yaml_str(
|
|
|
143
143
|
A chain Dag with 1 or more tasks (an empty entrypoint would create a
|
|
144
144
|
trivial task).
|
|
145
145
|
"""
|
|
146
|
-
configs =
|
|
146
|
+
configs = yaml_utils.read_yaml_all_str(yaml_str)
|
|
147
147
|
return _load_chain_dag(configs, env_overrides, secrets_overrides)
|
|
148
148
|
|
|
149
149
|
|
|
@@ -164,7 +164,7 @@ def dump_chain_dag_to_yaml_str(dag: dag_lib.Dag,
|
|
|
164
164
|
configs.append(
|
|
165
165
|
task.to_yaml_config(
|
|
166
166
|
use_user_specified_yaml=use_user_specified_yaml))
|
|
167
|
-
return
|
|
167
|
+
return yaml_utils.dump_yaml_str(configs)
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
def dump_chain_dag_to_yaml(dag: dag_lib.Dag, path: str) -> None:
|
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
from sky import sky_logging
|
|
5
5
|
from sky import skypilot_config
|
|
6
6
|
from sky.adaptors import kubernetes
|
|
7
|
-
from sky.utils import
|
|
7
|
+
from sky.utils import yaml_utils
|
|
8
8
|
|
|
9
9
|
logger = sky_logging.init_logger(__name__)
|
|
10
10
|
|
|
@@ -69,7 +69,7 @@ def initialize_configmap_sync_on_startup(config_file_path: str) -> None:
|
|
|
69
69
|
|
|
70
70
|
current_config = skypilot_config.parse_and_validate_config_file(
|
|
71
71
|
config_file_path)
|
|
72
|
-
config_yaml =
|
|
72
|
+
config_yaml = yaml_utils.dump_yaml_str(dict(current_config))
|
|
73
73
|
|
|
74
74
|
configmap_body = {
|
|
75
75
|
'apiVersion': 'v1',
|
|
@@ -111,7 +111,7 @@ def patch_configmap_with_config(config, config_file_path: str) -> None:
|
|
|
111
111
|
try:
|
|
112
112
|
namespace = _get_kubernetes_namespace()
|
|
113
113
|
configmap_name = _get_configmap_name()
|
|
114
|
-
config_yaml =
|
|
114
|
+
config_yaml = yaml_utils.dump_yaml_str(dict(config))
|
|
115
115
|
patch_body = {'data': {'config.yaml': config_yaml}}
|
|
116
116
|
|
|
117
117
|
try:
|
sky/utils/schemas.py
CHANGED
sky/utils/yaml_utils.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""YAML utilities."""
|
|
2
|
+
import io
|
|
3
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union
|
|
4
|
+
|
|
5
|
+
from sky.adaptors import common
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
import yaml
|
|
9
|
+
else:
|
|
10
|
+
yaml = common.LazyImport('yaml')
|
|
11
|
+
|
|
12
|
+
_c_extension_unavailable = False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def safe_load(stream) -> Any:
|
|
16
|
+
global _c_extension_unavailable
|
|
17
|
+
if _c_extension_unavailable:
|
|
18
|
+
return yaml.load(stream, Loader=yaml.SafeLoader)
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
return yaml.load(stream, Loader=yaml.CSafeLoader)
|
|
22
|
+
except AttributeError:
|
|
23
|
+
_c_extension_unavailable = True
|
|
24
|
+
return yaml.load(stream, Loader=yaml.SafeLoader)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def safe_load_all(stream) -> Any:
|
|
28
|
+
global _c_extension_unavailable
|
|
29
|
+
if _c_extension_unavailable:
|
|
30
|
+
return yaml.load_all(stream, Loader=yaml.SafeLoader)
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
return yaml.load_all(stream, Loader=yaml.CSafeLoader)
|
|
34
|
+
except AttributeError:
|
|
35
|
+
_c_extension_unavailable = True
|
|
36
|
+
return yaml.load_all(stream, Loader=yaml.SafeLoader)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def read_yaml(path: Optional[str]) -> Dict[str, Any]:
|
|
40
|
+
if path is None:
|
|
41
|
+
raise ValueError('Attempted to read a None YAML.')
|
|
42
|
+
with open(path, 'r', encoding='utf-8') as f:
|
|
43
|
+
config = safe_load(f)
|
|
44
|
+
return config
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def read_yaml_all_str(yaml_str: str) -> List[Dict[str, Any]]:
|
|
48
|
+
stream = io.StringIO(yaml_str)
|
|
49
|
+
config = safe_load_all(stream)
|
|
50
|
+
configs = list(config)
|
|
51
|
+
if not configs:
|
|
52
|
+
# Empty YAML file.
|
|
53
|
+
return [{}]
|
|
54
|
+
return configs
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def read_yaml_all(path: str) -> List[Dict[str, Any]]:
|
|
58
|
+
with open(path, 'r', encoding='utf-8') as f:
|
|
59
|
+
return read_yaml_all_str(f.read())
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def dump_yaml(path: str,
|
|
63
|
+
config: Union[List[Dict[str, Any]], Dict[str, Any]],
|
|
64
|
+
blank: bool = False) -> None:
|
|
65
|
+
"""Dumps a YAML file.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
path: the path to the YAML file.
|
|
69
|
+
config: the configuration to dump.
|
|
70
|
+
"""
|
|
71
|
+
with open(path, 'w', encoding='utf-8') as f:
|
|
72
|
+
contents = dump_yaml_str(config)
|
|
73
|
+
if blank and isinstance(config, dict) and len(config) == 0:
|
|
74
|
+
# when dumping to yaml, an empty dict will go in as {}.
|
|
75
|
+
contents = ''
|
|
76
|
+
f.write(contents)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def dump_yaml_str(config: Union[List[Dict[str, Any]], Dict[str, Any]]) -> str:
|
|
80
|
+
"""Dumps a YAML string.
|
|
81
|
+
Args:
|
|
82
|
+
config: the configuration to dump.
|
|
83
|
+
Returns:
|
|
84
|
+
The YAML string.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
# https://github.com/yaml/pyyaml/issues/127
|
|
88
|
+
class LineBreakDumper(yaml.SafeDumper):
|
|
89
|
+
|
|
90
|
+
def write_line_break(self, data=None):
|
|
91
|
+
super().write_line_break(data)
|
|
92
|
+
if len(self.indents) == 1:
|
|
93
|
+
super().write_line_break()
|
|
94
|
+
|
|
95
|
+
if isinstance(config, list):
|
|
96
|
+
dump_func = yaml.dump_all # type: ignore
|
|
97
|
+
else:
|
|
98
|
+
dump_func = yaml.dump # type: ignore
|
|
99
|
+
return dump_func(config,
|
|
100
|
+
Dumper=LineBreakDumper,
|
|
101
|
+
sort_keys=False,
|
|
102
|
+
default_flow_style=False)
|
sky/volumes/volume.py
CHANGED
|
@@ -125,14 +125,19 @@ class Volume:
|
|
|
125
125
|
|
|
126
126
|
def _validate_config(self) -> None:
|
|
127
127
|
"""Validate the volume config."""
|
|
128
|
+
assert self.cloud is not None, 'Cloud must be specified'
|
|
129
|
+
cloud_obj = registry.CLOUD_REGISTRY.from_str(self.cloud)
|
|
130
|
+
assert cloud_obj is not None
|
|
131
|
+
|
|
132
|
+
valid, err_msg = cloud_obj.is_volume_name_valid(self.name)
|
|
133
|
+
if not valid:
|
|
134
|
+
raise ValueError(f'Invalid volume name: {err_msg}')
|
|
135
|
+
|
|
128
136
|
if not self.resource_name and not self.size:
|
|
129
137
|
raise ValueError('Size is required for new volumes. '
|
|
130
138
|
'Please specify the size in the YAML file or '
|
|
131
139
|
'use the --size flag.')
|
|
132
140
|
if self.labels:
|
|
133
|
-
assert self.cloud is not None, 'Cloud must be specified'
|
|
134
|
-
cloud_obj = registry.CLOUD_REGISTRY.from_str(self.cloud)
|
|
135
|
-
assert cloud_obj is not None
|
|
136
141
|
for key, value in self.labels.items():
|
|
137
142
|
valid, err_msg = cloud_obj.is_label_valid(key, value)
|
|
138
143
|
if not valid:
|
|
@@ -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.dev20250828
|
|
4
4
|
Summary: SkyPilot: Run AI on Any Infra — Unified, Faster, Cheaper.
|
|
5
5
|
Author: SkyPilot Team
|
|
6
6
|
License: Apache 2.0
|
|
@@ -53,6 +53,7 @@ Requires-Dist: casbin
|
|
|
53
53
|
Requires-Dist: sqlalchemy_adapter
|
|
54
54
|
Requires-Dist: prometheus_client>=0.8.0
|
|
55
55
|
Requires-Dist: passlib
|
|
56
|
+
Requires-Dist: bcrypt
|
|
56
57
|
Requires-Dist: pyjwt
|
|
57
58
|
Requires-Dist: gitpython
|
|
58
59
|
Requires-Dist: types-paramiko
|