anyscale 0.26.52__py3-none-any.whl → 0.26.54__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.
- anyscale/_private/anyscale_client/anyscale_client.py +26 -26
- anyscale/_private/anyscale_client/common.py +5 -5
- anyscale/_private/anyscale_client/fake_anyscale_client.py +6 -6
- anyscale/_private/docgen/__main__.py +8 -8
- anyscale/_private/docgen/generator.py +48 -10
- anyscale/_private/docgen/models.md +2 -2
- anyscale/_private/sdk/__init__.py +124 -1
- anyscale/_private/workload/workload_config.py +4 -6
- anyscale/_private/workload/workload_sdk.py +9 -11
- anyscale/client/README.md +14 -13
- anyscale/client/openapi_client/__init__.py +4 -4
- anyscale/client/openapi_client/api/default_api.py +395 -325
- anyscale/client/openapi_client/models/__init__.py +4 -4
- anyscale/client/openapi_client/models/aws_config.py +2 -2
- anyscale/client/openapi_client/models/baseimagesenum.py +76 -1
- anyscale/client/openapi_client/models/cloud_data_bucket_file_type.py +2 -1
- anyscale/client/openapi_client/models/cloud_data_bucket_presigned_url_request.py +31 -3
- anyscale/client/openapi_client/models/cloud_deployment.py +37 -36
- anyscale/client/openapi_client/models/create_resource_notification.py +31 -3
- anyscale/client/openapi_client/models/{decorated_cloud_deployment.py → decorated_cloud_resource.py} +124 -96
- anyscale/client/openapi_client/models/{clouddeployment_list_response.py → decoratedcloudresource_list_response.py} +15 -15
- anyscale/client/openapi_client/models/{clouddeployment_response.py → decoratedcloudresource_response.py} +11 -11
- anyscale/client/openapi_client/models/file_storage.py +4 -4
- anyscale/client/openapi_client/models/gcp_config.py +2 -2
- anyscale/client/openapi_client/models/ha_job_error_types.py +9 -2
- anyscale/client/openapi_client/models/object_storage.py +2 -2
- anyscale/client/openapi_client/models/{decoratedclouddeployment_response.py → presigned_url_response.py} +24 -22
- anyscale/client/openapi_client/models/production_job_event.py +31 -3
- anyscale/client/openapi_client/models/resource_alert_event_type.py +2 -1
- anyscale/client/openapi_client/models/resource_notification.py +29 -1
- anyscale/client/openapi_client/models/supportedbaseimagesenum.py +76 -1
- anyscale/client/openapi_client/models/workload_info.py +31 -3
- anyscale/client/openapi_client/models/workload_state_info.py +29 -1
- anyscale/cloud/models.py +39 -42
- anyscale/commands/cloud_commands.py +25 -23
- anyscale/commands/command_examples.py +10 -10
- anyscale/commands/exec_commands.py +12 -1
- anyscale/commands/list_commands.py +42 -12
- anyscale/commands/project_commands.py +23 -10
- anyscale/commands/schedule_commands.py +22 -11
- anyscale/commands/service_commands.py +11 -6
- anyscale/commands/util.py +94 -1
- anyscale/commands/workspace_commands.py +92 -38
- anyscale/compute_config/__init__.py +1 -1
- anyscale/compute_config/_private/compute_config_sdk.py +8 -11
- anyscale/compute_config/commands.py +3 -3
- anyscale/compute_config/models.py +30 -30
- anyscale/controllers/cloud_controller.py +306 -300
- anyscale/controllers/kubernetes_verifier.py +1 -1
- anyscale/job/_private/job_sdk.py +12 -12
- anyscale/job/models.py +1 -1
- anyscale/sdk/anyscale_client/models/baseimagesenum.py +76 -1
- anyscale/sdk/anyscale_client/models/supportedbaseimagesenum.py +76 -1
- anyscale/shared_anyscale_utils/latest_ray_version.py +1 -1
- anyscale/version.py +1 -1
- anyscale/workspace/commands.py +114 -23
- anyscale/workspace/models.py +3 -5
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/METADATA +1 -1
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/RECORD +64 -64
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/WHEEL +0 -0
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/entry_points.txt +0 -0
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/licenses/LICENSE +0 -0
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/licenses/NOTICE +0 -0
- {anyscale-0.26.52.dist-info → anyscale-0.26.54.dist-info}/top_level.txt +0 -0
@@ -11,8 +11,7 @@ from anyscale.cli_logger import BlockLogger
|
|
11
11
|
from anyscale.client.openapi_client.models.execute_interactive_command_options import (
|
12
12
|
ExecuteInteractiveCommandOptions,
|
13
13
|
)
|
14
|
-
from anyscale.commands import
|
15
|
-
from anyscale.commands.util import LegacyAnyscaleCommand
|
14
|
+
from anyscale.commands.util import DeprecatedAnyscaleCommand, LegacyAnyscaleCommand
|
16
15
|
from anyscale.controllers.cluster_controller import ClusterController
|
17
16
|
from anyscale.controllers.workspace_controller import WorkspaceController
|
18
17
|
from anyscale.project_utils import find_project_root
|
@@ -34,10 +33,11 @@ def workspace_cli() -> None:
|
|
34
33
|
|
35
34
|
@workspace_cli.command(
|
36
35
|
name="create",
|
37
|
-
help="Create a workspace on Anyscale.",
|
38
|
-
cls=
|
39
|
-
|
40
|
-
|
36
|
+
help="[DEPRECATED - use 'workspace_v2 create' instead] Create a workspace on Anyscale.",
|
37
|
+
cls=DeprecatedAnyscaleCommand,
|
38
|
+
removal_date="2025-10-01",
|
39
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
40
|
+
alternative="use 'anyscale workspace_v2 create' instead",
|
41
41
|
)
|
42
42
|
@click.option(
|
43
43
|
"--name", "-n", required=True, help="Name of the workspace to create.",
|
@@ -85,6 +85,11 @@ def create( # noqa: PLR0913
|
|
85
85
|
ray_version: str,
|
86
86
|
compute_config_id: str,
|
87
87
|
) -> None:
|
88
|
+
"""Create a workspace on Anyscale.
|
89
|
+
|
90
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
91
|
+
Use 'anyscale workspace_v2 create' instead.
|
92
|
+
"""
|
88
93
|
if cluster_env_build_id is None and docker is None:
|
89
94
|
raise click.ClickException(
|
90
95
|
"Please specify one of `--docker` or `--cluster-env-build-id`."
|
@@ -121,15 +126,21 @@ def create( # noqa: PLR0913
|
|
121
126
|
|
122
127
|
@workspace_cli.command(
|
123
128
|
name="start",
|
124
|
-
help="Start an existing workspace on Anyscale.",
|
125
|
-
cls=
|
126
|
-
|
127
|
-
|
129
|
+
help="[DEPRECATED - use 'workspace_v2 start' instead] Start an existing workspace on Anyscale.",
|
130
|
+
cls=DeprecatedAnyscaleCommand,
|
131
|
+
removal_date="2025-10-01",
|
132
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
133
|
+
alternative="use 'anyscale workspace_v2 start' instead",
|
128
134
|
)
|
129
135
|
@click.option(
|
130
136
|
"--name", "-n", required=True, help="Name of existing workspace to start.",
|
131
137
|
)
|
132
138
|
def start(name: str) -> None:
|
139
|
+
"""Start an existing workspace on Anyscale.
|
140
|
+
|
141
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
142
|
+
Use 'anyscale workspace_v2 start' instead.
|
143
|
+
"""
|
133
144
|
cluster_controller = ClusterController()
|
134
145
|
|
135
146
|
workspace = get_workspace_from_name(name)
|
@@ -154,15 +165,21 @@ def start(name: str) -> None:
|
|
154
165
|
|
155
166
|
@workspace_cli.command(
|
156
167
|
name="terminate",
|
157
|
-
help="Terminate a workspace on Anyscale.",
|
158
|
-
cls=
|
159
|
-
|
160
|
-
|
168
|
+
help="[DEPRECATED - use 'workspace_v2 terminate' instead] Terminate a workspace on Anyscale.",
|
169
|
+
cls=DeprecatedAnyscaleCommand,
|
170
|
+
removal_date="2025-10-01",
|
171
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
172
|
+
alternative="use 'anyscale workspace_v2 terminate' instead",
|
161
173
|
)
|
162
174
|
@click.option(
|
163
175
|
"--name", "-n", required=True, help="Name of existing workspace to terminate.",
|
164
176
|
)
|
165
177
|
def terminate(name: str) -> None:
|
178
|
+
"""Terminate a workspace on Anyscale.
|
179
|
+
|
180
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
181
|
+
Use 'anyscale workspace_v2 terminate' instead.
|
182
|
+
"""
|
166
183
|
cluster_controller = ClusterController()
|
167
184
|
workspace = get_workspace_from_name(name)
|
168
185
|
cluster_id = workspace.cluster_id
|
@@ -179,9 +196,11 @@ def terminate(name: str) -> None:
|
|
179
196
|
|
180
197
|
@workspace_cli.command(
|
181
198
|
name="clone",
|
182
|
-
help="Clone a workspace on Anyscale.",
|
183
|
-
cls=
|
184
|
-
|
199
|
+
help="[DEPRECATED - use workspace_v2 clone functionality instead] Clone a workspace on Anyscale.",
|
200
|
+
cls=DeprecatedAnyscaleCommand,
|
201
|
+
removal_date="2025-10-01",
|
202
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
203
|
+
alternative="use workspace_v2 clone functionality instead",
|
185
204
|
)
|
186
205
|
@click.option(
|
187
206
|
"--name", "-n", required=True, help="Name of existing workspace to clone.",
|
@@ -190,8 +209,10 @@ def terminate(name: str) -> None:
|
|
190
209
|
"--verbose", "-v", required=False, is_flag=True, default=False, help="Verbose mode"
|
191
210
|
)
|
192
211
|
def clone(name: str, verbose: bool) -> None:
|
193
|
-
"""
|
194
|
-
|
212
|
+
"""Clone the workspace to a local dir whose name is the name of the workspace.
|
213
|
+
|
214
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
215
|
+
Use workspace_v2 clone functionality instead.
|
195
216
|
"""
|
196
217
|
_check_local()
|
197
218
|
|
@@ -207,13 +228,24 @@ def clone(name: str, verbose: bool) -> None:
|
|
207
228
|
_do_pull(pull_git_state=True, verbose=verbose)
|
208
229
|
|
209
230
|
|
210
|
-
@workspace_cli.command(
|
231
|
+
@workspace_cli.command(
|
232
|
+
name="activate",
|
233
|
+
help="[DEPRECATED - no longer needed] Activate a workspace.",
|
234
|
+
cls=DeprecatedAnyscaleCommand,
|
235
|
+
removal_date="2025-10-01",
|
236
|
+
deprecation_message="The workspace v1 activate command is no longer needed",
|
237
|
+
alternative="use workspace_v2 commands which don't require activation",
|
238
|
+
)
|
211
239
|
@click.argument(
|
212
240
|
"name", required=True, default=None,
|
213
241
|
)
|
214
242
|
def activate(name: str) -> None:
|
215
243
|
"""Activate a workspace.
|
216
244
|
|
245
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
246
|
+
The workspace v1 activate command is no longer needed.
|
247
|
+
Use workspace_v2 commands which don't require activation.
|
248
|
+
|
217
249
|
If the current directory is already a part of a workspace, change the workspace.
|
218
250
|
Else, setup a new workspace rooted at the current directory
|
219
251
|
|
@@ -239,10 +271,11 @@ def activate(name: str) -> None:
|
|
239
271
|
|
240
272
|
@workspace_cli.command(
|
241
273
|
name="pull",
|
242
|
-
help="Pull files from a workspace on Anyscale.",
|
243
|
-
cls=
|
244
|
-
|
245
|
-
|
274
|
+
help="[DEPRECATED - use 'workspace_v2 pull' instead] Pull files from a workspace on Anyscale.",
|
275
|
+
cls=DeprecatedAnyscaleCommand,
|
276
|
+
removal_date="2025-10-01",
|
277
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
278
|
+
alternative="use 'anyscale workspace_v2 pull' instead",
|
246
279
|
)
|
247
280
|
@click.option(
|
248
281
|
"--pull-git-state",
|
@@ -252,6 +285,11 @@ def activate(name: str) -> None:
|
|
252
285
|
help="Also pull git state. This will add additional overhead.",
|
253
286
|
)
|
254
287
|
def pull(pull_git_state) -> None:
|
288
|
+
"""Pull files from a workspace on Anyscale.
|
289
|
+
|
290
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
291
|
+
Use 'anyscale workspace_v2 pull' instead.
|
292
|
+
"""
|
255
293
|
_check_local()
|
256
294
|
_check_workspace()
|
257
295
|
_do_pull(pull_git_state)
|
@@ -259,10 +297,11 @@ def pull(pull_git_state) -> None:
|
|
259
297
|
|
260
298
|
@workspace_cli.command(
|
261
299
|
name="push",
|
262
|
-
help="Push files to a workspace on Anyscale.",
|
263
|
-
cls=
|
264
|
-
|
265
|
-
|
300
|
+
help="[DEPRECATED - use 'workspace_v2 push' instead] Push files to a workspace on Anyscale.",
|
301
|
+
cls=DeprecatedAnyscaleCommand,
|
302
|
+
removal_date="2025-10-01",
|
303
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
304
|
+
alternative="use 'anyscale workspace_v2 push' instead",
|
266
305
|
)
|
267
306
|
@click.option(
|
268
307
|
"--push-git-state",
|
@@ -272,6 +311,11 @@ def pull(pull_git_state) -> None:
|
|
272
311
|
help="Also push git state. This is currently unoptimized and will be very slow.",
|
273
312
|
)
|
274
313
|
def push(push_git_state) -> None:
|
314
|
+
"""Push files to a workspace on Anyscale.
|
315
|
+
|
316
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
317
|
+
Use 'anyscale workspace_v2 push' instead.
|
318
|
+
"""
|
275
319
|
_check_local()
|
276
320
|
_check_workspace()
|
277
321
|
_do_push(push_git_state)
|
@@ -279,10 +323,11 @@ def push(push_git_state) -> None:
|
|
279
323
|
|
280
324
|
@workspace_cli.command(
|
281
325
|
name="run",
|
282
|
-
help="Run a command in a workspace, syncing files first if needed.",
|
283
|
-
cls=
|
284
|
-
|
285
|
-
|
326
|
+
help="[DEPRECATED - use 'workspace_v2 run_command' instead] Run a command in a workspace, syncing files first if needed.",
|
327
|
+
cls=DeprecatedAnyscaleCommand,
|
328
|
+
removal_date="2025-10-01",
|
329
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
330
|
+
alternative="use 'anyscale workspace_v2 run_command' instead",
|
286
331
|
)
|
287
332
|
@click.argument("command", required=True)
|
288
333
|
@click.option(
|
@@ -310,6 +355,11 @@ def push(push_git_state) -> None:
|
|
310
355
|
help="Whether to skip pushing files prior to running the command.",
|
311
356
|
)
|
312
357
|
def run(command: str, web_terminal: bool, as_job: bool, no_push: bool,) -> None:
|
358
|
+
"""Run a command in a workspace, syncing files first if needed.
|
359
|
+
|
360
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
361
|
+
Use 'anyscale workspace_v2 run_command' instead.
|
362
|
+
"""
|
313
363
|
_check_local()
|
314
364
|
_check_workspace()
|
315
365
|
if as_job:
|
@@ -337,17 +387,20 @@ def run(command: str, web_terminal: bool, as_job: bool, no_push: bool,) -> None:
|
|
337
387
|
|
338
388
|
@workspace_cli.command(
|
339
389
|
name="ssh",
|
340
|
-
help="ssh into a workspace, you can also pass args to the ssh command. E.g. 'anyscale workspace ssh -- -L 8888:localhost:8888",
|
341
|
-
cls=
|
342
|
-
|
343
|
-
|
390
|
+
help="[DEPRECATED - use 'workspace_v2 ssh' instead] ssh into a workspace, you can also pass args to the ssh command. E.g. 'anyscale workspace ssh -- -L 8888:localhost:8888",
|
391
|
+
cls=DeprecatedAnyscaleCommand,
|
392
|
+
removal_date="2025-10-01",
|
393
|
+
deprecation_message="The workspace v1 CLI is being replaced",
|
394
|
+
alternative="use 'anyscale workspace_v2 ssh' instead",
|
344
395
|
)
|
345
396
|
@click.argument(
|
346
397
|
"args", nargs=-1, required=False, type=click.UNPROCESSED,
|
347
398
|
)
|
348
399
|
def ssh(args: Tuple[str]) -> None:
|
349
|
-
"""
|
350
|
-
|
400
|
+
"""ssh into a running workspace.
|
401
|
+
|
402
|
+
DEPRECATED: This command will be removed on 2025-10-01.
|
403
|
+
Use 'anyscale workspace_v2 ssh' instead.
|
351
404
|
"""
|
352
405
|
_check_local()
|
353
406
|
|
@@ -364,6 +417,7 @@ def list_command() -> None:
|
|
364
417
|
workspace_controller.list()
|
365
418
|
|
366
419
|
|
420
|
+
# TODO(vigneshka): Migrate to v2 if there is usage, then deprecate
|
367
421
|
@workspace_cli.command(name="cp", cls=LegacyAnyscaleCommand, is_limited_support=True)
|
368
422
|
@click.argument(
|
369
423
|
"remote_path",
|
@@ -20,7 +20,7 @@ from anyscale.compute_config.models import (
|
|
20
20
|
ComputeConfigVersion,
|
21
21
|
HeadNodeConfig,
|
22
22
|
MarketType,
|
23
|
-
|
23
|
+
MultiResourceComputeConfig,
|
24
24
|
WorkerNodeGroupConfig,
|
25
25
|
)
|
26
26
|
from anyscale.sdk.anyscale_client.models import ClusterComputeConfig
|
@@ -148,7 +148,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
148
148
|
flags["max_resources"] = compute_config.max_resources
|
149
149
|
|
150
150
|
return CloudDeploymentComputeConfig(
|
151
|
-
cloud_deployment=compute_config.
|
151
|
+
cloud_deployment=compute_config.cloud_resource,
|
152
152
|
allowed_azs=compute_config.zones,
|
153
153
|
head_node_type=self._convert_head_node_config_to_api_model(
|
154
154
|
compute_config.head_node,
|
@@ -180,7 +180,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
180
180
|
"The latest version tag will be generated and returned."
|
181
181
|
)
|
182
182
|
|
183
|
-
if isinstance(compute_config,
|
183
|
+
if isinstance(compute_config, MultiResourceComputeConfig):
|
184
184
|
return self.create_multi_deployment_compute_config(
|
185
185
|
compute_config, name=name
|
186
186
|
)
|
@@ -226,10 +226,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
226
226
|
return full_name, compute_config_id
|
227
227
|
|
228
228
|
def create_multi_deployment_compute_config(
|
229
|
-
self,
|
230
|
-
compute_config: MultiDeploymentComputeConfig,
|
231
|
-
*,
|
232
|
-
name: Optional[str] = None,
|
229
|
+
self, compute_config: MultiResourceComputeConfig, *, name: Optional[str] = None,
|
233
230
|
) -> Tuple[str, str]:
|
234
231
|
"""Register the provided multi-deployment compute config and return its internal ID."""
|
235
232
|
# Returns the default cloud if user-provided cloud is not specified (`None`).
|
@@ -381,7 +378,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
381
378
|
|
382
379
|
return configs
|
383
380
|
|
384
|
-
def
|
381
|
+
def _convert_cloud_deployment_compute_config_api_model_to_single_resource_compute_config(
|
385
382
|
self, cloud_name: str, api_model: CloudDeploymentComputeConfig,
|
386
383
|
) -> ComputeConfig:
|
387
384
|
worker_nodes = None
|
@@ -416,7 +413,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
416
413
|
|
417
414
|
return ComputeConfig(
|
418
415
|
cloud=cloud_name,
|
419
|
-
|
416
|
+
cloud_resource=api_model.cloud_deployment,
|
420
417
|
zones=zones,
|
421
418
|
advanced_instance_config=api_model.advanced_configurations_json or None,
|
422
419
|
enable_cross_zone_scaling=enable_cross_zone_scaling,
|
@@ -443,7 +440,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
443
440
|
configs = None
|
444
441
|
if api_model_config.deployment_configs:
|
445
442
|
configs = [
|
446
|
-
self.
|
443
|
+
self._convert_cloud_deployment_compute_config_api_model_to_single_resource_compute_config(
|
447
444
|
cloud.name, config
|
448
445
|
)
|
449
446
|
for config in api_model_config.deployment_configs
|
@@ -458,7 +455,7 @@ class PrivateComputeConfigSDK(BaseSDK):
|
|
458
455
|
return ComputeConfigVersion(
|
459
456
|
name=f"{api_model.name}:{api_model.version}",
|
460
457
|
id=api_model.id,
|
461
|
-
config=
|
458
|
+
config=MultiResourceComputeConfig(cloud=cloud.name, configs=configs),
|
462
459
|
)
|
463
460
|
|
464
461
|
# If there are no deployment configs, this is a compute config for a single cloud deployment - parse the top-level fields.
|
@@ -34,10 +34,10 @@ single_deployment_compute_config = ComputeConfig(
|
|
34
34
|
)
|
35
35
|
full_name: str = anyscale.compute_config.create(single_deployment_compute_config, name="my-single-deployment-compute-config")
|
36
36
|
|
37
|
-
multi_deployment_compute_config =
|
37
|
+
multi_deployment_compute_config = MultiResourceComputeConfig(
|
38
38
|
configs=[
|
39
39
|
ComputeConfig(
|
40
|
-
|
40
|
+
cloud_resource="vm-aws-us-west-1",
|
41
41
|
head_node=HeadNodeConfig(
|
42
42
|
instance_type="m5.2xlarge",
|
43
43
|
),
|
@@ -50,7 +50,7 @@ multi_deployment_compute_config = MultiDeploymentComputeConfig(
|
|
50
50
|
],
|
51
51
|
),
|
52
52
|
ComputeConfig(
|
53
|
-
|
53
|
+
cloud_resource="vm-aws-us-west-2",
|
54
54
|
head_node=HeadNodeConfig(
|
55
55
|
instance_type="m5.2xlarge",
|
56
56
|
),
|
@@ -315,7 +315,7 @@ worker_nodes:
|
|
315
315
|
|
316
316
|
@dataclass(frozen=True)
|
317
317
|
class ComputeConfig(ModelBase):
|
318
|
-
"""Compute configuration for instance types and cloud resources for a cluster with a single cloud
|
318
|
+
"""Compute configuration for instance types and cloud resources for a cluster with a single cloud resource."""
|
319
319
|
|
320
320
|
__doc_py_example__ = """
|
321
321
|
from anyscale.compute_config.models import (
|
@@ -417,18 +417,18 @@ advanced_instance_config: # (Optional) Defaults to no advanced configurations.
|
|
417
417
|
if cloud is not None and not isinstance(cloud, str):
|
418
418
|
raise TypeError("'cloud' must be a string")
|
419
419
|
|
420
|
-
|
420
|
+
cloud_resource: Optional[str] = field(
|
421
421
|
default=None,
|
422
422
|
repr=False,
|
423
423
|
metadata={
|
424
|
-
"docstring": "The cloud
|
424
|
+
"docstring": "The cloud resource to use for this workload. Defaults to the primary cloud resource of the Cloud.",
|
425
425
|
"customer_hosted_only": True,
|
426
426
|
},
|
427
427
|
)
|
428
428
|
|
429
|
-
def
|
430
|
-
if
|
431
|
-
raise TypeError("'
|
429
|
+
def _validate_cloud_resource(self, cloud_resource: Optional[str]):
|
430
|
+
if cloud_resource is not None and not isinstance(cloud_resource, str):
|
431
|
+
raise TypeError("'cloud_resource' must be a string")
|
432
432
|
|
433
433
|
head_node: Union[HeadNodeConfig, Dict, None] = field(
|
434
434
|
default=None,
|
@@ -600,18 +600,18 @@ advanced_instance_config: # (Optional) Defaults to no advanced configurations.
|
|
600
600
|
|
601
601
|
|
602
602
|
@dataclass(frozen=True)
|
603
|
-
class
|
604
|
-
"""EXPERIMENTAL. Compute configuration for a cluster with multiple possible cloud
|
603
|
+
class MultiResourceComputeConfig(ModelBase):
|
604
|
+
"""EXPERIMENTAL. Compute configuration for a cluster with multiple possible cloud resources."""
|
605
605
|
|
606
606
|
__doc_py_example__ = """
|
607
607
|
from anyscale.compute_config.models import (
|
608
|
-
|
608
|
+
MultiResourceComputeConfig, ComputeConfig, HeadNodeConfig, WorkerNodeGroupConfig
|
609
609
|
)
|
610
|
-
config =
|
610
|
+
config = MultiResourceComputeConfig(
|
611
611
|
cloud="my-cloud",
|
612
612
|
configs=[
|
613
613
|
ComputeConfig(
|
614
|
-
|
614
|
+
cloud_resource="vm-aws-us-west-1",
|
615
615
|
head_node=HeadNodeConfig(
|
616
616
|
instance_type="m5.2xlarge",
|
617
617
|
),
|
@@ -624,7 +624,7 @@ config = MultiDeploymentComputeConfig(
|
|
624
624
|
],
|
625
625
|
),
|
626
626
|
ComputeConfig(
|
627
|
-
|
627
|
+
cloud_resource="vm-aws-us-west-2",
|
628
628
|
head_node=HeadNodeConfig(
|
629
629
|
instance_type="m5.2xlarge",
|
630
630
|
),
|
@@ -643,14 +643,14 @@ config = MultiDeploymentComputeConfig(
|
|
643
643
|
__doc_yaml_example__ = """
|
644
644
|
cloud: my-cloud
|
645
645
|
configs:
|
646
|
-
-
|
646
|
+
- cloud_resource: vm-aws-us-west-1
|
647
647
|
head_node:
|
648
648
|
instance_type: m5.2xlarge
|
649
649
|
worker_nodes:
|
650
650
|
- instance_type: m5.4xlarge
|
651
651
|
min_nodes: 1
|
652
652
|
max_nodes: 10
|
653
|
-
-
|
653
|
+
- cloud_resource: vm-aws-us-west-2
|
654
654
|
head_node:
|
655
655
|
instance_type: m5.2xlarge
|
656
656
|
worker_nodes:
|
@@ -673,7 +673,7 @@ configs:
|
|
673
673
|
default_factory=list,
|
674
674
|
repr=False,
|
675
675
|
metadata={
|
676
|
-
"docstring": "List of compute configurations, one for each cloud
|
676
|
+
"docstring": "List of compute configurations, one for each cloud resource.",
|
677
677
|
"customer_hosted_only": True,
|
678
678
|
},
|
679
679
|
)
|
@@ -690,7 +690,7 @@ configs:
|
|
690
690
|
|
691
691
|
config_models: List[ComputeConfig] = []
|
692
692
|
unique_clouds = set()
|
693
|
-
|
693
|
+
unique_resources = set()
|
694
694
|
for config in configs:
|
695
695
|
if isinstance(config, dict):
|
696
696
|
config = ComputeConfig.from_dict(config)
|
@@ -701,14 +701,14 @@ configs:
|
|
701
701
|
if config.cloud:
|
702
702
|
unique_clouds.add(config.cloud)
|
703
703
|
|
704
|
-
|
704
|
+
unique_resources.add(config.cloud_resource)
|
705
705
|
|
706
706
|
if len(unique_clouds) > 1:
|
707
707
|
raise ValueError("'cloud' must be the same for all configs.")
|
708
708
|
|
709
|
-
if len(
|
709
|
+
if len(unique_resources) != len(configs):
|
710
710
|
raise ValueError(
|
711
|
-
"'
|
711
|
+
"'cloud_resource' must be unique for each compute configuration."
|
712
712
|
)
|
713
713
|
|
714
714
|
if len(configs) == 0:
|
@@ -719,14 +719,14 @@ configs:
|
|
719
719
|
return config_models
|
720
720
|
|
721
721
|
|
722
|
-
ComputeConfigType = Union[ComputeConfig,
|
722
|
+
ComputeConfigType = Union[ComputeConfig, MultiResourceComputeConfig]
|
723
723
|
|
724
724
|
|
725
725
|
def compute_config_type_from_yaml(config_file: str) -> ComputeConfigType:
|
726
726
|
"""
|
727
|
-
Parse a YAML compute config file into either a ComputeConfig or
|
727
|
+
Parse a YAML compute config file into either a ComputeConfig or MultiResourceComputeConfig.
|
728
728
|
"""
|
729
|
-
error_message = f"Could not parse config file '{config_file}' as a ComputeConfig or
|
729
|
+
error_message = f"Could not parse config file '{config_file}' as a ComputeConfig or MultiResourceComputeConfig:\n"
|
730
730
|
|
731
731
|
try:
|
732
732
|
return ComputeConfig.from_yaml(config_file)
|
@@ -734,18 +734,18 @@ def compute_config_type_from_yaml(config_file: str) -> ComputeConfigType:
|
|
734
734
|
error_message += f"ComputeConfig: {e}\n"
|
735
735
|
|
736
736
|
try:
|
737
|
-
return
|
737
|
+
return MultiResourceComputeConfig.from_yaml(config_file)
|
738
738
|
except Exception as e: # noqa: BLE001
|
739
|
-
error_message += f"
|
739
|
+
error_message += f"MultiResourceComputeConfig: {e}\n"
|
740
740
|
|
741
741
|
raise TypeError(error_message.rstrip())
|
742
742
|
|
743
743
|
|
744
744
|
def compute_config_type_from_dict(config_dict: Dict) -> ComputeConfigType:
|
745
745
|
"""
|
746
|
-
Parse a compute config dict into either a ComputeConfig or
|
746
|
+
Parse a compute config dict into either a ComputeConfig or MultiResourceComputeConfig.
|
747
747
|
"""
|
748
|
-
error_message = f"Could not parse config dict '{config_dict}' as a ComputeConfig or
|
748
|
+
error_message = f"Could not parse config dict '{config_dict}' as a ComputeConfig or MultiResourceComputeConfig:\n"
|
749
749
|
|
750
750
|
try:
|
751
751
|
return ComputeConfig.from_dict(config_dict)
|
@@ -753,9 +753,9 @@ def compute_config_type_from_dict(config_dict: Dict) -> ComputeConfigType:
|
|
753
753
|
error_message += f"ComputeConfig: {e}\n"
|
754
754
|
|
755
755
|
try:
|
756
|
-
return
|
756
|
+
return MultiResourceComputeConfig.from_dict(config_dict)
|
757
757
|
except Exception as e: # noqa: BLE001
|
758
|
-
error_message += f"
|
758
|
+
error_message += f"MultiResourceComputeConfig: {e}\n"
|
759
759
|
|
760
760
|
raise TypeError(error_message.rstrip())
|
761
761
|
|
@@ -819,8 +819,8 @@ config:
|
|
819
819
|
|
820
820
|
def _validate_config(self, config: Optional[ComputeConfigType]):
|
821
821
|
if config is not None and not isinstance(
|
822
|
-
config, (ComputeConfig,
|
822
|
+
config, (ComputeConfig, MultiResourceComputeConfig)
|
823
823
|
):
|
824
824
|
raise TypeError(
|
825
|
-
"'config' must be a ComputeConfig or
|
825
|
+
"'config' must be a ComputeConfig or MultiResourceComputeConfig"
|
826
826
|
)
|